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