1*de0de752SAndroid Build Coastguard Worker /* compress_plugin.c
2*de0de752SAndroid Build Coastguard Worker **
3*de0de752SAndroid Build Coastguard Worker ** Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
4*de0de752SAndroid Build Coastguard Worker **
5*de0de752SAndroid Build Coastguard Worker ** Redistribution and use in source and binary forms, with or without
6*de0de752SAndroid Build Coastguard Worker ** modification, are permitted provided that the following conditions are
7*de0de752SAndroid Build Coastguard Worker ** met:
8*de0de752SAndroid Build Coastguard Worker ** * Redistributions of source code must retain the above copyright
9*de0de752SAndroid Build Coastguard Worker ** notice, this list of conditions and the following disclaimer.
10*de0de752SAndroid Build Coastguard Worker ** * Redistributions in binary form must reproduce the above
11*de0de752SAndroid Build Coastguard Worker ** copyright notice, this list of conditions and the following
12*de0de752SAndroid Build Coastguard Worker ** disclaimer in the documentation and/or other materials provided
13*de0de752SAndroid Build Coastguard Worker ** with the distribution.
14*de0de752SAndroid Build Coastguard Worker ** * Neither the name of The Linux Foundation nor the names of its
15*de0de752SAndroid Build Coastguard Worker ** contributors may be used to endorse or promote products derived
16*de0de752SAndroid Build Coastguard Worker ** from this software without specific prior written permission.
17*de0de752SAndroid Build Coastguard Worker **
18*de0de752SAndroid Build Coastguard Worker ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19*de0de752SAndroid Build Coastguard Worker ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20*de0de752SAndroid Build Coastguard Worker ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21*de0de752SAndroid Build Coastguard Worker ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22*de0de752SAndroid Build Coastguard Worker ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*de0de752SAndroid Build Coastguard Worker ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*de0de752SAndroid Build Coastguard Worker ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25*de0de752SAndroid Build Coastguard Worker ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26*de0de752SAndroid Build Coastguard Worker ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27*de0de752SAndroid Build Coastguard Worker ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28*de0de752SAndroid Build Coastguard Worker ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*de0de752SAndroid Build Coastguard Worker **/
30*de0de752SAndroid Build Coastguard Worker
31*de0de752SAndroid Build Coastguard Worker #include <stdio.h>
32*de0de752SAndroid Build Coastguard Worker #include <stdlib.h>
33*de0de752SAndroid Build Coastguard Worker #include <stdint.h>
34*de0de752SAndroid Build Coastguard Worker #include <fcntl.h>
35*de0de752SAndroid Build Coastguard Worker #include <stdarg.h>
36*de0de752SAndroid Build Coastguard Worker #include <string.h>
37*de0de752SAndroid Build Coastguard Worker #include <errno.h>
38*de0de752SAndroid Build Coastguard Worker #include <unistd.h>
39*de0de752SAndroid Build Coastguard Worker #include <poll.h>
40*de0de752SAndroid Build Coastguard Worker #include <dlfcn.h>
41*de0de752SAndroid Build Coastguard Worker
42*de0de752SAndroid Build Coastguard Worker #include <sys/ioctl.h>
43*de0de752SAndroid Build Coastguard Worker #include <linux/ioctl.h>
44*de0de752SAndroid Build Coastguard Worker #include <sound/asound.h>
45*de0de752SAndroid Build Coastguard Worker #include "tinycompress/compress_plugin.h"
46*de0de752SAndroid Build Coastguard Worker #include "sound/compress_offload.h"
47*de0de752SAndroid Build Coastguard Worker #include "compress_ops.h"
48*de0de752SAndroid Build Coastguard Worker #include "snd_utils.h"
49*de0de752SAndroid Build Coastguard Worker
50*de0de752SAndroid Build Coastguard Worker #define U32_MAX ((uint32_t)~0U)
51*de0de752SAndroid Build Coastguard Worker
52*de0de752SAndroid Build Coastguard Worker enum {
53*de0de752SAndroid Build Coastguard Worker COMPRESS_PLUG_STATE_OPEN,
54*de0de752SAndroid Build Coastguard Worker COMPRESS_PLUG_STATE_SETUP,
55*de0de752SAndroid Build Coastguard Worker COMPRESS_PLUG_STATE_PREPARED,
56*de0de752SAndroid Build Coastguard Worker COMPRESS_PLUG_STATE_PAUSE,
57*de0de752SAndroid Build Coastguard Worker COMPRESS_PLUG_STATE_RUNNING,
58*de0de752SAndroid Build Coastguard Worker };
59*de0de752SAndroid Build Coastguard Worker
60*de0de752SAndroid Build Coastguard Worker struct compress_plug_data {
61*de0de752SAndroid Build Coastguard Worker unsigned int card;
62*de0de752SAndroid Build Coastguard Worker unsigned int device;
63*de0de752SAndroid Build Coastguard Worker unsigned int fd;
64*de0de752SAndroid Build Coastguard Worker unsigned int flags;
65*de0de752SAndroid Build Coastguard Worker
66*de0de752SAndroid Build Coastguard Worker void *dl_hdl;
67*de0de752SAndroid Build Coastguard Worker COMPRESS_PLUGIN_OPEN_FN_PTR();
68*de0de752SAndroid Build Coastguard Worker
69*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin;
70*de0de752SAndroid Build Coastguard Worker void *dev_node;
71*de0de752SAndroid Build Coastguard Worker };
72*de0de752SAndroid Build Coastguard Worker
compress_plug_get_caps(struct compress_plug_data * plug_data,struct snd_compr_caps * caps)73*de0de752SAndroid Build Coastguard Worker static int compress_plug_get_caps(struct compress_plug_data *plug_data,
74*de0de752SAndroid Build Coastguard Worker struct snd_compr_caps *caps)
75*de0de752SAndroid Build Coastguard Worker {
76*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
77*de0de752SAndroid Build Coastguard Worker
78*de0de752SAndroid Build Coastguard Worker return plugin->ops->get_caps(plugin, caps);
79*de0de752SAndroid Build Coastguard Worker }
80*de0de752SAndroid Build Coastguard Worker
compress_plug_set_params(struct compress_plug_data * plug_data,struct snd_compr_params * params)81*de0de752SAndroid Build Coastguard Worker static int compress_plug_set_params(struct compress_plug_data *plug_data,
82*de0de752SAndroid Build Coastguard Worker struct snd_compr_params *params)
83*de0de752SAndroid Build Coastguard Worker {
84*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
85*de0de752SAndroid Build Coastguard Worker int rc;
86*de0de752SAndroid Build Coastguard Worker
87*de0de752SAndroid Build Coastguard Worker if (plugin->state == COMPRESS_PLUG_STATE_RUNNING)
88*de0de752SAndroid Build Coastguard Worker return plugin->ops->set_params(plugin, params);
89*de0de752SAndroid Build Coastguard Worker else if (plugin->state != COMPRESS_PLUG_STATE_OPEN)
90*de0de752SAndroid Build Coastguard Worker return -EBADFD;
91*de0de752SAndroid Build Coastguard Worker
92*de0de752SAndroid Build Coastguard Worker if (params->buffer.fragment_size == 0 ||
93*de0de752SAndroid Build Coastguard Worker params->buffer.fragments > U32_MAX / params->buffer.fragment_size ||
94*de0de752SAndroid Build Coastguard Worker params->buffer.fragments == 0)
95*de0de752SAndroid Build Coastguard Worker return -EINVAL;
96*de0de752SAndroid Build Coastguard Worker
97*de0de752SAndroid Build Coastguard Worker rc = plugin->ops->set_params(plugin, params);
98*de0de752SAndroid Build Coastguard Worker if (!rc)
99*de0de752SAndroid Build Coastguard Worker plugin->state = COMPRESS_PLUG_STATE_SETUP;
100*de0de752SAndroid Build Coastguard Worker
101*de0de752SAndroid Build Coastguard Worker return rc;
102*de0de752SAndroid Build Coastguard Worker }
103*de0de752SAndroid Build Coastguard Worker
compress_plug_avail(struct compress_plug_data * plug_data,struct snd_compr_avail * avail)104*de0de752SAndroid Build Coastguard Worker static int compress_plug_avail(struct compress_plug_data *plug_data,
105*de0de752SAndroid Build Coastguard Worker struct snd_compr_avail *avail)
106*de0de752SAndroid Build Coastguard Worker {
107*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
108*de0de752SAndroid Build Coastguard Worker
109*de0de752SAndroid Build Coastguard Worker return plugin->ops->avail(plugin, avail);
110*de0de752SAndroid Build Coastguard Worker }
111*de0de752SAndroid Build Coastguard Worker
compress_plug_tstamp(struct compress_plug_data * plug_data,struct snd_compr_tstamp * tstamp)112*de0de752SAndroid Build Coastguard Worker static int compress_plug_tstamp(struct compress_plug_data *plug_data,
113*de0de752SAndroid Build Coastguard Worker struct snd_compr_tstamp *tstamp)
114*de0de752SAndroid Build Coastguard Worker {
115*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
116*de0de752SAndroid Build Coastguard Worker
117*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_SETUP)
118*de0de752SAndroid Build Coastguard Worker return -EBADFD;
119*de0de752SAndroid Build Coastguard Worker
120*de0de752SAndroid Build Coastguard Worker return plugin->ops->tstamp(plugin, tstamp);
121*de0de752SAndroid Build Coastguard Worker }
122*de0de752SAndroid Build Coastguard Worker
compress_plug_start(struct compress_plug_data * plug_data)123*de0de752SAndroid Build Coastguard Worker static int compress_plug_start(struct compress_plug_data *plug_data)
124*de0de752SAndroid Build Coastguard Worker {
125*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
126*de0de752SAndroid Build Coastguard Worker int rc;
127*de0de752SAndroid Build Coastguard Worker
128*de0de752SAndroid Build Coastguard Worker /* for playback moved to prepare in first write */
129*de0de752SAndroid Build Coastguard Worker /* for capture: move to prepare state set params */
130*de0de752SAndroid Build Coastguard Worker /* TODO: add direction in set params */
131*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_PREPARED)
132*de0de752SAndroid Build Coastguard Worker return -EBADFD;
133*de0de752SAndroid Build Coastguard Worker
134*de0de752SAndroid Build Coastguard Worker rc = plugin->ops->start(plugin);
135*de0de752SAndroid Build Coastguard Worker if (!rc)
136*de0de752SAndroid Build Coastguard Worker plugin->state = COMPRESS_PLUG_STATE_RUNNING;
137*de0de752SAndroid Build Coastguard Worker
138*de0de752SAndroid Build Coastguard Worker return rc;
139*de0de752SAndroid Build Coastguard Worker }
140*de0de752SAndroid Build Coastguard Worker
compress_plug_stop(struct compress_plug_data * plug_data)141*de0de752SAndroid Build Coastguard Worker static int compress_plug_stop(struct compress_plug_data *plug_data)
142*de0de752SAndroid Build Coastguard Worker {
143*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
144*de0de752SAndroid Build Coastguard Worker int rc;
145*de0de752SAndroid Build Coastguard Worker
146*de0de752SAndroid Build Coastguard Worker if (plugin->state == COMPRESS_PLUG_STATE_PREPARED ||
147*de0de752SAndroid Build Coastguard Worker plugin->state == COMPRESS_PLUG_STATE_SETUP)
148*de0de752SAndroid Build Coastguard Worker return -EBADFD;
149*de0de752SAndroid Build Coastguard Worker
150*de0de752SAndroid Build Coastguard Worker rc = plugin->ops->stop(plugin);
151*de0de752SAndroid Build Coastguard Worker if (!rc)
152*de0de752SAndroid Build Coastguard Worker plugin->state = COMPRESS_PLUG_STATE_SETUP;
153*de0de752SAndroid Build Coastguard Worker
154*de0de752SAndroid Build Coastguard Worker return rc;
155*de0de752SAndroid Build Coastguard Worker }
156*de0de752SAndroid Build Coastguard Worker
compress_plug_pause(struct compress_plug_data * plug_data)157*de0de752SAndroid Build Coastguard Worker static int compress_plug_pause(struct compress_plug_data *plug_data)
158*de0de752SAndroid Build Coastguard Worker {
159*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
160*de0de752SAndroid Build Coastguard Worker int rc;
161*de0de752SAndroid Build Coastguard Worker
162*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_RUNNING)
163*de0de752SAndroid Build Coastguard Worker return -EBADFD;
164*de0de752SAndroid Build Coastguard Worker
165*de0de752SAndroid Build Coastguard Worker rc = plugin->ops->pause(plugin);
166*de0de752SAndroid Build Coastguard Worker if (!rc)
167*de0de752SAndroid Build Coastguard Worker plugin->state = COMPRESS_PLUG_STATE_PAUSE;
168*de0de752SAndroid Build Coastguard Worker
169*de0de752SAndroid Build Coastguard Worker return rc;
170*de0de752SAndroid Build Coastguard Worker }
171*de0de752SAndroid Build Coastguard Worker
compress_plug_resume(struct compress_plug_data * plug_data)172*de0de752SAndroid Build Coastguard Worker static int compress_plug_resume(struct compress_plug_data *plug_data)
173*de0de752SAndroid Build Coastguard Worker {
174*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
175*de0de752SAndroid Build Coastguard Worker int rc;
176*de0de752SAndroid Build Coastguard Worker
177*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_PAUSE)
178*de0de752SAndroid Build Coastguard Worker return -EBADFD;
179*de0de752SAndroid Build Coastguard Worker
180*de0de752SAndroid Build Coastguard Worker rc = plugin->ops->resume(plugin);
181*de0de752SAndroid Build Coastguard Worker if (!rc)
182*de0de752SAndroid Build Coastguard Worker plugin->state = COMPRESS_PLUG_STATE_RUNNING;
183*de0de752SAndroid Build Coastguard Worker
184*de0de752SAndroid Build Coastguard Worker return rc;
185*de0de752SAndroid Build Coastguard Worker }
186*de0de752SAndroid Build Coastguard Worker
compress_plug_drain(struct compress_plug_data * plug_data)187*de0de752SAndroid Build Coastguard Worker static int compress_plug_drain(struct compress_plug_data *plug_data)
188*de0de752SAndroid Build Coastguard Worker {
189*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
190*de0de752SAndroid Build Coastguard Worker
191*de0de752SAndroid Build Coastguard Worker /* check if we will allow in pause */
192*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_RUNNING)
193*de0de752SAndroid Build Coastguard Worker return -EBADFD;
194*de0de752SAndroid Build Coastguard Worker
195*de0de752SAndroid Build Coastguard Worker return plugin->ops->drain(plugin);
196*de0de752SAndroid Build Coastguard Worker }
197*de0de752SAndroid Build Coastguard Worker
compress_plug_partial_drain(struct compress_plug_data * plug_data)198*de0de752SAndroid Build Coastguard Worker static int compress_plug_partial_drain(struct compress_plug_data *plug_data)
199*de0de752SAndroid Build Coastguard Worker {
200*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
201*de0de752SAndroid Build Coastguard Worker
202*de0de752SAndroid Build Coastguard Worker /* check if we will allow in pause */
203*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_RUNNING)
204*de0de752SAndroid Build Coastguard Worker return -EBADFD;
205*de0de752SAndroid Build Coastguard Worker
206*de0de752SAndroid Build Coastguard Worker return plugin->ops->partial_drain(plugin);
207*de0de752SAndroid Build Coastguard Worker }
208*de0de752SAndroid Build Coastguard Worker
compress_plug_next_track(struct compress_plug_data * plug_data)209*de0de752SAndroid Build Coastguard Worker static int compress_plug_next_track(struct compress_plug_data *plug_data)
210*de0de752SAndroid Build Coastguard Worker {
211*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
212*de0de752SAndroid Build Coastguard Worker
213*de0de752SAndroid Build Coastguard Worker /* transion to next track applied to running stream only */
214*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_RUNNING)
215*de0de752SAndroid Build Coastguard Worker return -EBADFD;
216*de0de752SAndroid Build Coastguard Worker
217*de0de752SAndroid Build Coastguard Worker return plugin->ops->next_track(plugin);
218*de0de752SAndroid Build Coastguard Worker }
219*de0de752SAndroid Build Coastguard Worker
compress_plug_ioctl(void * data,unsigned int cmd,...)220*de0de752SAndroid Build Coastguard Worker static int compress_plug_ioctl(void *data, unsigned int cmd, ...)
221*de0de752SAndroid Build Coastguard Worker {
222*de0de752SAndroid Build Coastguard Worker struct compress_plug_data *plug_data = data;
223*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
224*de0de752SAndroid Build Coastguard Worker int ret = 0;
225*de0de752SAndroid Build Coastguard Worker va_list ap;
226*de0de752SAndroid Build Coastguard Worker void *arg;
227*de0de752SAndroid Build Coastguard Worker
228*de0de752SAndroid Build Coastguard Worker va_start(ap, cmd);
229*de0de752SAndroid Build Coastguard Worker arg = va_arg(ap, void *);
230*de0de752SAndroid Build Coastguard Worker va_end(ap);
231*de0de752SAndroid Build Coastguard Worker
232*de0de752SAndroid Build Coastguard Worker switch (cmd) {
233*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_IOCTL_VERSION:
234*de0de752SAndroid Build Coastguard Worker *((int*)arg) = SNDRV_COMPRESS_VERSION;
235*de0de752SAndroid Build Coastguard Worker break;
236*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_GET_CAPS:
237*de0de752SAndroid Build Coastguard Worker ret = compress_plug_get_caps(plug_data, arg);
238*de0de752SAndroid Build Coastguard Worker break;
239*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_SET_PARAMS:
240*de0de752SAndroid Build Coastguard Worker ret = compress_plug_set_params(plug_data, arg);
241*de0de752SAndroid Build Coastguard Worker break;
242*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_AVAIL:
243*de0de752SAndroid Build Coastguard Worker ret = compress_plug_avail(plug_data, arg);
244*de0de752SAndroid Build Coastguard Worker break;
245*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_TSTAMP:
246*de0de752SAndroid Build Coastguard Worker ret = compress_plug_tstamp(plug_data, arg);
247*de0de752SAndroid Build Coastguard Worker break;
248*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_START:
249*de0de752SAndroid Build Coastguard Worker ret = compress_plug_start(plug_data);
250*de0de752SAndroid Build Coastguard Worker break;
251*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_STOP:
252*de0de752SAndroid Build Coastguard Worker ret = compress_plug_stop(plug_data);
253*de0de752SAndroid Build Coastguard Worker break;
254*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_PAUSE:
255*de0de752SAndroid Build Coastguard Worker ret = compress_plug_pause(plug_data);
256*de0de752SAndroid Build Coastguard Worker break;
257*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_RESUME:
258*de0de752SAndroid Build Coastguard Worker ret = compress_plug_resume(plug_data);
259*de0de752SAndroid Build Coastguard Worker break;
260*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_DRAIN:
261*de0de752SAndroid Build Coastguard Worker ret = compress_plug_drain(plug_data);
262*de0de752SAndroid Build Coastguard Worker break;
263*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_PARTIAL_DRAIN:
264*de0de752SAndroid Build Coastguard Worker ret = compress_plug_partial_drain(plug_data);
265*de0de752SAndroid Build Coastguard Worker break;
266*de0de752SAndroid Build Coastguard Worker case SNDRV_COMPRESS_NEXT_TRACK:
267*de0de752SAndroid Build Coastguard Worker ret = compress_plug_next_track(plug_data);
268*de0de752SAndroid Build Coastguard Worker break;
269*de0de752SAndroid Build Coastguard Worker default:
270*de0de752SAndroid Build Coastguard Worker if (plugin->ops->ioctl)
271*de0de752SAndroid Build Coastguard Worker ret = plugin->ops->ioctl(plugin, cmd, arg);
272*de0de752SAndroid Build Coastguard Worker else
273*de0de752SAndroid Build Coastguard Worker ret = -EINVAL;
274*de0de752SAndroid Build Coastguard Worker break;
275*de0de752SAndroid Build Coastguard Worker }
276*de0de752SAndroid Build Coastguard Worker
277*de0de752SAndroid Build Coastguard Worker return ret;
278*de0de752SAndroid Build Coastguard Worker }
279*de0de752SAndroid Build Coastguard Worker
compress_plug_poll(void * data,struct pollfd * fds,nfds_t nfds,int timeout)280*de0de752SAndroid Build Coastguard Worker static int compress_plug_poll(void *data, struct pollfd *fds,
281*de0de752SAndroid Build Coastguard Worker nfds_t nfds, int timeout)
282*de0de752SAndroid Build Coastguard Worker {
283*de0de752SAndroid Build Coastguard Worker struct compress_plug_data *plug_data = data;
284*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
285*de0de752SAndroid Build Coastguard Worker
286*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_RUNNING)
287*de0de752SAndroid Build Coastguard Worker return -EBADFD;
288*de0de752SAndroid Build Coastguard Worker
289*de0de752SAndroid Build Coastguard Worker return plugin->ops->poll(plugin, fds, nfds, timeout);
290*de0de752SAndroid Build Coastguard Worker }
291*de0de752SAndroid Build Coastguard Worker
292*de0de752SAndroid Build Coastguard Worker
compress_plug_read(void * data,void * buf,size_t size)293*de0de752SAndroid Build Coastguard Worker static int compress_plug_read(void *data, void *buf, size_t size)
294*de0de752SAndroid Build Coastguard Worker {
295*de0de752SAndroid Build Coastguard Worker struct compress_plug_data *plug_data = data;
296*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
297*de0de752SAndroid Build Coastguard Worker
298*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_RUNNING &&
299*de0de752SAndroid Build Coastguard Worker plugin->state != COMPRESS_PLUG_STATE_SETUP)
300*de0de752SAndroid Build Coastguard Worker return -EBADFD;
301*de0de752SAndroid Build Coastguard Worker
302*de0de752SAndroid Build Coastguard Worker return plugin->ops->read(plugin, buf, size);
303*de0de752SAndroid Build Coastguard Worker }
304*de0de752SAndroid Build Coastguard Worker
compress_plug_write(void * data,const void * buf,size_t size)305*de0de752SAndroid Build Coastguard Worker static int compress_plug_write(void *data, const void *buf, size_t size)
306*de0de752SAndroid Build Coastguard Worker {
307*de0de752SAndroid Build Coastguard Worker struct compress_plug_data *plug_data = data;
308*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
309*de0de752SAndroid Build Coastguard Worker int rc;
310*de0de752SAndroid Build Coastguard Worker
311*de0de752SAndroid Build Coastguard Worker if (plugin->state != COMPRESS_PLUG_STATE_SETUP &&
312*de0de752SAndroid Build Coastguard Worker plugin->state != COMPRESS_PLUG_STATE_PREPARED &&
313*de0de752SAndroid Build Coastguard Worker plugin->state != COMPRESS_PLUG_STATE_RUNNING)
314*de0de752SAndroid Build Coastguard Worker return -EBADFD;
315*de0de752SAndroid Build Coastguard Worker
316*de0de752SAndroid Build Coastguard Worker rc = plugin->ops->write(plugin, buf, size);
317*de0de752SAndroid Build Coastguard Worker if ((rc > 0) && (plugin->state == COMPRESS_PLUG_STATE_SETUP))
318*de0de752SAndroid Build Coastguard Worker plugin->state = COMPRESS_PLUG_STATE_PREPARED;
319*de0de752SAndroid Build Coastguard Worker
320*de0de752SAndroid Build Coastguard Worker return rc;
321*de0de752SAndroid Build Coastguard Worker }
322*de0de752SAndroid Build Coastguard Worker
compress_plug_close(void * data)323*de0de752SAndroid Build Coastguard Worker static void compress_plug_close(void *data)
324*de0de752SAndroid Build Coastguard Worker {
325*de0de752SAndroid Build Coastguard Worker struct compress_plug_data *plug_data = data;
326*de0de752SAndroid Build Coastguard Worker struct compress_plugin *plugin = plug_data->plugin;
327*de0de752SAndroid Build Coastguard Worker
328*de0de752SAndroid Build Coastguard Worker plugin->ops->close(plugin);
329*de0de752SAndroid Build Coastguard Worker dlclose(plug_data->dl_hdl);
330*de0de752SAndroid Build Coastguard Worker
331*de0de752SAndroid Build Coastguard Worker free(plug_data);
332*de0de752SAndroid Build Coastguard Worker }
333*de0de752SAndroid Build Coastguard Worker
compress_plug_open(unsigned int card,unsigned int device,unsigned int flags,void ** data,void * node)334*de0de752SAndroid Build Coastguard Worker static int compress_plug_open(unsigned int card, unsigned int device,
335*de0de752SAndroid Build Coastguard Worker unsigned int flags, void **data, void *node)
336*de0de752SAndroid Build Coastguard Worker {
337*de0de752SAndroid Build Coastguard Worker struct compress_plug_data *plug_data;
338*de0de752SAndroid Build Coastguard Worker void *dl_hdl;
339*de0de752SAndroid Build Coastguard Worker int rc = 0;
340*de0de752SAndroid Build Coastguard Worker char *so_name, *open_fn, token[80], *name, *token_saveptr;
341*de0de752SAndroid Build Coastguard Worker
342*de0de752SAndroid Build Coastguard Worker plug_data = calloc(1, sizeof(*plug_data));
343*de0de752SAndroid Build Coastguard Worker if (!plug_data) {
344*de0de752SAndroid Build Coastguard Worker return -ENOMEM;
345*de0de752SAndroid Build Coastguard Worker }
346*de0de752SAndroid Build Coastguard Worker
347*de0de752SAndroid Build Coastguard Worker rc = snd_utils_get_str(node, "so-name", &so_name);
348*de0de752SAndroid Build Coastguard Worker if (rc) {
349*de0de752SAndroid Build Coastguard Worker fprintf(stderr, "%s: failed to get plugin lib name\n",
350*de0de752SAndroid Build Coastguard Worker __func__);
351*de0de752SAndroid Build Coastguard Worker goto err_get_lib;
352*de0de752SAndroid Build Coastguard Worker }
353*de0de752SAndroid Build Coastguard Worker
354*de0de752SAndroid Build Coastguard Worker dl_hdl = dlopen(so_name, RTLD_NOW);
355*de0de752SAndroid Build Coastguard Worker if (!dl_hdl) {
356*de0de752SAndroid Build Coastguard Worker fprintf(stderr, "%s: unable to open %s, error: %s\n",
357*de0de752SAndroid Build Coastguard Worker __func__, so_name, dlerror());
358*de0de752SAndroid Build Coastguard Worker goto err_dl_open;
359*de0de752SAndroid Build Coastguard Worker } else {
360*de0de752SAndroid Build Coastguard Worker fprintf(stderr, "%s: dlopen successful for %s\n",
361*de0de752SAndroid Build Coastguard Worker __func__, so_name);
362*de0de752SAndroid Build Coastguard Worker }
363*de0de752SAndroid Build Coastguard Worker
364*de0de752SAndroid Build Coastguard Worker sscanf(so_name, "lib%s", token);
365*de0de752SAndroid Build Coastguard Worker token_saveptr = token;
366*de0de752SAndroid Build Coastguard Worker name = strtok_r(token, ".", &token_saveptr);
367*de0de752SAndroid Build Coastguard Worker if (!name) {
368*de0de752SAndroid Build Coastguard Worker fprintf(stderr, "%s: invalid library name\n", __func__);
369*de0de752SAndroid Build Coastguard Worker goto err_open_fn;
370*de0de752SAndroid Build Coastguard Worker }
371*de0de752SAndroid Build Coastguard Worker const size_t open_fn_size = strlen(name) + strlen("_open") + 1;
372*de0de752SAndroid Build Coastguard Worker open_fn = calloc(1, open_fn_size);
373*de0de752SAndroid Build Coastguard Worker if (!open_fn) {
374*de0de752SAndroid Build Coastguard Worker rc = -ENOMEM;
375*de0de752SAndroid Build Coastguard Worker goto err_open_fn;
376*de0de752SAndroid Build Coastguard Worker }
377*de0de752SAndroid Build Coastguard Worker
378*de0de752SAndroid Build Coastguard Worker strlcpy(open_fn, name, open_fn_size);
379*de0de752SAndroid Build Coastguard Worker strlcat(open_fn, "_open", open_fn_size);
380*de0de752SAndroid Build Coastguard Worker
381*de0de752SAndroid Build Coastguard Worker plug_data->plugin_open_fn = dlsym(dl_hdl, open_fn);
382*de0de752SAndroid Build Coastguard Worker if (!plug_data->plugin_open_fn) {
383*de0de752SAndroid Build Coastguard Worker fprintf(stderr, "%s: dlsym to open fn failed, err = '%s'\n",
384*de0de752SAndroid Build Coastguard Worker __func__, dlerror());
385*de0de752SAndroid Build Coastguard Worker goto err_dlsym;
386*de0de752SAndroid Build Coastguard Worker }
387*de0de752SAndroid Build Coastguard Worker
388*de0de752SAndroid Build Coastguard Worker rc = plug_data->plugin_open_fn(&plug_data->plugin,
389*de0de752SAndroid Build Coastguard Worker card, device, flags);
390*de0de752SAndroid Build Coastguard Worker if (rc) {
391*de0de752SAndroid Build Coastguard Worker fprintf(stderr, "%s: failed to open plugin\n", __func__);
392*de0de752SAndroid Build Coastguard Worker goto err_dlsym;
393*de0de752SAndroid Build Coastguard Worker }
394*de0de752SAndroid Build Coastguard Worker
395*de0de752SAndroid Build Coastguard Worker /* Call snd-card-def to get card and compress nodes */
396*de0de752SAndroid Build Coastguard Worker /* Check how to manage fd for plugin */
397*de0de752SAndroid Build Coastguard Worker
398*de0de752SAndroid Build Coastguard Worker plug_data->dl_hdl = dl_hdl;
399*de0de752SAndroid Build Coastguard Worker plug_data->card = card;
400*de0de752SAndroid Build Coastguard Worker plug_data->device = device;
401*de0de752SAndroid Build Coastguard Worker plug_data->dev_node = node;
402*de0de752SAndroid Build Coastguard Worker plug_data->flags = flags;
403*de0de752SAndroid Build Coastguard Worker
404*de0de752SAndroid Build Coastguard Worker *data = plug_data;
405*de0de752SAndroid Build Coastguard Worker
406*de0de752SAndroid Build Coastguard Worker plug_data->plugin->state = COMPRESS_PLUG_STATE_OPEN;
407*de0de752SAndroid Build Coastguard Worker
408*de0de752SAndroid Build Coastguard Worker return 0;
409*de0de752SAndroid Build Coastguard Worker
410*de0de752SAndroid Build Coastguard Worker err_dlsym:
411*de0de752SAndroid Build Coastguard Worker free(open_fn);
412*de0de752SAndroid Build Coastguard Worker err_open_fn:
413*de0de752SAndroid Build Coastguard Worker dlclose(dl_hdl);
414*de0de752SAndroid Build Coastguard Worker err_get_lib:
415*de0de752SAndroid Build Coastguard Worker err_dl_open:
416*de0de752SAndroid Build Coastguard Worker free(plug_data);
417*de0de752SAndroid Build Coastguard Worker
418*de0de752SAndroid Build Coastguard Worker return rc;
419*de0de752SAndroid Build Coastguard Worker }
420*de0de752SAndroid Build Coastguard Worker
421*de0de752SAndroid Build Coastguard Worker struct compress_ops compr_plug_ops = {
422*de0de752SAndroid Build Coastguard Worker .open = compress_plug_open,
423*de0de752SAndroid Build Coastguard Worker .close = compress_plug_close,
424*de0de752SAndroid Build Coastguard Worker .ioctl = compress_plug_ioctl,
425*de0de752SAndroid Build Coastguard Worker .read = compress_plug_read,
426*de0de752SAndroid Build Coastguard Worker .write = compress_plug_write,
427*de0de752SAndroid Build Coastguard Worker .poll = compress_plug_poll,
428*de0de752SAndroid Build Coastguard Worker };
429