blob: 5b045ea739b156a04873222b5ed5d73d9271f3bb [file] [log] [blame]
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001/*
2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_usb"
21#define LOG_NDEBUG 0
22#define LOG_NDDEBUG 0
23
24#include <errno.h>
25#include <pthread.h>
26#include <stdlib.h>
27#include <cutils/log.h>
28#include <cutils/str_parms.h>
29#include <sys/ioctl.h>
30#include <fcntl.h>
31#include <sys/stat.h>
32
33#include <system/audio.h>
34#include <tinyalsa/asoundlib.h>
35
36#ifdef USB_HEADSET_ENABLED
37#define USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE 512
38#define USB_LOW_LATENCY_OUTPUT_PERIOD_COUNT 8
39#define USB_DEFAULT_OUTPUT_SAMPLING_RATE 48000
40
41#define USB_PROXY_DEFAULT_SAMPLING_RATE 48000
42#define USB_PROXY_OPEN_RETRY_COUNT 100
43#define USB_PROXY_OPEN_WAIT_TIME 20
44#define USB_PROXY_PERIOD_SIZE 3072
45#define USB_PROXY_RATE_8000 8000
46#define USB_PROXY_RATE_16000 16000
47#define USB_PROXY_RATE_48000 48000
48#define USB_PERIOD_SIZE 2048
49#define USB_BUFF_SIZE 2048
50#define AFE_PROXY_PERIOD_COUNT 32
51#define AFE_PROXY_PLAYBACK_DEVICE 8
52#define AFE_PROXY_CAPTURE_DEVICE 7
53
54struct usb_module {
55 uint32_t usb_card;
56 uint32_t proxy_card;
57 uint32_t usb_device_id;
58 uint32_t proxy_device_id;
59
60 int32_t channels_playback;
61 int32_t sample_rate_playback;
62 int32_t channels_record;
63 int32_t sample_rate_record;
64
65 bool is_playback_running;
66 bool is_record_running;
67
68 pthread_t usb_playback_thr;
69 pthread_t usb_record_thr;
70 pthread_mutex_t usb_playback_lock;
71 pthread_mutex_t usb_record_lock;
72
73 struct pcm *proxy_pcm_playback_handle;
74 struct pcm *usb_pcm_playback_handle;
75 struct pcm *proxy_pcm_record_handle;
76 struct pcm *usb_pcm_record_handle;
77 struct audio_device *adev;
78};
79
80static struct usb_module *usbmod = NULL;
81static pthread_once_t alloc_usbmod_once_ctl = PTHREAD_ONCE_INIT;
82
83struct pcm_config pcm_config_usbmod = {
84 .channels = 2,
85 .rate = USB_DEFAULT_OUTPUT_SAMPLING_RATE,
86 .period_size = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE,
87 .period_count = USB_LOW_LATENCY_OUTPUT_PERIOD_COUNT,
88 .format = PCM_FORMAT_S16_LE,
89 .start_threshold = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
90 .stop_threshold = INT_MAX,
91 .avail_min = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
92};
93
94static void usb_alloc()
95{
96 usbmod = calloc(1, sizeof(struct usb_module));
97}
98
99static int usb_get_numof_rates(char *rates_str)
100{
101 int i, size = 0;
102 char *next_sr_string, *temp_ptr;
103 next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);
104
105 if (next_sr_string == NULL) {
106 ALOGE("%s: get_numof_rates: could not find rates string", __func__);
107 return (int)NULL;
108 }
109
110 for (i = 1; next_sr_string != NULL; i++) {
111 size ++;
112 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
113 }
114 return size;
115}
116
117static int usb_get_capability(char *type, int32_t *channels,
118 int32_t *sample_rate)
119{
120 ALOGD("%s: for %s", __func__, type);
121 long unsigned file_size;
122 FILE *fp;
123 char *buffer;
124 int32_t err = 1;
125 int32_t size = 0;
126 int32_t fd, i, channels_playback;
127 char *read_buf, *str_start, *channel_start, *rates_str, *rates_str_for_val,
128 *rates_str_start, *next_sr_str, *test, *next_sr_string, *temp_ptr;
129 struct stat st;
130 int rates_supported[size];
131 char path[128];
132
133 memset(&st, 0x0, sizeof(struct stat));
134 *sample_rate = 0;
135 snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
136 usbmod->usb_card);
137
138 fd = open(path, O_RDONLY);
139 if (fd <0) {
140 ALOGE("%s: error failed to open config file %s error: %d\n",
141 __func__, path, errno);
142 close(fd);
143 return -EINVAL;
144 }
145
146 if (fstat(fd, &st) < 0) {
147 ALOGE("%s: error failed to stat %s error %d\n",
148 __func__, path, errno);
149 close(fd);
150 return -EINVAL;
151 }
152
153 file_size = st.st_size;
154
155 read_buf = (char *)calloc(1, USB_BUFF_SIZE);
156 err = read(fd, read_buf, USB_BUFF_SIZE);
157 str_start = strstr(read_buf, type);
158 if (str_start == NULL) {
159 ALOGE("%s: error %s section not found in usb config file",
160 __func__, type);
161 close(fd);
162 free(read_buf);
163 return -EINVAL;
164 }
165
166 channel_start = strstr(str_start, "Channels:");
167 if (channel_start == NULL) {
168 ALOGE("%s: error could not find Channels information", __func__);
169 close(fd);
170 free(read_buf);
171 return -EINVAL;
172 }
173
174 channel_start = strstr(channel_start, " ");
175 if (channel_start == NULL) {
176 ALOGE("%s: error channel section not found in usb config file",
177 __func__);
178 close(fd);
179 free(read_buf);
180 return -EINVAL;
181 }
182
183 channels_playback = atoi(channel_start);
184 if (channels_playback == 1) {
185 *channels = 1;
186 } else {
187 *channels = 2;
188 }
189
190 ALOGD("%s: channels supported by device: %d", __func__, *channels);
191 rates_str_start = strstr(str_start, "Rates:");
192 if (rates_str_start == NULL) {
193 ALOGE("%s: error cant find rates information", __func__);
194 close(fd);
195 free(read_buf);
196 return -EINVAL;
197 }
198
199 rates_str_start = strstr(rates_str_start, " ");
200 if (rates_str_start == NULL) {
201 ALOGE("%s: error channel section not found in usb config file",
202 __func__);
203 close(fd);
204 free(read_buf);
205 return -EINVAL;
206 }
207
208 char *target = strchr(rates_str_start, '\n');
209 if (target == NULL) {
210 ALOGE("%s: error end of line not found", __func__);
211 close(fd);
212 free(read_buf);
213 return -EINVAL;
214 }
215
216 size = target - rates_str_start;
217 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
218 ALOGE("%s: error unable to allocate memory to hold sample rate strings",
219 __func__);
220 close(fd);
221 free(read_buf);
222 return -ENOMEM;
223 }
224
225 if ((rates_str_for_val = (char *)malloc(size + 1)) == NULL) {
226 ALOGE("%s: error unable to allocate memory to hold sample rate string",
227 __func__);
228 close(fd);
229 free(rates_str);
230 free(read_buf);
231 return -ENOMEM;
232 }
233
234 memcpy(rates_str, rates_str_start, size);
235 memcpy(rates_str_for_val, rates_str_start, size);
236 rates_str[size] = '\0';
237 rates_str_for_val[size] = '\0';
238
239 size = usb_get_numof_rates(rates_str);
240 if (!size) {
241 ALOGE("%s: error could not get rate size, returning", __func__);
242 close(fd);
243 free(rates_str_for_val);
244 free(rates_str);
245 free(read_buf);
246 return -EINVAL;
247 }
248
249 next_sr_string = strtok_r(rates_str_for_val, " ,", &temp_ptr);
250 if (next_sr_string == NULL) {
251 ALOGE("%s: error could not get first rate val", __func__);
252 close(fd);
253 free(rates_str_for_val);
254 free(rates_str);
255 free(read_buf);
256 return -EINVAL;
257 }
258
259 rates_supported[0] = atoi(next_sr_string);
260 ALOGD("%s: rates_supported[0] for playback: %d",
261 __func__, rates_supported[0]);
262 for (i = 1; i<size; i++) {
263 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
264 rates_supported[i] = atoi(next_sr_string);
265 ALOGD("rates_supported[%d] for playback: %d",i, rates_supported[i]);
266 }
267
268 for (i = 0; i<size; i++) {
269 if ((rates_supported[i] > *sample_rate) &&
270 (rates_supported[i] <= 48000)) {
271 /* Sample Rate should be one of the proxy supported rates only
272 This is because proxy port is used to read from/write to DSP */
273 if ((rates_supported[i] == USB_PROXY_RATE_8000) ||
274 (rates_supported[i] == USB_PROXY_RATE_16000) ||
275 (rates_supported[i] == USB_PROXY_RATE_48000)) {
276 *sample_rate = rates_supported[i];
277 }
278 }
279 }
280 ALOGD("%s: sample_rate: %d", __func__, *sample_rate);
281
282 close(fd);
283 free(rates_str_for_val);
284 free(rates_str);
285 free(read_buf);
286 return 0;
287}
288
289static int32_t usb_playback_entry(void *adev)
290{
291 unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
292 int32_t ret, bytes, proxy_open_retry_count;
293
294 ALOGD("%s: entry", __func__);
295 /* update audio device pointer */
296 usbmod->adev = (struct audio_device*)adev;
297 proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
298
299 /* get capabilities */
300 pthread_mutex_lock(&usbmod->usb_playback_lock);
301 ret = usb_get_capability((char *)"Playback:",
302 &usbmod->channels_playback, &usbmod->sample_rate_playback);
303 if (ret) {
304 ALOGE("%s: could not get playback capabilities from usb device",
305 __func__);
306 pthread_mutex_unlock(&usbmod->usb_playback_lock);
307 return -EINVAL;
308 }
309 /* update config for usb
310 1 pcm frame(sample)= 4 bytes since two channels*/
311 pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
312 pcm_config_usbmod.channels = usbmod->channels_playback;
313 pcm_config_usbmod.rate = usbmod->sample_rate_playback;
314 ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
315 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
316 pcm_config_usbmod.rate);
317
318 usbmod->usb_pcm_playback_handle = pcm_open(usbmod->usb_card, \
319 usbmod->usb_device_id, PCM_OUT |
320 PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
321
322 if ((usbmod->usb_pcm_playback_handle \
323 && !pcm_is_ready(usbmod->usb_pcm_playback_handle))
324 || (!usbmod->is_playback_running)) {
325 ALOGE("%s: failed: %s", __func__,
326 pcm_get_error(usbmod->usb_pcm_playback_handle));
327 pcm_close(usbmod->usb_pcm_playback_handle);
328 usbmod->usb_pcm_playback_handle = NULL;
329 pthread_mutex_unlock(&usbmod->usb_playback_lock);
330 return -ENOMEM;
331 }
332 ALOGD("%s: USB configured for playback", __func__);
333
334 /* update config for proxy*/
335 pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/3;
336 pcm_config_usbmod.rate = usbmod->sample_rate_playback;
337 pcm_config_usbmod.channels = usbmod->channels_playback;
338 pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT;
339 usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
340 ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
341 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
342 pcm_config_usbmod.rate);
343
344 while(proxy_open_retry_count){
345 usbmod->proxy_pcm_playback_handle = pcm_open(usbmod->proxy_card,
346 usbmod->proxy_device_id, PCM_IN |
347 PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
348 if(!usbmod->proxy_pcm_playback_handle){
349 proxy_open_retry_count--;
350 usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
351 ALOGE("%s: pcm_open for proxy failed retrying = %d",
352 __func__, proxy_open_retry_count);
353 }
354 else{
355 break;
356 }
357 }
358
359 if ((usbmod->proxy_pcm_playback_handle
360 && !pcm_is_ready(usbmod->proxy_pcm_playback_handle))
361 || (!usbmod->is_playback_running)) {
362 ALOGE("%s: failed: %s", __func__,
363 pcm_get_error(usbmod->proxy_pcm_playback_handle));
364 pcm_close(usbmod->proxy_pcm_playback_handle);
365 usbmod->proxy_pcm_playback_handle = NULL;
366 pthread_mutex_unlock(&usbmod->usb_playback_lock);
367 return -ENOMEM;
368 }
369 ALOGD("%s: PROXY configured for playback", __func__);
370 pthread_mutex_unlock(&usbmod->usb_playback_lock);
371
372 /* main loop to read from proxy and write to usb */
373 while (usbmod->is_playback_running) {
374 /* read data from proxy */
375 ret = pcm_mmap_read(usbmod->proxy_pcm_playback_handle,
376 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
377 /* Write to usb */
378 ret = pcm_mmap_write(usbmod->usb_pcm_playback_handle,
379 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
380 if(!usbmod->is_playback_running)
381 break;
382
383 memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
384 } /* main loop end */
385
386 ALOGD("%s: exiting USB playback thread",__func__);
387 return 0;
388}
389
390static void* usb_playback_launcher(void *adev)
391{
392 int32_t ret;
393
394 usbmod->is_playback_running = true;
395 ret = usb_playback_entry(adev);
396
397 if (ret) {
398 ALOGE("%s: failed with err:%d", __func__, ret);
399 usbmod->is_playback_running = false;
400 }
401 return NULL;
402}
403
404static int32_t usb_record_entry(void *adev)
405{
406 unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
407 int32_t ret, bytes, proxy_open_retry_count;
408 ALOGD("%s: entry", __func__);
409
410 /* update audio device pointer */
411 usbmod->adev = (struct audio_device*)adev;
412 proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
413
414 /* get capabilities */
415 pthread_mutex_lock(&usbmod->usb_record_lock);
416 ret = usb_get_capability((char *)"Capture:",
417 &usbmod->channels_record, &usbmod->sample_rate_record);
418 if (ret) {
419 ALOGE("%s: could not get capture capabilities from usb device",
420 __func__);
421 pthread_mutex_unlock(&usbmod->usb_record_lock);
422 return -EINVAL;
423 }
424 /* update config for usb
425 1 pcm frame(sample)= 4 bytes since two channels*/
426 pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
427 pcm_config_usbmod.channels = usbmod->channels_record;
428 pcm_config_usbmod.rate = usbmod->sample_rate_record;
429 ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
430 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
431 pcm_config_usbmod.rate);
432
433 usbmod->usb_pcm_record_handle = pcm_open(usbmod->usb_card, \
434 usbmod->usb_device_id, PCM_IN |
435 PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
436
437 if ((usbmod->usb_pcm_record_handle \
438 && !pcm_is_ready(usbmod->usb_pcm_record_handle))
439 || (!usbmod->is_record_running)) {
440 ALOGE("%s: failed: %s", __func__,
441 pcm_get_error(usbmod->usb_pcm_record_handle));
442 pcm_close(usbmod->usb_pcm_record_handle);
443 usbmod->usb_pcm_record_handle = NULL;
444 pthread_mutex_unlock(&usbmod->usb_record_lock);
445 return -ENOMEM;
446 }
447 ALOGD("%s: USB configured for capture", __func__);
448
449 /* update config for proxy*/
450 pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/4;
451 pcm_config_usbmod.rate = usbmod->sample_rate_record;
452 pcm_config_usbmod.channels = usbmod->channels_record;
453 pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT * 2;
454 usbmod->proxy_device_id = AFE_PROXY_CAPTURE_DEVICE;
455 ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
456 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
457 pcm_config_usbmod.rate);
458
459 while(proxy_open_retry_count){
460 usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
461 usbmod->proxy_device_id, PCM_OUT |
462 PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
463 if(!usbmod->proxy_pcm_record_handle){
464 proxy_open_retry_count--;
465 usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
466 ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
467 __func__, proxy_open_retry_count);
468 }
469 else{
470 break;
471 }
472 }
473 if ((usbmod->proxy_pcm_record_handle
474 && !pcm_is_ready(usbmod->proxy_pcm_record_handle))
475 || (!usbmod->is_record_running)) {
476 ALOGE("%s: failed: %s", __func__,
477 pcm_get_error(usbmod->proxy_pcm_record_handle));
478 pcm_close(usbmod->proxy_pcm_record_handle);
479 usbmod->proxy_pcm_record_handle = NULL;
480 pthread_mutex_unlock(&usbmod->usb_record_lock);
481 return -ENOMEM;
482 }
483 ALOGD("%s: PROXY configured for capture", __func__);
484 pthread_mutex_unlock(&usbmod->usb_record_lock);
485
486 /* main loop to read from usb and write to proxy */
487 while (usbmod->is_record_running) {
488 /* read data from usb */
489 ret = pcm_mmap_read(usbmod->usb_pcm_record_handle,
490 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
491 /* Write to proxy */
492 ret = pcm_mmap_write(usbmod->proxy_pcm_record_handle,
493 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
494 if(!usbmod->is_record_running)
495 break;
496
497 memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
498 } /* main loop end */
499
500 ALOGD("%s: exiting USB capture thread",__func__);
501 return 0;
502}
503
504static void* usb_capture_launcher(void *adev)
505{
506 int32_t ret;
507
508 usbmod->is_record_running = true;
509 ret = usb_record_entry(adev);
510
511 if (ret) {
512 ALOGE("%s: failed with err:%d", __func__, ret);
513 usbmod->is_record_running = false;
514 }
515 return NULL;
516}
517
518void audio_extn_usb_init(void *adev)
519{
520 pthread_once(&alloc_usbmod_once_ctl, usb_alloc);
521
522 usbmod->is_playback_running = false;
523 usbmod->is_record_running = false;
524
525 usbmod->usb_pcm_playback_handle = NULL;
526 usbmod->proxy_pcm_playback_handle = NULL;
527
528 usbmod->usb_pcm_record_handle = NULL;
529 usbmod->proxy_pcm_record_handle = NULL;
530
531 usbmod->usb_card = 1;
532 usbmod->usb_device_id = 0;
533 usbmod->proxy_card = 0;
534 usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
535 usbmod->adev = (struct audio_device*)adev;
536}
537
538void audio_extn_usb_deinit()
539{
540 if (NULL != usbmod){
541 free(usbmod);
542 usbmod = NULL;
543 }
544}
545
546void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)
547{
548 /* Proxy port and USB headset are related to two different sound cards */
549 if (sndcard_idx == usbmod->usb_card) {
550 usbmod->usb_card = usbmod->proxy_card;
551 }
552
553 usbmod->proxy_card = sndcard_idx;
554}
555
556void audio_extn_usb_start_playback(void *adev)
557{
558 int32_t ret;
559
560 if (NULL == usbmod){
561 ALOGE("%s: USB device object is NULL", __func__);
562 return;
563 }
564
565 if (usbmod->is_playback_running){
566 ALOGE("%s: USB playback thread already running", __func__);
567 return;
568 }
569
570 ALOGD("%s: creating USB playback thread", __func__);
571 ret = pthread_create(&usbmod->usb_playback_thr, NULL,
572 usb_playback_launcher, (void*)adev);
573 if (ret)
574 ALOGE("%s: failed to create USB playback thread with err:%d",
575 __func__, ret);
576}
577
578void audio_extn_usb_stop_playback()
579{
580 int32_t ret;
581 ALOGD("%s: entry", __func__);
582
583 usbmod->is_playback_running = false;
584 if (NULL != usbmod->proxy_pcm_playback_handle)
585 pcm_stop(usbmod->proxy_pcm_playback_handle);
586
587 if (NULL != usbmod->usb_pcm_playback_handle)
588 pcm_stop(usbmod->usb_pcm_playback_handle);
589
590 if(usbmod->usb_playback_thr) {
591 ret = pthread_join(usbmod->usb_playback_thr,NULL);
592 ALOGE("%s: return for pthread_join = %d", __func__, ret);
593 usbmod->usb_playback_thr = (pthread_t)NULL;
594 }
595
596 pthread_mutex_lock(&usbmod->usb_playback_lock);
597 if (NULL != usbmod->usb_pcm_playback_handle){
598 pcm_close(usbmod->usb_pcm_playback_handle);
599 usbmod->usb_pcm_playback_handle = NULL;
600 }
601
602 if (NULL != usbmod->proxy_pcm_playback_handle){
603 pcm_close(usbmod->proxy_pcm_playback_handle);
604 usbmod->proxy_pcm_playback_handle = NULL;
605 }
606 pthread_mutex_unlock(&usbmod->usb_playback_lock);
607
608 ALOGD("%s: exiting",__func__);
609}
610
611void audio_extn_usb_start_capture(void *adev)
612{
613 int32_t ret;
614
615 if (NULL == usbmod){
616 ALOGE("%s: USB device object is NULL", __func__);
617 return;
618 }
619
620 if (usbmod->is_record_running){
621 ALOGE("%s: USB capture thread already running", __func__);
622 return;
623 }
624
625 ALOGD("%s: creating USB capture thread", __func__);
626 ret = pthread_create(&usbmod->usb_record_thr, NULL,
627 usb_capture_launcher, (void*)adev);
628 if (ret)
629 ALOGE("%s: failed to create USB capture thread with err:%d",
630 __func__, ret);
631}
632
633void audio_extn_usb_stop_capture()
634{
635 int32_t ret;
636 ALOGD("%s: entry", __func__);
637
638 usbmod->is_record_running = false;
639 if (NULL != usbmod->proxy_pcm_record_handle)
640 pcm_stop(usbmod->proxy_pcm_record_handle);
641
642 if (NULL != usbmod->usb_pcm_record_handle)
643 pcm_stop(usbmod->usb_pcm_record_handle);
644
645 if(usbmod->usb_record_thr) {
646 ret = pthread_join(usbmod->usb_record_thr,NULL);
647 ALOGE("%s: return for pthread_join = %d", __func__, ret);
648 usbmod->usb_record_thr = (pthread_t)NULL;
649 }
650
651 pthread_mutex_lock(&usbmod->usb_record_lock);
652 if (NULL != usbmod->usb_pcm_record_handle){
653 pcm_close(usbmod->usb_pcm_record_handle);
654 usbmod->usb_pcm_record_handle = NULL;
655 }
656
657 if (NULL != usbmod->proxy_pcm_record_handle){
658 pcm_close(usbmod->proxy_pcm_record_handle);
659 usbmod->proxy_pcm_record_handle = NULL;
660 }
661 pthread_mutex_unlock(&usbmod->usb_record_lock);
662
663 ALOGD("%s: exiting",__func__);
664}
665
666bool audio_extn_usb_is_proxy_inuse()
667{
668 if( usbmod->is_record_running || usbmod->is_playback_running)
669 return true;
670 else
671 return false;
672}
673#endif /*USB_HEADSET_ENABLED end*/