1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 #include "sound_pcm.h"
5 #include "ulog/ulog.h"
6 
7 #define LOG_TAG  "[sound_pcm]"
8 #define PCM_LOCK(pcm) aos_mutex_lock(&pcm->mutex, AOS_WAIT_FOREVER)
9 #define PCM_UNLOCK(pcm) aos_mutex_unlock(&pcm->mutex)
10 #define PCM_RETURN_ERR      -1
11 #define PCM_RETURN_SUCCESS  0
12 
13 
aos_device_name_hint(int card,void * hints)14 int aos_device_name_hint(int card, void *hints)
15 {
16     int i = 0, j = 0, fd = -1;
17     char fn[256];
18     hint_list_t *node = NULL;
19 
20     if(card == -1) {
21         for(i = 0; i < AOS_SNDCARD_NUM_MAX; i++) {
22             for(j = 0; j < AOS_SNDCARD_DEVICE_NUM_MAX; j++) {
23                 memset(fn, 0, sizeof(fn));
24                 snprintf(fn, sizeof(fn), "/dev/pcmC%uD%u%c", i, j, 'p');
25                 fd = open(fn, O_RDWR|O_NONBLOCK);
26                 if (fd > 0) {
27                     node = (hint_list_t *)calloc(1, sizeof(hint_list_t));
28                     if(!node) {
29                         return -ENOMEM;
30                     }
31                     hints = (void *)node;
32                     node->card = i;
33                     node->device = j;
34                     strncpy(node->name, fn, sizeof(node->name));
35                     close(fd);
36                     LOGD(LOG_TAG, "%s:%d, found sound card %d device %d %s", __func__, __LINE__, i, j, node->name);
37                     return PCM_RETURN_SUCCESS;
38                 }
39             }
40         }
41     } else {
42         for(j = 0; j < AOS_SNDCARD_DEVICE_NUM_MAX; j++) {
43             memset(fn, 0, sizeof(fn));
44             snprintf(fn, sizeof(fn), "/dev/pcmC%uD%u%c", card, j, 'p');
45             fd = open(fn, O_RDWR|O_NONBLOCK);
46             if (fd > 0) {
47                 node = (hint_list_t *)calloc(1, sizeof(hint_list_t));
48                 if(!node) {
49                     return -ENOMEM;
50                 }
51                 hints = (void *)node;
52                 node->card = card;
53                 node->device = j;
54                 strncpy(node->name, fn, sizeof(node->name));
55                 close(fd);
56                 LOGD(LOG_TAG, "%s:%d, found sound card %d device %d %s", __func__, __LINE__, card, j, node->name);
57                 return PCM_RETURN_SUCCESS;
58             }
59         }
60     }
61     LOGE(LOG_TAG, "%s:%d, found no sound device ", __func__, __LINE__);
62     return PCM_RETURN_ERR;
63 }
64 
aos_pcm_open(aos_pcm_t ** pcm,const char * name,aos_pcm_stream_t stream,int mode)65 int aos_pcm_open(aos_pcm_t **pcm, const char *name, aos_pcm_stream_t stream, int mode)
66 {
67     int card = 0, device = 0, fd = -1;
68     char fn[256];
69     if(!name) {
70         LOGE(LOG_TAG, "%s:%d, param name is null", __func__, __LINE__);
71         return PCM_RETURN_ERR;
72     }
73     *pcm = (aos_pcm_t *)calloc(1, sizeof(aos_pcm_t));
74     if(NULL == *pcm) {
75         LOGE(LOG_TAG, "%s:%d, calloc aos_pcm_t failed", __func__, __LINE__);
76         return -ENOMEM;
77     }
78     memset(*pcm, 0, sizeof(aos_pcm_t));
79     if(!strcmp(name, "default")) {
80         for(card = 0; card < AOS_SNDCARD_NUM_MAX; card++) {
81             for(device = 0; device < AOS_SNDCARD_DEVICE_NUM_MAX; device++) {
82                 memset(fn, 0, sizeof(fn));
83                 snprintf(fn, sizeof(fn), "/dev/pcmC%uD%u%c", card, device, (stream == AOS_PCM_STREAM_PLAYBACK) ? 'p' : 'c');
84                 fd = open(fn, O_RDWR|O_NONBLOCK);
85                 if (fd > 0) {
86                     (*pcm)->fd = fd;
87                     (*pcm)->card = card;
88                     (*pcm)->device = device;
89                     (*pcm)->name = strdup(fn);
90                     (*pcm)->stream = stream;
91                     (*pcm)->mode = mode;
92                     (*pcm)->state = AOS_PCM_STATE_OPEN;
93                     aos_mutex_new(&((*pcm)->mutex));
94                     aos_event_new(&((*pcm)->evt), 0);
95                     LOGD(LOG_TAG, "%s:%d, open card %d device %d successfully", __func__, __LINE__, card, device);
96                     return PCM_RETURN_SUCCESS;
97                 }
98             }
99         }
100     } else {
101         for(card = 0; card < AOS_SNDCARD_NUM_MAX; card++) {
102             for(device = 0; device < AOS_SNDCARD_DEVICE_NUM_MAX; device++) {
103                 memset(fn, 0, sizeof(fn));
104                 snprintf(fn, sizeof(fn), "/dev/pcmC%uD%u%c", card, device, (stream == AOS_PCM_STREAM_PLAYBACK) ? 'p' : 'c');
105                 if(!strcmp(name, fn)) {
106                     fd = open(fn, O_RDWR|O_NONBLOCK);
107                     if (fd > 0) {
108                         (*pcm)->fd = fd;
109                         (*pcm)->card = card;
110                         (*pcm)->device = device;
111                         (*pcm)->name = strdup(fn);
112                         (*pcm)->stream = stream;
113                         (*pcm)->mode = mode;
114                         (*pcm)->state = AOS_PCM_STATE_OPEN;
115                         aos_mutex_new(&((*pcm)->mutex));
116                         aos_event_new(&((*pcm)->evt), 0);
117                         LOGD(LOG_TAG, "%s:%d, open card %d device %d successfully", __func__, __LINE__, card, device);
118                         return PCM_RETURN_SUCCESS;
119                     }
120                 }
121             }
122         }
123     }
124     LOGE(LOG_TAG, "%s:%d, open %s device failed", __func__, __LINE__, (stream == AOS_PCM_STREAM_PLAYBACK) ? "playback" : "capture");
125     free(*pcm);
126     *pcm = NULL;
127     return PCM_RETURN_ERR;
128 }
129 
aos_pcm_prepare(aos_pcm_t * pcm)130 int aos_pcm_prepare(aos_pcm_t *pcm)
131 {
132     int ret = PCM_RETURN_SUCCESS;
133     if(NULL == pcm) {
134         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
135         return PCM_RETURN_ERR;
136     }
137     if(pcm->fd < 0) {
138         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
139         return PCM_RETURN_ERR;
140     }
141     PCM_LOCK(pcm);
142     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_PREPARE)) {
143         LOGE(LOG_TAG, "%s:%d, ioctl prepare failed", __func__, __LINE__);
144         ret = PCM_RETURN_ERR;
145     } else {
146         pcm->state = AOS_PCM_STATE_PREPARED;
147     }
148     PCM_UNLOCK(pcm);
149     return ret;
150 }
151 
aos_pcm_start(aos_pcm_t * pcm)152 int aos_pcm_start(aos_pcm_t *pcm)
153 {
154     int ret = PCM_RETURN_SUCCESS;
155     if(NULL == pcm) {
156         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
157         return PCM_RETURN_ERR;
158     }
159     if(pcm->fd < 0) {
160         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
161         return PCM_RETURN_ERR;
162     }
163     PCM_LOCK(pcm);
164     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_START)) {
165         LOGE(LOG_TAG, "%s:%d, ioctl start failed", __func__, __LINE__);
166         ret = PCM_RETURN_ERR;
167     } else {
168         pcm->state = AOS_PCM_STATE_RUNNING;
169     }
170     PCM_UNLOCK(pcm);
171     return ret;
172 }
173 
aos_pcm_wait(aos_pcm_t * pcm,int timeout)174 int aos_pcm_wait(aos_pcm_t *pcm, int timeout)
175 {
176     int ret = PCM_RETURN_SUCCESS;
177     unsigned int actl_flags = 0;
178     if(NULL == pcm) {
179         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
180         return PCM_RETURN_ERR;
181     }
182     if(pcm->fd < 0) {
183         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
184         return PCM_RETURN_ERR;
185     }
186     PCM_LOCK(pcm);
187     aos_event_get(&pcm->evt, AOS_PCM_EVT_READ | AOS_PCM_EVT_XRUN, AOS_EVENT_OR_CLEAR, &actl_flags, timeout);
188     PCM_UNLOCK(pcm);
189 
190     if (actl_flags & AOS_EVENT_OR_CLEAR) {
191         LOGE(LOG_TAG,"PCM_EVT_XRUN");
192         return -EPIPE;
193     }
194 
195     return ret; // TBD 2x : ret value + evt to driver
196 }
197 
aos_pcm_stop(aos_pcm_t * pcm)198 int aos_pcm_stop(aos_pcm_t *pcm)
199 {
200     int ret = PCM_RETURN_SUCCESS;
201     if(NULL == pcm) {
202         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
203         return PCM_RETURN_ERR;
204     }
205     if(pcm->fd < 0) {
206         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
207         return PCM_RETURN_ERR;
208     }
209     PCM_LOCK(pcm);
210     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_DROP)) {
211         LOGE(LOG_TAG, "%s:%d, ioctl drop failed", __func__, __LINE__);
212         ret = PCM_RETURN_ERR;
213     } else {
214         pcm->state = AOS_PCM_STATE_PAUSED;
215     }
216     PCM_UNLOCK(pcm);
217     return ret;
218 }
219 
aos_pcm_drain(aos_pcm_t * pcm)220 int aos_pcm_drain(aos_pcm_t *pcm)
221 {
222     int ret = PCM_RETURN_SUCCESS;
223     if(NULL == pcm) {
224         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
225         return PCM_RETURN_ERR;
226     }
227     if(pcm->fd < 0) {
228         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
229         return PCM_RETURN_ERR;
230     }
231     PCM_LOCK(pcm);
232     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_DRAIN)) {
233         LOGE(LOG_TAG, "%s:%d, ioctl drain failed", __func__, __LINE__);
234         ret = PCM_RETURN_ERR;
235     }
236     PCM_UNLOCK(pcm);
237     return ret;
238 }
239 
aos_pcm_pause(aos_pcm_t * pcm,int enable)240 int aos_pcm_pause(aos_pcm_t *pcm, int enable)
241 {
242     int ret = PCM_RETURN_SUCCESS;
243     if(NULL == pcm) {
244         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
245         return PCM_RETURN_ERR;
246     }
247     if(pcm->fd < 0) {
248         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
249         return PCM_RETURN_ERR;
250     }
251     PCM_LOCK(pcm);
252     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_PAUSE, enable)) {
253         LOGE(LOG_TAG, "%s:%d, ioctl pause failed", __func__, __LINE__);
254         ret = PCM_RETURN_ERR;
255     }
256     PCM_UNLOCK(pcm);
257     return ret;
258 }
259 
aos_pcm_close(aos_pcm_t * pcm)260 int aos_pcm_close(aos_pcm_t *pcm)
261 {
262     int ret = PCM_RETURN_SUCCESS;
263     if(NULL == pcm) {
264         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
265         return PCM_RETURN_ERR;
266     }
267     if(pcm->fd < 0) {
268         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
269         return PCM_RETURN_ERR;
270     }
271     PCM_LOCK(pcm);
272     if(close(pcm->fd)) {
273         LOGE(LOG_TAG, "%s:%d, close pcm failed", __func__, __LINE__);
274         ret = PCM_RETURN_ERR;
275     }
276     if(pcm->name) {
277         free(pcm->name);
278     }
279     if(pcm->open_func) {
280         free(pcm->open_func);
281     }
282     if(pcm->private_data) {
283         free(pcm->private_data);
284     }
285     if(pcm->hw_params) {
286         free(pcm->hw_params);
287     }
288     if(pcm->sw_params) {
289         free(pcm->sw_params);
290     }
291     PCM_UNLOCK(pcm);
292     free(pcm);
293     return ret;
294 }
295 
aos_pcm_recover(aos_pcm_t * pcm)296 int aos_pcm_recover(aos_pcm_t *pcm)
297 {
298     int ret = PCM_RETURN_SUCCESS;
299     if(NULL == pcm) {
300         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
301         return PCM_RETURN_ERR;
302     }
303     if(pcm->fd < 0) {
304         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
305         return PCM_RETURN_ERR;
306     }
307     PCM_LOCK(pcm);
308     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_RECOVER)) {
309         LOGE(LOG_TAG, "%s:%d, ioctl recover failed", __func__, __LINE__);
310         ret = PCM_RETURN_ERR;
311     }
312     PCM_UNLOCK(pcm);
313     return ret;
314 }
315 
aos_pcm_suspend(aos_pcm_t * pcm)316 int aos_pcm_suspend(aos_pcm_t *pcm)
317 {
318     int ret = PCM_RETURN_SUCCESS;
319     if(NULL == pcm) {
320         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
321         return PCM_RETURN_ERR;
322     }
323     if(pcm->fd < 0) {
324         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
325         return PCM_RETURN_ERR;
326     }
327     PCM_LOCK(pcm);
328     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_SUSPEND)) {
329         LOGE(LOG_TAG, "%s:%d, ioctl suspend failed", __func__, __LINE__);
330         ret = PCM_RETURN_ERR;
331     }
332     PCM_UNLOCK(pcm);
333     return ret;
334 }
335 
aos_pcm_resume(aos_pcm_t * pcm)336 int aos_pcm_resume(aos_pcm_t *pcm)
337 {
338     int ret = PCM_RETURN_SUCCESS;
339     if(NULL == pcm) {
340         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
341         return PCM_RETURN_ERR;
342     }
343     if(pcm->fd < 0) {
344         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
345         return PCM_RETURN_ERR;
346     }
347     PCM_LOCK(pcm);
348     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_RESUME)) {
349         LOGE(LOG_TAG, "%s:%d, ioctl resume failed", __func__, __LINE__);
350         ret = PCM_RETURN_ERR;
351     }
352     PCM_UNLOCK(pcm);
353     return ret;
354 }
355 
aos_pcm_hw_params_alloca(aos_pcm_hw_params_t ** p)356 int aos_pcm_hw_params_alloca(aos_pcm_hw_params_t **p)
357 {
358     *p = (aos_pcm_hw_params_t *)calloc(1, sizeof(aos_pcm_hw_params_t));
359     if(NULL == *p) {
360         LOGE(LOG_TAG, "%s:%d, calloc aos_pcm_hw_params_t failed", __func__, __LINE__);
361         return -ENOMEM;
362     }
363     return PCM_RETURN_SUCCESS;
364 }
365 
aos_pcm_hw_params_any(aos_pcm_hw_params_t * params)366 int aos_pcm_hw_params_any(aos_pcm_hw_params_t *params)
367 {
368     if(!params) {
369         return PCM_RETURN_ERR;
370     }
371     params->access = AOS_PCM_ACCESS_RW_INTERLEAVED;
372     params->format = AOSRV_PCM_FORMAT_S16_LE;
373     params->channels = 2;
374     params->rate = 16000;
375     params->sample_bits = (params->format * 8);
376     params->frame_bits = (params->format * params->channels * 8);
377     return PCM_RETURN_SUCCESS;
378 }
379 
aos_pcm_hw_params(aos_pcm_t * pcm,aos_pcm_hw_params_t * p)380 int aos_pcm_hw_params(aos_pcm_t *pcm, aos_pcm_hw_params_t *p)
381 {
382     int ret = PCM_RETURN_SUCCESS;
383     audio_hw_params_t params;
384     if(NULL == pcm) {
385         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
386         return PCM_RETURN_ERR;
387     }
388     if(pcm->fd < 0) {
389         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
390         return PCM_RETURN_ERR;
391     }
392     if(p && pcm->hw_params) {
393         memcpy(pcm->hw_params, p, sizeof(aos_pcm_hw_params_t));
394     }
395     PCM_LOCK(pcm);
396     params.block = (pcm->mode & AOS_PCM_NONBLOCK) ? 0 : 1;
397     params.interleave = (p->access == AOS_PCM_ACCESS_RW_NONINTERLEAVED) ? 0 : 1;
398     params.channels = p->channels;
399     params.rate = p->rate;
400     params.sample_bits = p->format * 8;
401     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_HW_PARAMS, &params)) {
402         LOGE(LOG_TAG, "%s:%d, cannot set hw params", __func__, __LINE__);
403         ret = PCM_RETURN_ERR;
404     }
405     PCM_UNLOCK(pcm);
406     LOGD(LOG_TAG, "%s:%d, block %d, interleave %d, rate %d channels %d bits %d", __func__, __LINE__, params.block,
407          params.interleave, params.rate, params.channels, params.sample_bits);
408     return ret;
409 }
410 
aos_pcm_sw_params_any(aos_pcm_sw_params_t * params)411 int aos_pcm_sw_params_any(aos_pcm_sw_params_t *params)
412 {
413     if(!params) {
414         return PCM_RETURN_ERR;
415     }
416     params->period_step = 20; // 20ms period by default
417     return PCM_RETURN_SUCCESS;
418 }
419 
aos_pcm_sw_params_alloca(aos_pcm_sw_params_t ** p)420 int aos_pcm_sw_params_alloca(aos_pcm_sw_params_t **p)
421 {
422     *p = (aos_pcm_sw_params_t *)calloc(1, sizeof(aos_pcm_sw_params_t));
423     if(NULL == *p) {
424         LOGE(LOG_TAG, "%s:%d, calloc aos_pcm_sw_params_t failed", __func__, __LINE__);
425         return -ENOMEM;
426     }
427     return PCM_RETURN_SUCCESS;
428 }
429 
aos_pcm_sw_params(aos_pcm_t * pcm,aos_pcm_sw_params_t * p)430 int aos_pcm_sw_params(aos_pcm_t *pcm, aos_pcm_sw_params_t *p)
431 {
432     int ret = PCM_RETURN_SUCCESS;
433     audio_sw_params_t params;
434     if(NULL == pcm) {
435         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
436         return PCM_RETURN_ERR;
437     }
438     if(pcm->fd < 0) {
439         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
440         return PCM_RETURN_ERR;
441     }
442     if(pcm->sw_params && p) {
443         pcm->sw_params->period_step = p->period_step;
444     } else {
445         LOGE(LOG_TAG, "%s:%d, invalid pcm->sw_params or p", __func__, __LINE__);
446         return PCM_RETURN_ERR;
447     }
448     PCM_LOCK(pcm);
449     params.hdl = &pcm->evt;
450     params.period = p->period_step;
451     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_SW_PARAMS, &params)) {
452         LOGE(LOG_TAG, "%s:%d, cannot set sw params", __func__, __LINE__);
453         ret = PCM_RETURN_ERR;
454     }
455     PCM_UNLOCK(pcm);
456     return ret;
457 }
458 
aos_pcm_set_params(aos_pcm_t * pcm,aos_pcm_format_t format,aos_pcm_access_t access,unsigned int channels,unsigned int rate,int soft_resample,unsigned int latency)459 int aos_pcm_set_params(aos_pcm_t *pcm, aos_pcm_format_t format, aos_pcm_access_t access, unsigned int channels,
460                        unsigned int rate, int soft_resample, unsigned int latency)
461 {
462     int ret = PCM_RETURN_SUCCESS;
463     audio_hw_params_t params;
464     if(NULL == pcm) {
465         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
466         return PCM_RETURN_ERR;
467     }
468     if(pcm->fd < 0) {
469         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
470         return PCM_RETURN_ERR;
471     }
472     if (!pcm->hw_params) {
473         pcm->hw_params = aos_zalloc(sizeof(aos_pcm_hw_params_t));
474 
475         if (pcm->hw_params == NULL) {
476             return PCM_RETURN_ERR;
477         }
478     }
479     pcm->hw_params->access = access;
480     pcm->hw_params->channels = channels;
481     pcm->hw_params->format = format;
482     pcm->hw_params->rate = rate;
483     pcm->hw_params->sample_bits = format * 8;
484     pcm->hw_params->frame_bits = format * 8 * channels;
485 
486     params.block = (pcm->mode & AOS_PCM_NONBLOCK) ? 0 : 1;
487     params.interleave = (access == AOS_PCM_ACCESS_RW_NONINTERLEAVED) ? 0 : 1;
488     params.channels = channels;
489     params.rate = rate;
490     switch(format) {
491         case AOSRV_PCM_FORMAT_S8:
492             params.sample_bits = 8;
493             break;
494         case AOSRV_PCM_FORMAT_S16_LE:
495             params.sample_bits = 16;
496             break;
497         case AOSRV_PCM_FORMAT_S24_LE:
498             params.sample_bits = 24;
499             break;
500         case AOSRV_PCM_FORMAT_S32_LE:
501             params.sample_bits = 32;
502             break;
503         default:
504             return PCM_RETURN_ERR;
505     }
506     PCM_LOCK(pcm);
507     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_HW_PARAMS, &params)) {
508         LOGE(LOG_TAG, "%s:%d, cannot set hw params", __func__, __LINE__);
509         ret = PCM_RETURN_ERR;
510     }
511     PCM_UNLOCK(pcm);
512     LOGD(LOG_TAG, "%s:%d, block %d, interleave %d, rate %d channels %d bits %d", __func__, __LINE__, params.block,
513          params.interleave, params.rate, params.channels, params.sample_bits);
514     return ret;
515 }
516 
aos_pcm_writei(aos_pcm_t * pcm,const void * buffer,aos_pcm_uframes_t size)517 aos_pcm_sframes_t aos_pcm_writei(aos_pcm_t *pcm, const void *buffer, aos_pcm_uframes_t size)
518 {
519     audio_xferi_t x;
520     if(NULL == pcm) {
521         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
522         return PCM_RETURN_ERR;
523     }
524     if(pcm->fd < 0) {
525         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
526         return PCM_RETURN_ERR;
527     }
528     if(pcm->state != AOS_PCM_STATE_RUNNING) {
529         LOGE(LOG_TAG, "%s:%d, unexpected pcm state %d", __func__, __LINE__, pcm->state);
530         return PCM_RETURN_ERR;
531     }
532     if(pcm->stream != AOS_PCM_STREAM_PLAYBACK) {
533         LOGE(LOG_TAG, "%s:%d, not playback device", __func__, __LINE__);
534         return PCM_RETURN_ERR;
535     }
536     PCM_LOCK(pcm);
537     x.buf = (void*)buffer;
538     x.frames = size;
539     x.result = 0;
540     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_WRITEI_FRAMES, &x)) {
541         LOGE(LOG_TAG, "%s:%d, ioctl writei failed", __func__, __LINE__);
542     }
543     PCM_UNLOCK(pcm);
544     //LOGE(LOG_TAG, "%s:%d, frames %d result %d", __func__, __LINE__, x.frames, x.result);
545     return x.result;
546 }
547 
aos_pcm_writen(aos_pcm_t * pcm,void ** bufs,aos_pcm_uframes_t size)548 aos_pcm_sframes_t aos_pcm_writen(aos_pcm_t *pcm, void **bufs, aos_pcm_uframes_t size)
549 {
550     audio_xfern_t x;
551     if(NULL == pcm) {
552         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
553         return PCM_RETURN_ERR;
554     }
555     if(pcm->fd < 0) {
556         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
557         return PCM_RETURN_ERR;
558     }
559     if(pcm->state != AOS_PCM_STATE_RUNNING) {
560         LOGE(LOG_TAG, "%s:%d, unexpected pcm state %d", __func__, __LINE__, pcm->state);
561         return PCM_RETURN_ERR;
562     }
563     if(pcm->stream != AOS_PCM_STREAM_PLAYBACK) {
564         LOGE(LOG_TAG, "%s:%d, not playback device", __func__, __LINE__);
565         return PCM_RETURN_ERR;
566     }
567     PCM_LOCK(pcm);
568     x.bufs = bufs;
569     x.frames = size;
570     x.result = 0;
571     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_WRITEN_FRAMES, &x)) {
572         LOGE(LOG_TAG, "%s:%d, ioctl writen failed", __func__, __LINE__);
573     }
574     PCM_UNLOCK(pcm);
575     //LOGE(LOG_TAG, "%s:%d, frames %d result %d", __func__, __LINE__, x.frames, x.result);
576     return x.result;
577 }
578 
aos_pcm_readi(aos_pcm_t * pcm,void * buffer,aos_pcm_uframes_t size)579 aos_pcm_sframes_t aos_pcm_readi(aos_pcm_t *pcm, void *buffer, aos_pcm_uframes_t size)
580 {
581     audio_xferi_t x;
582     if(NULL == pcm) {
583         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
584         return PCM_RETURN_ERR;
585     }
586     if(pcm->fd < 0) {
587         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
588         return PCM_RETURN_ERR;
589     }
590     if(pcm->state != AOS_PCM_STATE_RUNNING) {
591         LOGE(LOG_TAG, "%s:%d, unexpected pcm state %d", __func__, __LINE__, pcm->state);
592         return PCM_RETURN_ERR;
593     }
594     if(pcm->stream != AOS_PCM_STREAM_CAPTURE) {
595         LOGE(LOG_TAG, "%s:%d, not capture device", __func__, __LINE__);
596         return PCM_RETURN_ERR;
597     }
598     PCM_LOCK(pcm);
599     x.buf = (void*)buffer;
600     x.frames = size;
601     x.result = 0;
602     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_READI_FRAMES, &x)) {
603         LOGE(LOG_TAG, "%s:%d, ioctl readi failed", __func__, __LINE__);
604     }
605     PCM_UNLOCK(pcm);
606     return x.result;
607 }
608 
aos_pcm_readn(aos_pcm_t * pcm,void ** bufs,aos_pcm_uframes_t size)609 aos_pcm_sframes_t aos_pcm_readn(aos_pcm_t *pcm, void **bufs, aos_pcm_uframes_t size)
610 {
611     audio_xfern_t x;
612     if(NULL == pcm) {
613         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
614         return PCM_RETURN_ERR;
615     }
616     if(pcm->fd < 0) {
617         LOGE(LOG_TAG, "%s:%d, param fd is not opened", __func__, __LINE__);
618         return PCM_RETURN_ERR;
619     }
620     if(pcm->state != AOS_PCM_STATE_RUNNING) {
621         LOGE(LOG_TAG, "%s:%d, unexpected pcm state %d", __func__, __LINE__, pcm->state);
622         return PCM_RETURN_ERR;
623     }
624     if(pcm->stream != AOS_PCM_STREAM_CAPTURE) {
625         LOGE(LOG_TAG, "%s:%d, not capture device", __func__, __LINE__);
626         return PCM_RETURN_ERR;
627     }
628     PCM_LOCK(pcm);
629     x.bufs = bufs;
630     x.frames = size;
631     x.result = 0;
632     if(ioctl(pcm->fd, AUDIO_PCM_IOCTL_READN_FRAMES, &x)) {
633         LOGE(LOG_TAG, "%s:%d, ioctl readn failed", __func__, __LINE__);
634     }
635     PCM_UNLOCK(pcm);
636     return x.result;
637 }
638 
aos_pcm_bytes_to_frames(aos_pcm_t * pcm,int bytes)639 aos_pcm_sframes_t aos_pcm_bytes_to_frames(aos_pcm_t *pcm, int bytes)
640 {
641     if(!pcm) {
642         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
643         return PCM_RETURN_ERR;
644     }
645 
646     return (bytes / (pcm->hw_params->frame_bits / 8));
647 }
648 
aos_pcm_frames_to_bytes(aos_pcm_t * pcm,aos_pcm_sframes_t frames)649 int aos_pcm_frames_to_bytes(aos_pcm_t *pcm, aos_pcm_sframes_t frames)
650 {
651     if(!pcm) {
652         LOGE(LOG_TAG, "%s:%d, param pcm is null", __func__, __LINE__);
653         return PCM_RETURN_ERR;
654     }
655     return (frames * (pcm->hw_params->frame_bits / 8));
656 }