blob: 88af9bef27a2891973d8e37ca021d47ae9777f5b [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;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800130 int *rates_supported;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700131 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
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800249 rates_supported = (int *)malloc(sizeof(int) * size);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700250 next_sr_string = strtok_r(rates_str_for_val, " ,", &temp_ptr);
251 if (next_sr_string == NULL) {
252 ALOGE("%s: error could not get first rate val", __func__);
253 close(fd);
254 free(rates_str_for_val);
255 free(rates_str);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800256 free(rates_supported);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700257 free(read_buf);
258 return -EINVAL;
259 }
260
261 rates_supported[0] = atoi(next_sr_string);
262 ALOGD("%s: rates_supported[0] for playback: %d",
263 __func__, rates_supported[0]);
264 for (i = 1; i<size; i++) {
265 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
266 rates_supported[i] = atoi(next_sr_string);
267 ALOGD("rates_supported[%d] for playback: %d",i, rates_supported[i]);
268 }
269
270 for (i = 0; i<size; i++) {
271 if ((rates_supported[i] > *sample_rate) &&
272 (rates_supported[i] <= 48000)) {
273 /* Sample Rate should be one of the proxy supported rates only
274 This is because proxy port is used to read from/write to DSP */
275 if ((rates_supported[i] == USB_PROXY_RATE_8000) ||
276 (rates_supported[i] == USB_PROXY_RATE_16000) ||
277 (rates_supported[i] == USB_PROXY_RATE_48000)) {
278 *sample_rate = rates_supported[i];
279 }
280 }
281 }
282 ALOGD("%s: sample_rate: %d", __func__, *sample_rate);
283
284 close(fd);
285 free(rates_str_for_val);
286 free(rates_str);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800287 free(rates_supported);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700288 free(read_buf);
289 return 0;
290}
291
292static int32_t usb_playback_entry(void *adev)
293{
294 unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
295 int32_t ret, bytes, proxy_open_retry_count;
296
297 ALOGD("%s: entry", __func__);
298 /* update audio device pointer */
299 usbmod->adev = (struct audio_device*)adev;
300 proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
301
302 /* get capabilities */
303 pthread_mutex_lock(&usbmod->usb_playback_lock);
304 ret = usb_get_capability((char *)"Playback:",
305 &usbmod->channels_playback, &usbmod->sample_rate_playback);
306 if (ret) {
307 ALOGE("%s: could not get playback capabilities from usb device",
308 __func__);
309 pthread_mutex_unlock(&usbmod->usb_playback_lock);
310 return -EINVAL;
311 }
312 /* update config for usb
313 1 pcm frame(sample)= 4 bytes since two channels*/
314 pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
315 pcm_config_usbmod.channels = usbmod->channels_playback;
316 pcm_config_usbmod.rate = usbmod->sample_rate_playback;
317 ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
318 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
319 pcm_config_usbmod.rate);
320
321 usbmod->usb_pcm_playback_handle = pcm_open(usbmod->usb_card, \
322 usbmod->usb_device_id, PCM_OUT |
323 PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
324
325 if ((usbmod->usb_pcm_playback_handle \
326 && !pcm_is_ready(usbmod->usb_pcm_playback_handle))
327 || (!usbmod->is_playback_running)) {
328 ALOGE("%s: failed: %s", __func__,
329 pcm_get_error(usbmod->usb_pcm_playback_handle));
330 pcm_close(usbmod->usb_pcm_playback_handle);
331 usbmod->usb_pcm_playback_handle = NULL;
332 pthread_mutex_unlock(&usbmod->usb_playback_lock);
333 return -ENOMEM;
334 }
335 ALOGD("%s: USB configured for playback", __func__);
336
337 /* update config for proxy*/
338 pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/3;
339 pcm_config_usbmod.rate = usbmod->sample_rate_playback;
340 pcm_config_usbmod.channels = usbmod->channels_playback;
341 pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT;
342 usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
343 ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
344 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
345 pcm_config_usbmod.rate);
346
347 while(proxy_open_retry_count){
348 usbmod->proxy_pcm_playback_handle = pcm_open(usbmod->proxy_card,
349 usbmod->proxy_device_id, PCM_IN |
350 PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
351 if(!usbmod->proxy_pcm_playback_handle){
352 proxy_open_retry_count--;
353 usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
354 ALOGE("%s: pcm_open for proxy failed retrying = %d",
355 __func__, proxy_open_retry_count);
356 }
357 else{
358 break;
359 }
360 }
361
362 if ((usbmod->proxy_pcm_playback_handle
363 && !pcm_is_ready(usbmod->proxy_pcm_playback_handle))
364 || (!usbmod->is_playback_running)) {
365 ALOGE("%s: failed: %s", __func__,
366 pcm_get_error(usbmod->proxy_pcm_playback_handle));
367 pcm_close(usbmod->proxy_pcm_playback_handle);
368 usbmod->proxy_pcm_playback_handle = NULL;
369 pthread_mutex_unlock(&usbmod->usb_playback_lock);
370 return -ENOMEM;
371 }
372 ALOGD("%s: PROXY configured for playback", __func__);
373 pthread_mutex_unlock(&usbmod->usb_playback_lock);
374
375 /* main loop to read from proxy and write to usb */
376 while (usbmod->is_playback_running) {
377 /* read data from proxy */
378 ret = pcm_mmap_read(usbmod->proxy_pcm_playback_handle,
379 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
380 /* Write to usb */
381 ret = pcm_mmap_write(usbmod->usb_pcm_playback_handle,
382 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
383 if(!usbmod->is_playback_running)
384 break;
385
386 memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
387 } /* main loop end */
388
389 ALOGD("%s: exiting USB playback thread",__func__);
390 return 0;
391}
392
393static void* usb_playback_launcher(void *adev)
394{
395 int32_t ret;
396
397 usbmod->is_playback_running = true;
398 ret = usb_playback_entry(adev);
399
400 if (ret) {
401 ALOGE("%s: failed with err:%d", __func__, ret);
402 usbmod->is_playback_running = false;
403 }
404 return NULL;
405}
406
407static int32_t usb_record_entry(void *adev)
408{
409 unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
410 int32_t ret, bytes, proxy_open_retry_count;
411 ALOGD("%s: entry", __func__);
412
413 /* update audio device pointer */
414 usbmod->adev = (struct audio_device*)adev;
415 proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
416
417 /* get capabilities */
418 pthread_mutex_lock(&usbmod->usb_record_lock);
419 ret = usb_get_capability((char *)"Capture:",
420 &usbmod->channels_record, &usbmod->sample_rate_record);
421 if (ret) {
422 ALOGE("%s: could not get capture capabilities from usb device",
423 __func__);
424 pthread_mutex_unlock(&usbmod->usb_record_lock);
425 return -EINVAL;
426 }
427 /* update config for usb
428 1 pcm frame(sample)= 4 bytes since two channels*/
429 pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
430 pcm_config_usbmod.channels = usbmod->channels_record;
431 pcm_config_usbmod.rate = usbmod->sample_rate_record;
432 ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
433 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
434 pcm_config_usbmod.rate);
435
436 usbmod->usb_pcm_record_handle = pcm_open(usbmod->usb_card, \
437 usbmod->usb_device_id, PCM_IN |
438 PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
439
440 if ((usbmod->usb_pcm_record_handle \
441 && !pcm_is_ready(usbmod->usb_pcm_record_handle))
442 || (!usbmod->is_record_running)) {
443 ALOGE("%s: failed: %s", __func__,
444 pcm_get_error(usbmod->usb_pcm_record_handle));
445 pcm_close(usbmod->usb_pcm_record_handle);
446 usbmod->usb_pcm_record_handle = NULL;
447 pthread_mutex_unlock(&usbmod->usb_record_lock);
448 return -ENOMEM;
449 }
450 ALOGD("%s: USB configured for capture", __func__);
451
452 /* update config for proxy*/
453 pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/4;
454 pcm_config_usbmod.rate = usbmod->sample_rate_record;
455 pcm_config_usbmod.channels = usbmod->channels_record;
456 pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT * 2;
457 usbmod->proxy_device_id = AFE_PROXY_CAPTURE_DEVICE;
458 ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
459 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
460 pcm_config_usbmod.rate);
461
462 while(proxy_open_retry_count){
463 usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
464 usbmod->proxy_device_id, PCM_OUT |
465 PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
466 if(!usbmod->proxy_pcm_record_handle){
467 proxy_open_retry_count--;
468 usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
469 ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
470 __func__, proxy_open_retry_count);
471 }
472 else{
473 break;
474 }
475 }
476 if ((usbmod->proxy_pcm_record_handle
477 && !pcm_is_ready(usbmod->proxy_pcm_record_handle))
478 || (!usbmod->is_record_running)) {
479 ALOGE("%s: failed: %s", __func__,
480 pcm_get_error(usbmod->proxy_pcm_record_handle));
481 pcm_close(usbmod->proxy_pcm_record_handle);
482 usbmod->proxy_pcm_record_handle = NULL;
483 pthread_mutex_unlock(&usbmod->usb_record_lock);
484 return -ENOMEM;
485 }
486 ALOGD("%s: PROXY configured for capture", __func__);
487 pthread_mutex_unlock(&usbmod->usb_record_lock);
488
489 /* main loop to read from usb and write to proxy */
490 while (usbmod->is_record_running) {
491 /* read data from usb */
492 ret = pcm_mmap_read(usbmod->usb_pcm_record_handle,
493 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
494 /* Write to proxy */
495 ret = pcm_mmap_write(usbmod->proxy_pcm_record_handle,
496 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
497 if(!usbmod->is_record_running)
498 break;
499
500 memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
501 } /* main loop end */
502
503 ALOGD("%s: exiting USB capture thread",__func__);
504 return 0;
505}
506
507static void* usb_capture_launcher(void *adev)
508{
509 int32_t ret;
510
511 usbmod->is_record_running = true;
512 ret = usb_record_entry(adev);
513
514 if (ret) {
515 ALOGE("%s: failed with err:%d", __func__, ret);
516 usbmod->is_record_running = false;
517 }
518 return NULL;
519}
520
521void audio_extn_usb_init(void *adev)
522{
523 pthread_once(&alloc_usbmod_once_ctl, usb_alloc);
524
525 usbmod->is_playback_running = false;
526 usbmod->is_record_running = false;
527
528 usbmod->usb_pcm_playback_handle = NULL;
529 usbmod->proxy_pcm_playback_handle = NULL;
530
531 usbmod->usb_pcm_record_handle = NULL;
532 usbmod->proxy_pcm_record_handle = NULL;
533
534 usbmod->usb_card = 1;
535 usbmod->usb_device_id = 0;
536 usbmod->proxy_card = 0;
537 usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
538 usbmod->adev = (struct audio_device*)adev;
539}
540
541void audio_extn_usb_deinit()
542{
543 if (NULL != usbmod){
544 free(usbmod);
545 usbmod = NULL;
546 }
547}
548
549void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)
550{
551 /* Proxy port and USB headset are related to two different sound cards */
552 if (sndcard_idx == usbmod->usb_card) {
553 usbmod->usb_card = usbmod->proxy_card;
554 }
555
556 usbmod->proxy_card = sndcard_idx;
557}
558
559void audio_extn_usb_start_playback(void *adev)
560{
561 int32_t ret;
562
563 if (NULL == usbmod){
564 ALOGE("%s: USB device object is NULL", __func__);
565 return;
566 }
567
568 if (usbmod->is_playback_running){
569 ALOGE("%s: USB playback thread already running", __func__);
570 return;
571 }
572
573 ALOGD("%s: creating USB playback thread", __func__);
574 ret = pthread_create(&usbmod->usb_playback_thr, NULL,
575 usb_playback_launcher, (void*)adev);
576 if (ret)
577 ALOGE("%s: failed to create USB playback thread with err:%d",
578 __func__, ret);
579}
580
581void audio_extn_usb_stop_playback()
582{
583 int32_t ret;
584 ALOGD("%s: entry", __func__);
585
586 usbmod->is_playback_running = false;
587 if (NULL != usbmod->proxy_pcm_playback_handle)
588 pcm_stop(usbmod->proxy_pcm_playback_handle);
589
590 if (NULL != usbmod->usb_pcm_playback_handle)
591 pcm_stop(usbmod->usb_pcm_playback_handle);
592
593 if(usbmod->usb_playback_thr) {
594 ret = pthread_join(usbmod->usb_playback_thr,NULL);
595 ALOGE("%s: return for pthread_join = %d", __func__, ret);
596 usbmod->usb_playback_thr = (pthread_t)NULL;
597 }
598
599 pthread_mutex_lock(&usbmod->usb_playback_lock);
600 if (NULL != usbmod->usb_pcm_playback_handle){
601 pcm_close(usbmod->usb_pcm_playback_handle);
602 usbmod->usb_pcm_playback_handle = NULL;
603 }
604
605 if (NULL != usbmod->proxy_pcm_playback_handle){
606 pcm_close(usbmod->proxy_pcm_playback_handle);
607 usbmod->proxy_pcm_playback_handle = NULL;
608 }
609 pthread_mutex_unlock(&usbmod->usb_playback_lock);
610
611 ALOGD("%s: exiting",__func__);
612}
613
614void audio_extn_usb_start_capture(void *adev)
615{
616 int32_t ret;
617
618 if (NULL == usbmod){
619 ALOGE("%s: USB device object is NULL", __func__);
620 return;
621 }
622
623 if (usbmod->is_record_running){
624 ALOGE("%s: USB capture thread already running", __func__);
625 return;
626 }
627
628 ALOGD("%s: creating USB capture thread", __func__);
629 ret = pthread_create(&usbmod->usb_record_thr, NULL,
630 usb_capture_launcher, (void*)adev);
631 if (ret)
632 ALOGE("%s: failed to create USB capture thread with err:%d",
633 __func__, ret);
634}
635
636void audio_extn_usb_stop_capture()
637{
638 int32_t ret;
639 ALOGD("%s: entry", __func__);
640
641 usbmod->is_record_running = false;
642 if (NULL != usbmod->proxy_pcm_record_handle)
643 pcm_stop(usbmod->proxy_pcm_record_handle);
644
645 if (NULL != usbmod->usb_pcm_record_handle)
646 pcm_stop(usbmod->usb_pcm_record_handle);
647
648 if(usbmod->usb_record_thr) {
649 ret = pthread_join(usbmod->usb_record_thr,NULL);
650 ALOGE("%s: return for pthread_join = %d", __func__, ret);
651 usbmod->usb_record_thr = (pthread_t)NULL;
652 }
653
654 pthread_mutex_lock(&usbmod->usb_record_lock);
655 if (NULL != usbmod->usb_pcm_record_handle){
656 pcm_close(usbmod->usb_pcm_record_handle);
657 usbmod->usb_pcm_record_handle = NULL;
658 }
659
660 if (NULL != usbmod->proxy_pcm_record_handle){
661 pcm_close(usbmod->proxy_pcm_record_handle);
662 usbmod->proxy_pcm_record_handle = NULL;
663 }
664 pthread_mutex_unlock(&usbmod->usb_record_lock);
665
666 ALOGD("%s: exiting",__func__);
667}
668
669bool audio_extn_usb_is_proxy_inuse()
670{
671 if( usbmod->is_record_running || usbmod->is_playback_running)
672 return true;
673 else
674 return false;
675}
676#endif /*USB_HEADSET_ENABLED end*/