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