1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 #include <string.h>
5 #include <errno.h>
6 #include <ulog/ulog.h>
7 #include "audio_rtos.h"
8 #include "audio_card.h"
9 #include "pcm_dev.h"
10 #include "pb_task.h"
11 #include "cap_task.h"
12 
13 #define LOG_TAG    "[audio_rtos]"
14 
15 static native_pcm_device_t native_device[2];
16 
pcm_open(void * dev)17 static int pcm_open(void *dev)
18 {
19     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
20     if(!pcm_dev) {
21         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
22         return -EINVAL;
23     }
24     if(pcm_dev->isOpenState) {
25         //return -EBUSY;
26         return 0; /* WAR in case app not close pcm stream before open. */
27     }
28     if(!pcm_dev->ops) {
29         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
30         return -EINVAL;
31     }
32     pcm_dev->isOpenState = true;
33     return 0;
34 }
35 
pcm_hw_params(void * dev,audio_hw_params_t * params)36 static int pcm_hw_params(void *dev, audio_hw_params_t *params)
37 {
38     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
39     if(!pcm_dev) {
40         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
41         return -EINVAL;
42     }
43     if(!params) {
44         LOGE(LOG_TAG, "%s:%d, params is null", __func__, __LINE__);
45         return -EINVAL;
46     }
47     pcm_dev->params.block = params->block;
48     pcm_dev->params.interleave = params->interleave;
49     pcm_dev->params.rate = params->rate;
50     pcm_dev->params.channels = params->channels;
51     pcm_dev->params.sample_bits = params->sample_bits;
52     return 0;
53 }
54 
pcm_sw_params(void * dev,audio_sw_params_t * params)55 static int pcm_sw_params(void *dev, audio_sw_params_t *params)
56 {
57     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
58     if(!pcm_dev) {
59         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
60         return -EINVAL;
61     }
62     if(!params) {
63         LOGE(LOG_TAG, "%s:%d, params is null", __func__, __LINE__);
64         return -EINVAL;
65     }
66     pcm_dev->swParams.hdl = params->hdl;
67     pcm_dev->swParams.period = params->period;
68     return 0;
69 }
70 
pcm_hw_prepare(void * dev)71 static int pcm_hw_prepare(void *dev)
72 {
73     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
74     if(!pcm_dev) {
75         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
76         return -EINVAL;
77     }
78     if(!pcm_dev->ops) {
79         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
80         return -EINVAL;
81     }
82     if(!pcm_dev->ops->open) {
83         LOGE(LOG_TAG, "%s:%d, dev ops open is null", __func__, __LINE__);
84         return -EINVAL;
85     }
86     if(!pcm_dev->hdl) {
87         /* if 1st time open this pcm stream */
88         pcm_dev->hdl = pcm_dev->ops->open(pcm_dev->mode, pcm_dev->params.rate, pcm_dev->params.channels, pcm_dev->params.sample_bits, pcm_dev->swParams.hdl);
89         if(!pcm_dev->hdl) {
90             LOGE(LOG_TAG, "%s:%d, pcm_dev open failed", __func__, __LINE__);
91             return -1;
92         }
93     } else {
94         /* if not 1st time open this stream, it means recovering this stream */
95         pcm_dev->ops->close(pcm_dev->hdl);
96         /* if 1st time open this pcm stream */
97         pcm_dev->hdl = pcm_dev->ops->open(pcm_dev->mode, pcm_dev->params.rate, pcm_dev->params.channels, pcm_dev->params.sample_bits, pcm_dev->swParams.hdl);
98         if(!pcm_dev->hdl) {
99             LOGE(LOG_TAG, "%s:%d, pcm_dev open failed", __func__, __LINE__);
100             return -1;
101         }
102     }
103     return 0;
104 }
105 
pcm_start(void * dev)106 static int pcm_start(void *dev)
107 {
108     int ret = -1;
109     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
110     if(!pcm_dev) {
111         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
112         return -EINVAL;
113     }
114     if(!pcm_dev->ops) {
115         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
116         return -EINVAL;
117     }
118     if(!pcm_dev->ops->start) {
119         LOGE(LOG_TAG, "%s:%d, dev ops start is null", __func__, __LINE__);
120         return -EINVAL;
121     }
122     ret = pcm_dev->ops->start(pcm_dev->hdl);
123     if(pcm_dev->mode == PCM_STREAM_OUT) {
124         /* start playback thread */
125         playback_task_start();
126     } else {
127         /* start playback thread */
128         capture_task_start(dev);
129     }
130     return ret;
131 }
132 
pcm_readi(void * dev,audio_xferi_t * xbuf)133 static int pcm_readi(void *dev, audio_xferi_t *xbuf)
134 {
135     int ret = -1;
136     unsigned int byte_len = 0, frame_size = 0;
137     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
138     if(!pcm_dev) {
139         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
140         return -EINVAL;
141     }
142     frame_size = (pcm_dev->params.channels) * (pcm_dev->params.sample_bits) / 8;
143     byte_len = xbuf->frames * frame_size;
144     ret = capture_read_data(pcm_dev, xbuf->buf, byte_len, pcm_dev->params.block);
145     xbuf->result = (ret > 0) ? ret / frame_size : 0;
146     return 0;
147 }
148 
pcm_writei(void * dev,audio_xferi_t * xbuf)149 static int pcm_writei(void *dev, audio_xferi_t *xbuf)
150 {
151     int ret = 0;
152     int byte_len = 0, frame_size = 0;
153     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
154     if(!pcm_dev) {
155         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
156         return -EINVAL;
157     }
158     if(!pcm_dev->ops) {
159         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
160         return -EINVAL;
161     }
162     if(!pcm_dev->ops->write) {
163         LOGE(LOG_TAG, "%s:%d, dev ops write is null", __func__, __LINE__);
164         return -EINVAL;
165     }
166     if(!xbuf || !(xbuf->buf)) {
167         LOGE(LOG_TAG, "%s:%d, invalid xbuf", __func__, __LINE__);
168         return -EINVAL;
169     }
170     frame_size = (pcm_dev->params.channels) * (pcm_dev->params.sample_bits) / 8;
171     byte_len = (xbuf->frames) * frame_size;
172     ret = playback_push_data(dev, xbuf->buf, byte_len, pcm_dev->params.block);
173     xbuf->result = (ret > 0) ? ret / frame_size : 0;
174     return 0;
175 }
176 
pcm_readn(void * dev,audio_xfern_t * xbuf)177 static int pcm_readn(void *dev, audio_xfern_t *xbuf)
178 {
179     int ret = 0;
180     LOGE(LOG_TAG, "%s:%d, unsupported by now", __func__, __LINE__);
181     return ret;
182 }
183 
pcm_writen(void * dev,audio_xfern_t * xbuf)184 static int pcm_writen(void *dev, audio_xfern_t *xbuf)
185 {
186     int ret = 0;
187     LOGE(LOG_TAG, "%s:%d, unsupported by now", __func__, __LINE__);
188     return ret;
189 }
190 
pcm_drain(void * dev)191 int pcm_drain(void *dev)
192 {
193     int ret = -1;
194     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
195     if(pcm_dev->mode == PCM_STREAM_OUT) {
196         /* stop playback task */
197         ret = playback_task_drain();
198     }
199     LOGE(LOG_TAG, "%s:%d", __func__, __LINE__);
200     return ret;
201 }
202 
pcm_pause(void * dev,int enable)203 int pcm_pause(void *dev, int enable)
204 {
205     int ret = -1;
206     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
207     if(!pcm_dev) {
208         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
209         return -EINVAL;
210     }
211     if(!pcm_dev->ops) {
212         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
213         return -EINVAL;
214     }
215     if(!pcm_dev->ops->pause) {
216         LOGE(LOG_TAG, "%s:%d, dev ops close is null", __func__, __LINE__);
217         return -EINVAL;
218     }
219     ret = pcm_dev->ops->pause(pcm_dev->hdl, enable);
220     return ret;
221 }
222 
pcm_suspend(void * dev)223 int pcm_suspend(void *dev)
224 {
225     int ret = -1;
226     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
227     if(!pcm_dev) {
228         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
229         return -EINVAL;
230     }
231     if(!pcm_dev->ops) {
232         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
233         return -EINVAL;
234     }
235     if(!pcm_dev->ops->suspend) {
236         LOGE(LOG_TAG, "%s:%d, dev ops close is null", __func__, __LINE__);
237         return -EINVAL;
238     }
239     ret = pcm_dev->ops->suspend(pcm_dev->hdl);
240     return ret;
241 }
242 
pcm_resume(void * dev)243 int pcm_resume(void *dev)
244 {
245     int ret = -1;
246     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
247     if(!pcm_dev) {
248         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
249         return -EINVAL;
250     }
251     if(!pcm_dev->ops) {
252         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
253         return -EINVAL;
254     }
255     if(!pcm_dev->ops->resume) {
256         LOGE(LOG_TAG, "%s:%d, dev ops close is null", __func__, __LINE__);
257         return -EINVAL;
258     }
259     ret = pcm_dev->ops->resume(pcm_dev->hdl);
260     return ret;
261 }
262 
pcm_stop(void * dev)263 int pcm_stop(void *dev)
264 {
265     int ret = -1;
266     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
267     if(!pcm_dev) {
268         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
269         return -EINVAL;
270     }
271     if(!pcm_dev->ops) {
272         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
273         return -EINVAL;
274     }
275     if(!pcm_dev->ops->stop) {
276         LOGE(LOG_TAG, "%s:%d, dev ops stop is null", __func__, __LINE__);
277         return -EINVAL;
278     }
279     if(pcm_dev->mode == PCM_STREAM_OUT) {
280         /* stop playback task */
281         playback_task_stop();
282     } else {
283         /* stop capture task */
284         capture_task_stop();
285     }
286     ret = pcm_dev->ops->stop(pcm_dev->hdl);
287     LOGE(LOG_TAG, "%s:%d", __func__, __LINE__);
288     return ret;
289 }
290 
pcm_close(void * dev)291 int pcm_close(void *dev)
292 {
293     int ret = -1;
294     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
295     if(!pcm_dev) {
296         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
297         return -EINVAL;
298     }
299     if(!pcm_dev->ops) {
300         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
301         return -EINVAL;
302     }
303     if(!pcm_dev->ops->close) {
304         LOGE(LOG_TAG, "%s:%d, dev ops close is null", __func__, __LINE__);
305         return -EINVAL;
306     }
307     ret = pcm_dev->ops->close(pcm_dev->hdl);
308     pcm_dev->hdl = NULL;
309     pcm_dev->isOpenState = false;
310     return ret;
311 }
312 
pcm_recover(void * dev)313 int pcm_recover(void *dev)
314 {
315     int ret = -1;
316     native_pcm_device_t *pcm_dev = (native_pcm_device_t *)dev;
317     if(!pcm_dev) {
318         LOGE(LOG_TAG, "%s:%d, dev is null", __func__, __LINE__);
319         return -EINVAL;
320     }
321     if(!pcm_dev->ops) {
322         LOGE(LOG_TAG, "%s:%d, dev ops is null", __func__, __LINE__);
323         return -EINVAL;
324     }
325     if(!pcm_dev->ops->recover) {
326         LOGE(LOG_TAG, "%s:%d, dev ops close is null", __func__, __LINE__);
327         return -EINVAL;
328     }
329     ret = pcm_dev->ops->recover(pcm_dev->hdl);
330     return ret;
331 }
332 
333 static pcm_device_ops_t pcm_dev_ops = {
334     .open = pcm_open,
335     .hw_params = pcm_hw_params,
336     .sw_params = pcm_sw_params,
337     .hw_prepare = pcm_hw_prepare,
338     .start = pcm_start,
339     .readi = pcm_readi,
340     .readn = pcm_readn,
341     .writei = pcm_writei,
342     .writen = pcm_writen,
343     .drain = pcm_drain,
344     .pause = pcm_pause,
345     .resume = pcm_resume,
346     .stop = pcm_stop,
347     .close = pcm_close,
348     .recover = pcm_recover,
349 };
350 
351 /**
352  * audio_native_card_register - create an audio card
353  * @rec_num: recoder number
354  * @spk_num: speaker number
355  * @controls: audio_kcontrol_new properties belongs to audio card
356  * @controls_num: audio_kcontrol_new number
357  */
audio_native_card_register(int rec_num,int spk_num,pcm_stream_ops_t * ops,const struct audio_kcontrol_new * controls,int controls_num)358 int audio_native_card_register(int rec_num, int spk_num, pcm_stream_ops_t *ops, const struct audio_kcontrol_new *controls, int controls_num)
359 {
360     int ret = -1;
361     audio_card_t *card = NULL;
362     pcm_device_t *pcm_dev = NULL;
363     char name[20] = {0};
364 
365     card = audio_card_new();
366     if(!card) {
367         LOGE(LOG_TAG, "%s:%d, new card failed", __func__, __LINE__);
368         return ret;
369     }
370 
371     if(rec_num > 0) {
372         snprintf(name, sizeof(name), "/dev/pcmC%dD%dc", card->id, card->pcm_str_num);
373         pcm_dev = audio_pcm_device_new(AUDIO_DEVICE_TYPE_PCM_CAPTURE, name, &pcm_dev_ops, (void*)&native_device[0]);
374         if(!pcm_dev) {
375             LOGE(LOG_TAG, "%s:%d, new capture device failed", __func__, __LINE__);
376             return -ENOMEM;
377         }
378         native_device[0].mode = PCM_STREAM_IN;
379         native_device[0].ops = ops;
380         native_device[0].parent_data = (void *)card;
381         ret = audio_card_add_pcm_dev(card, pcm_dev);
382         if(ret < 0) {
383             LOGE(LOG_TAG, "%s:%d, add capture device failed", __func__, __LINE__);
384             return ret;
385         }
386     }
387 
388     if(spk_num > 0) {
389         snprintf(name, sizeof(name), "/dev/pcmC%dD%dp", card->id, card->pcm_str_num);
390         pcm_dev = audio_pcm_device_new(AUDIO_DEVICE_TYPE_PCM_PLAYBACK, name, &pcm_dev_ops, (void*)&native_device[1]);
391         if(!pcm_dev) {
392             LOGE(LOG_TAG, "%s:%d, new playback device failed", __func__, __LINE__);
393             return -ENOMEM;
394         }
395         native_device[1].mode = PCM_STREAM_OUT;
396         native_device[1].ops = ops;
397         native_device[1].parent_data = (void *)card;
398         ret = audio_card_add_pcm_dev(card, pcm_dev);
399         if(ret < 0) {
400             LOGE(LOG_TAG, "%s:%d, add playback device failed", __func__, __LINE__);
401             return ret;
402         }
403     }
404     card->pcm_str_num++;
405 
406     if(controls && controls_num > 0) {
407         audio_add_controls(card->ctrl_dev, controls, controls_num, NULL);
408     }
409     return 0;
410 }
411 
412