1*02e95f1aSMarcin Radomski /* plugin.h 2*02e95f1aSMarcin Radomski ** Copyright (c) 2019-2020, The Linux Foundation. 3*02e95f1aSMarcin Radomski ** 4*02e95f1aSMarcin Radomski ** Redistribution and use in source and binary forms, with or without 5*02e95f1aSMarcin Radomski ** modification, are permitted provided that the following conditions are 6*02e95f1aSMarcin Radomski ** met: 7*02e95f1aSMarcin Radomski ** * Redistributions of source code must retain the above copyright 8*02e95f1aSMarcin Radomski ** notice, this list of conditions and the following disclaimer. 9*02e95f1aSMarcin Radomski ** * Redistributions in binary form must reproduce the above 10*02e95f1aSMarcin Radomski ** copyright notice, this list of conditions and the following 11*02e95f1aSMarcin Radomski ** disclaimer in the documentation and/or other materials provided 12*02e95f1aSMarcin Radomski ** with the distribution. 13*02e95f1aSMarcin Radomski ** * Neither the name of The Linux Foundation nor the names of its 14*02e95f1aSMarcin Radomski ** contributors may be used to endorse or promote products derived 15*02e95f1aSMarcin Radomski ** from this software without specific prior written permission. 16*02e95f1aSMarcin Radomski ** 17*02e95f1aSMarcin Radomski ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18*02e95f1aSMarcin Radomski ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19*02e95f1aSMarcin Radomski ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20*02e95f1aSMarcin Radomski ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21*02e95f1aSMarcin Radomski ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22*02e95f1aSMarcin Radomski ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23*02e95f1aSMarcin Radomski ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24*02e95f1aSMarcin Radomski ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25*02e95f1aSMarcin Radomski ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26*02e95f1aSMarcin Radomski ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27*02e95f1aSMarcin Radomski ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*02e95f1aSMarcin Radomski **/ 29*02e95f1aSMarcin Radomski 30*02e95f1aSMarcin Radomski #ifndef TINYALSA_PLUGIN_H 31*02e95f1aSMarcin Radomski #define TINYALSA_PLUGIN_H 32*02e95f1aSMarcin Radomski 33*02e95f1aSMarcin Radomski #include <poll.h> 34*02e95f1aSMarcin Radomski #include <stdint.h> 35*02e95f1aSMarcin Radomski #include <stdlib.h> 36*02e95f1aSMarcin Radomski #include <sys/types.h> 37*02e95f1aSMarcin Radomski #include <time.h> 38*02e95f1aSMarcin Radomski 39*02e95f1aSMarcin Radomski #include <sound/asound.h> 40*02e95f1aSMarcin Radomski 41*02e95f1aSMarcin Radomski /* static initializers */ 42*02e95f1aSMarcin Radomski 43*02e95f1aSMarcin Radomski #define SND_VALUE_ENUM(etexts, eitems) \ 44*02e95f1aSMarcin Radomski {.texts = etexts, .items = eitems} 45*02e95f1aSMarcin Radomski 46*02e95f1aSMarcin Radomski #define SND_VALUE_BYTES(csize) \ 47*02e95f1aSMarcin Radomski {.size = csize } 48*02e95f1aSMarcin Radomski 49*02e95f1aSMarcin Radomski #define SND_VALUE_INTEGER(icount, imin, imax, istep) \ 50*02e95f1aSMarcin Radomski {.count = icount, .min = imin, .max = imax, .step = istep } 51*02e95f1aSMarcin Radomski 52*02e95f1aSMarcin Radomski #define SND_VALUE_TLV_BYTES(csize, cget, cput) \ 53*02e95f1aSMarcin Radomski {.size = csize, .get = cget, .put = cput } 54*02e95f1aSMarcin Radomski 55*02e95f1aSMarcin Radomski /* pointer based initializers */ 56*02e95f1aSMarcin Radomski #define INIT_SND_CONTROL_INTEGER(c, cname, cget, cput, cint, pval, pdata) \ 57*02e95f1aSMarcin Radomski { \ 58*02e95f1aSMarcin Radomski c->iface = SNDRV_CTL_ELEM_IFACE_MIXER; \ 59*02e95f1aSMarcin Radomski c->access = SNDRV_CTL_ELEM_ACCESS_READWRITE; \ 60*02e95f1aSMarcin Radomski c->type = SNDRV_CTL_ELEM_TYPE_INTEGER; \ 61*02e95f1aSMarcin Radomski c->name = cname; c->value = &cint; c->get = cget; c->put = cput; \ 62*02e95f1aSMarcin Radomski c->private_value = pval; c->private_data = pdata; \ 63*02e95f1aSMarcin Radomski } 64*02e95f1aSMarcin Radomski 65*02e95f1aSMarcin Radomski #define INIT_SND_CONTROL_BYTES(c, cname, cget, cput, cint, pval, pdata) \ 66*02e95f1aSMarcin Radomski { \ 67*02e95f1aSMarcin Radomski c->iface = SNDRV_CTL_ELEM_IFACE_MIXER; \ 68*02e95f1aSMarcin Radomski c->access = SNDRV_CTL_ELEM_ACCESS_READWRITE; \ 69*02e95f1aSMarcin Radomski c->type = SNDRV_CTL_ELEM_TYPE_BYTES; \ 70*02e95f1aSMarcin Radomski c->name = cname; c->value = &cint; c->get = cget; c->put = cput; \ 71*02e95f1aSMarcin Radomski c->private_value = pval; c->private_data = pdata; \ 72*02e95f1aSMarcin Radomski } 73*02e95f1aSMarcin Radomski 74*02e95f1aSMarcin Radomski #define INIT_SND_CONTROL_ENUM(c, cname, cget, cput, cenum, pval, pdata) \ 75*02e95f1aSMarcin Radomski { \ 76*02e95f1aSMarcin Radomski c->iface = SNDRV_CTL_ELEM_IFACE_MIXER; \ 77*02e95f1aSMarcin Radomski c->access = SNDRV_CTL_ELEM_ACCESS_READWRITE; \ 78*02e95f1aSMarcin Radomski c->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; \ 79*02e95f1aSMarcin Radomski c->name = cname; c->value = cenum; c->get = cget; c->put = cput; \ 80*02e95f1aSMarcin Radomski c->private_value = pval; c->private_data = pdata; \ 81*02e95f1aSMarcin Radomski } 82*02e95f1aSMarcin Radomski 83*02e95f1aSMarcin Radomski #define INIT_SND_CONTROL_TLV_BYTES(c, cname, cbytes, priv_val, priv_data) \ 84*02e95f1aSMarcin Radomski { \ 85*02e95f1aSMarcin Radomski c->iface = SNDRV_CTL_ELEM_IFACE_MIXER; \ 86*02e95f1aSMarcin Radomski c->access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE; \ 87*02e95f1aSMarcin Radomski c->type = SNDRV_CTL_ELEM_TYPE_BYTES; \ 88*02e95f1aSMarcin Radomski c->name = cname; c->value = &cbytes; \ 89*02e95f1aSMarcin Radomski c->private_value = priv_val; c->private_data = priv_data; \ 90*02e95f1aSMarcin Radomski } 91*02e95f1aSMarcin Radomski 92*02e95f1aSMarcin Radomski struct mixer_plugin; 93*02e95f1aSMarcin Radomski struct pcm_plugin; 94*02e95f1aSMarcin Radomski struct snd_node; 95*02e95f1aSMarcin Radomski 96*02e95f1aSMarcin Radomski /** Operations that are required to be registered by the plugin. 97*02e95f1aSMarcin Radomski * @ingroup libtinyalsa-pcm 98*02e95f1aSMarcin Radomski */ 99*02e95f1aSMarcin Radomski struct pcm_plugin_ops { 100*02e95f1aSMarcin Radomski /** open the pcm plugin */ 101*02e95f1aSMarcin Radomski int (*open) (struct pcm_plugin **plugin, unsigned int card, 102*02e95f1aSMarcin Radomski unsigned int device, unsigned int flags); 103*02e95f1aSMarcin Radomski /** close the pcm plugin */ 104*02e95f1aSMarcin Radomski int (*close) (struct pcm_plugin *plugin); 105*02e95f1aSMarcin Radomski /** Set the PCM hardware parameters to the plugin */ 106*02e95f1aSMarcin Radomski int (*hw_params) (struct pcm_plugin *plugin, 107*02e95f1aSMarcin Radomski struct snd_pcm_hw_params *params); 108*02e95f1aSMarcin Radomski /** Set the PCM software parameters to the plugin */ 109*02e95f1aSMarcin Radomski int (*sw_params) (struct pcm_plugin *plugin, 110*02e95f1aSMarcin Radomski struct snd_pcm_sw_params *params); 111*02e95f1aSMarcin Radomski /** Synchronize the pointer */ 112*02e95f1aSMarcin Radomski int (*sync_ptr) (struct pcm_plugin *plugin, 113*02e95f1aSMarcin Radomski struct snd_pcm_sync_ptr *sync_ptr); 114*02e95f1aSMarcin Radomski /** Write frames to plugin to be rendered to output */ 115*02e95f1aSMarcin Radomski int (*writei_frames) (struct pcm_plugin *plugin, 116*02e95f1aSMarcin Radomski struct snd_xferi *x); 117*02e95f1aSMarcin Radomski /** Read frames from plugin captured from input */ 118*02e95f1aSMarcin Radomski int (*readi_frames) (struct pcm_plugin *plugin, 119*02e95f1aSMarcin Radomski struct snd_xferi *x); 120*02e95f1aSMarcin Radomski /** Obtain the timestamp for the PCM */ 121*02e95f1aSMarcin Radomski int (*ttstamp) (struct pcm_plugin *plugin, 122*02e95f1aSMarcin Radomski int *tstamp); 123*02e95f1aSMarcin Radomski /** Prepare the plugin for data transfer */ 124*02e95f1aSMarcin Radomski int (*prepare) (struct pcm_plugin *plugin); 125*02e95f1aSMarcin Radomski /** Start data transfer from/to the plugin */ 126*02e95f1aSMarcin Radomski int (*start) (struct pcm_plugin *plugin); 127*02e95f1aSMarcin Radomski /** Signal the plugin to drain PCM */ 128*02e95f1aSMarcin Radomski int (*drain) (struct pcm_plugin *plugin); 129*02e95f1aSMarcin Radomski /** Stop a PCM dropping pending frames if drain() is NOT called. 130*02e95f1aSMarcin Radomski * Stop a PCM preserving pending frames if drain() is called. */ 131*02e95f1aSMarcin Radomski int (*drop) (struct pcm_plugin *plugin); 132*02e95f1aSMarcin Radomski /** Any custom or alsa specific ioctl implementation */ 133*02e95f1aSMarcin Radomski int (*ioctl) (struct pcm_plugin *plugin, 134*02e95f1aSMarcin Radomski int cmd, void *arg); 135*02e95f1aSMarcin Radomski void *(*mmap) (struct pcm_plugin *plugin, void *addr, size_t length, 136*02e95f1aSMarcin Radomski int prot, int flags, off_t offset); 137*02e95f1aSMarcin Radomski int (*munmap) (struct pcm_plugin *plugin, void *addr, size_t length); 138*02e95f1aSMarcin Radomski int (*poll) (struct pcm_plugin *plugin, struct pollfd *pfd, nfds_t nfds, 139*02e95f1aSMarcin Radomski int timeout); 140*02e95f1aSMarcin Radomski }; 141*02e95f1aSMarcin Radomski 142*02e95f1aSMarcin Radomski /** Minimum and maximum values for hardware parameter constraints. 143*02e95f1aSMarcin Radomski * @ingroup libtinyalsa-pcm 144*02e95f1aSMarcin Radomski */ 145*02e95f1aSMarcin Radomski struct pcm_plugin_min_max { 146*02e95f1aSMarcin Radomski /** Minimum value for the hardware parameter */ 147*02e95f1aSMarcin Radomski unsigned int min; 148*02e95f1aSMarcin Radomski /** Maximum value for the hardware parameter */ 149*02e95f1aSMarcin Radomski unsigned int max; 150*02e95f1aSMarcin Radomski }; 151*02e95f1aSMarcin Radomski 152*02e95f1aSMarcin Radomski /** Encapsulate the hardware parameter constraints 153*02e95f1aSMarcin Radomski * @ingroup libtinyalsa-pcm 154*02e95f1aSMarcin Radomski */ 155*02e95f1aSMarcin Radomski struct pcm_plugin_hw_constraints { 156*02e95f1aSMarcin Radomski /** Value for SNDRV_PCM_HW_PARAM_ACCESS param */ 157*02e95f1aSMarcin Radomski uint64_t access; 158*02e95f1aSMarcin Radomski /** Value for SNDRV_PCM_HW_PARAM_FORMAT param. 159*02e95f1aSMarcin Radomski * As of this implementation ALSA supports 52 formats */ 160*02e95f1aSMarcin Radomski uint64_t format; 161*02e95f1aSMarcin Radomski /** Value for SNDRV_PCM_HW_PARAM_SAMPLE_BITS param */ 162*02e95f1aSMarcin Radomski struct pcm_plugin_min_max bit_width; 163*02e95f1aSMarcin Radomski /** Value for SNDRV_PCM_HW_PARAM_CHANNELS param */ 164*02e95f1aSMarcin Radomski struct pcm_plugin_min_max channels; 165*02e95f1aSMarcin Radomski /** Value for SNDRV_PCM_HW_PARAM_RATE param */ 166*02e95f1aSMarcin Radomski struct pcm_plugin_min_max rate; 167*02e95f1aSMarcin Radomski /** Value for SNDRV_PCM_HW_PARAM_PERIODS param */ 168*02e95f1aSMarcin Radomski struct pcm_plugin_min_max periods; 169*02e95f1aSMarcin Radomski /** Value for SNDRV_PCM_HW_PARAM_PERIOD_BYTES param */ 170*02e95f1aSMarcin Radomski struct pcm_plugin_min_max period_bytes; 171*02e95f1aSMarcin Radomski }; 172*02e95f1aSMarcin Radomski 173*02e95f1aSMarcin Radomski struct pcm_plugin { 174*02e95f1aSMarcin Radomski /** Card number for the pcm device */ 175*02e95f1aSMarcin Radomski unsigned int card; 176*02e95f1aSMarcin Radomski /** device number for the pcm device */ 177*02e95f1aSMarcin Radomski unsigned int device; 178*02e95f1aSMarcin Radomski /** pointer to the contraints registered by the plugin */ 179*02e95f1aSMarcin Radomski struct pcm_plugin_hw_constraints *constraints; 180*02e95f1aSMarcin Radomski /** Indicates read/write mode, etc.. */ 181*02e95f1aSMarcin Radomski int mode; 182*02e95f1aSMarcin Radomski /* Pointer to hold the plugin's private data */ 183*02e95f1aSMarcin Radomski void *priv; 184*02e95f1aSMarcin Radomski /* Tracks the plugin state */ 185*02e95f1aSMarcin Radomski unsigned int state; 186*02e95f1aSMarcin Radomski }; 187*02e95f1aSMarcin Radomski 188*02e95f1aSMarcin Radomski typedef void (*mixer_event_callback)(struct mixer_plugin *); 189*02e95f1aSMarcin Radomski 190*02e95f1aSMarcin Radomski struct mixer_plugin_ops { 191*02e95f1aSMarcin Radomski int (*open) (struct mixer_plugin **plugin, unsigned int card); 192*02e95f1aSMarcin Radomski void (*close) (struct mixer_plugin **plugin); 193*02e95f1aSMarcin Radomski int (*subscribe_events) (struct mixer_plugin *plugin, 194*02e95f1aSMarcin Radomski mixer_event_callback event_cb); 195*02e95f1aSMarcin Radomski ssize_t (*read_event) (struct mixer_plugin *plugin, 196*02e95f1aSMarcin Radomski struct snd_ctl_event *ev, size_t size); 197*02e95f1aSMarcin Radomski }; 198*02e95f1aSMarcin Radomski 199*02e95f1aSMarcin Radomski struct snd_control { 200*02e95f1aSMarcin Radomski snd_ctl_elem_iface_t iface; 201*02e95f1aSMarcin Radomski unsigned int access; 202*02e95f1aSMarcin Radomski const char *name; 203*02e95f1aSMarcin Radomski snd_ctl_elem_type_t type; 204*02e95f1aSMarcin Radomski void *value; 205*02e95f1aSMarcin Radomski int (*get) (struct mixer_plugin *plugin, 206*02e95f1aSMarcin Radomski struct snd_control *control, 207*02e95f1aSMarcin Radomski struct snd_ctl_elem_value *ev); 208*02e95f1aSMarcin Radomski int (*put) (struct mixer_plugin *plugin, 209*02e95f1aSMarcin Radomski struct snd_control *control, 210*02e95f1aSMarcin Radomski struct snd_ctl_elem_value *ev); 211*02e95f1aSMarcin Radomski uint32_t private_value; 212*02e95f1aSMarcin Radomski void *private_data; 213*02e95f1aSMarcin Radomski }; 214*02e95f1aSMarcin Radomski 215*02e95f1aSMarcin Radomski struct mixer_plugin { 216*02e95f1aSMarcin Radomski unsigned int card; 217*02e95f1aSMarcin Radomski void *priv; 218*02e95f1aSMarcin Radomski 219*02e95f1aSMarcin Radomski int eventfd; 220*02e95f1aSMarcin Radomski int subscribed; 221*02e95f1aSMarcin Radomski int event_cnt; 222*02e95f1aSMarcin Radomski 223*02e95f1aSMarcin Radomski struct snd_control *controls; 224*02e95f1aSMarcin Radomski unsigned int num_controls; 225*02e95f1aSMarcin Radomski }; 226*02e95f1aSMarcin Radomski 227*02e95f1aSMarcin Radomski struct snd_value_enum { 228*02e95f1aSMarcin Radomski unsigned int items; 229*02e95f1aSMarcin Radomski char **texts; 230*02e95f1aSMarcin Radomski }; 231*02e95f1aSMarcin Radomski 232*02e95f1aSMarcin Radomski struct snd_value_bytes { 233*02e95f1aSMarcin Radomski unsigned int size; 234*02e95f1aSMarcin Radomski }; 235*02e95f1aSMarcin Radomski 236*02e95f1aSMarcin Radomski struct snd_value_tlv_bytes { 237*02e95f1aSMarcin Radomski unsigned int size; 238*02e95f1aSMarcin Radomski int (*get) (struct mixer_plugin *plugin, 239*02e95f1aSMarcin Radomski struct snd_control *control, 240*02e95f1aSMarcin Radomski struct snd_ctl_tlv *tlv); 241*02e95f1aSMarcin Radomski int (*put) (struct mixer_plugin *plugin, 242*02e95f1aSMarcin Radomski struct snd_control *control, 243*02e95f1aSMarcin Radomski struct snd_ctl_tlv *tlv); 244*02e95f1aSMarcin Radomski }; 245*02e95f1aSMarcin Radomski 246*02e95f1aSMarcin Radomski struct snd_value_int { 247*02e95f1aSMarcin Radomski unsigned int count; 248*02e95f1aSMarcin Radomski int min; 249*02e95f1aSMarcin Radomski int max; 250*02e95f1aSMarcin Radomski int step; 251*02e95f1aSMarcin Radomski }; 252*02e95f1aSMarcin Radomski 253*02e95f1aSMarcin Radomski /** Operations defined by the plugin. 254*02e95f1aSMarcin Radomski * */ 255*02e95f1aSMarcin Radomski struct snd_node_ops { 256*02e95f1aSMarcin Radomski /** Function pointer to get card definition */ 257*02e95f1aSMarcin Radomski void* (*open_card)(unsigned int card); 258*02e95f1aSMarcin Radomski /** Function pointer to release card definition */ 259*02e95f1aSMarcin Radomski void (*close_card)(void *card); 260*02e95f1aSMarcin Radomski /** Get interger type properties from device definition */ 261*02e95f1aSMarcin Radomski int (*get_int)(void *node, const char *prop, int *val); 262*02e95f1aSMarcin Radomski /** Get string type properties from device definition */ 263*02e95f1aSMarcin Radomski int (*get_str)(void *node, const char *prop, char **val); 264*02e95f1aSMarcin Radomski /** Function pointer to get mixer definition */ 265*02e95f1aSMarcin Radomski void* (*get_mixer)(void *card); 266*02e95f1aSMarcin Radomski /** Function pointer to get PCM definition */ 267*02e95f1aSMarcin Radomski void* (*get_pcm)(void *card, unsigned int id); 268*02e95f1aSMarcin Radomski /** Reserved for other nodes such as compress */ 269*02e95f1aSMarcin Radomski void* reserved[4]; 270*02e95f1aSMarcin Radomski }; 271*02e95f1aSMarcin Radomski 272*02e95f1aSMarcin Radomski #endif /* end of TINYALSA_PLUGIN_H */ 273