blob: 699c3b7d3d8de77463d0c6a696638eb09bb4a2ce [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
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800155 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700156 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);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800351 if(usbmod->proxy_pcm_playback_handle
352 && !pcm_is_ready(usbmod->proxy_pcm_playback_handle)){
353 pcm_close(usbmod->proxy_pcm_playback_handle);
354 usbmod->proxy_pcm_playback_handle = NULL;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700355 proxy_open_retry_count--;
356 usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
357 ALOGE("%s: pcm_open for proxy failed retrying = %d",
358 __func__, proxy_open_retry_count);
359 }
360 else{
361 break;
362 }
363 }
364
365 if ((usbmod->proxy_pcm_playback_handle
366 && !pcm_is_ready(usbmod->proxy_pcm_playback_handle))
367 || (!usbmod->is_playback_running)) {
368 ALOGE("%s: failed: %s", __func__,
369 pcm_get_error(usbmod->proxy_pcm_playback_handle));
370 pcm_close(usbmod->proxy_pcm_playback_handle);
371 usbmod->proxy_pcm_playback_handle = NULL;
372 pthread_mutex_unlock(&usbmod->usb_playback_lock);
373 return -ENOMEM;
374 }
375 ALOGD("%s: PROXY configured for playback", __func__);
376 pthread_mutex_unlock(&usbmod->usb_playback_lock);
377
378 /* main loop to read from proxy and write to usb */
379 while (usbmod->is_playback_running) {
380 /* read data from proxy */
381 ret = pcm_mmap_read(usbmod->proxy_pcm_playback_handle,
382 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
383 /* Write to usb */
384 ret = pcm_mmap_write(usbmod->usb_pcm_playback_handle,
385 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
386 if(!usbmod->is_playback_running)
387 break;
388
389 memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
390 } /* main loop end */
391
392 ALOGD("%s: exiting USB playback thread",__func__);
393 return 0;
394}
395
396static void* usb_playback_launcher(void *adev)
397{
398 int32_t ret;
399
400 usbmod->is_playback_running = true;
401 ret = usb_playback_entry(adev);
402
403 if (ret) {
404 ALOGE("%s: failed with err:%d", __func__, ret);
405 usbmod->is_playback_running = false;
406 }
407 return NULL;
408}
409
410static int32_t usb_record_entry(void *adev)
411{
412 unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
413 int32_t ret, bytes, proxy_open_retry_count;
414 ALOGD("%s: entry", __func__);
415
416 /* update audio device pointer */
417 usbmod->adev = (struct audio_device*)adev;
418 proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
419
420 /* get capabilities */
421 pthread_mutex_lock(&usbmod->usb_record_lock);
422 ret = usb_get_capability((char *)"Capture:",
423 &usbmod->channels_record, &usbmod->sample_rate_record);
424 if (ret) {
425 ALOGE("%s: could not get capture capabilities from usb device",
426 __func__);
427 pthread_mutex_unlock(&usbmod->usb_record_lock);
428 return -EINVAL;
429 }
430 /* update config for usb
431 1 pcm frame(sample)= 4 bytes since two channels*/
432 pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
433 pcm_config_usbmod.channels = usbmod->channels_record;
434 pcm_config_usbmod.rate = usbmod->sample_rate_record;
435 ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
436 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
437 pcm_config_usbmod.rate);
438
439 usbmod->usb_pcm_record_handle = pcm_open(usbmod->usb_card, \
440 usbmod->usb_device_id, PCM_IN |
441 PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
442
443 if ((usbmod->usb_pcm_record_handle \
444 && !pcm_is_ready(usbmod->usb_pcm_record_handle))
445 || (!usbmod->is_record_running)) {
446 ALOGE("%s: failed: %s", __func__,
447 pcm_get_error(usbmod->usb_pcm_record_handle));
448 pcm_close(usbmod->usb_pcm_record_handle);
449 usbmod->usb_pcm_record_handle = NULL;
450 pthread_mutex_unlock(&usbmod->usb_record_lock);
451 return -ENOMEM;
452 }
453 ALOGD("%s: USB configured for capture", __func__);
454
455 /* update config for proxy*/
456 pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/4;
457 pcm_config_usbmod.rate = usbmod->sample_rate_record;
458 pcm_config_usbmod.channels = usbmod->channels_record;
459 pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT * 2;
460 usbmod->proxy_device_id = AFE_PROXY_CAPTURE_DEVICE;
461 ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
462 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
463 pcm_config_usbmod.rate);
464
465 while(proxy_open_retry_count){
466 usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
467 usbmod->proxy_device_id, PCM_OUT |
468 PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800469 if(usbmod->proxy_pcm_record_handle
470 && !pcm_is_ready(usbmod->proxy_pcm_record_handle)){
471 pcm_close(usbmod->proxy_pcm_record_handle);
472 usbmod->proxy_pcm_record_handle = NULL;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700473 proxy_open_retry_count--;
474 usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
475 ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
476 __func__, proxy_open_retry_count);
477 }
478 else{
479 break;
480 }
481 }
482 if ((usbmod->proxy_pcm_record_handle
483 && !pcm_is_ready(usbmod->proxy_pcm_record_handle))
484 || (!usbmod->is_record_running)) {
485 ALOGE("%s: failed: %s", __func__,
486 pcm_get_error(usbmod->proxy_pcm_record_handle));
487 pcm_close(usbmod->proxy_pcm_record_handle);
488 usbmod->proxy_pcm_record_handle = NULL;
489 pthread_mutex_unlock(&usbmod->usb_record_lock);
490 return -ENOMEM;
491 }
492 ALOGD("%s: PROXY configured for capture", __func__);
493 pthread_mutex_unlock(&usbmod->usb_record_lock);
494
495 /* main loop to read from usb and write to proxy */
496 while (usbmod->is_record_running) {
497 /* read data from usb */
498 ret = pcm_mmap_read(usbmod->usb_pcm_record_handle,
499 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
500 /* Write to proxy */
501 ret = pcm_mmap_write(usbmod->proxy_pcm_record_handle,
502 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
503 if(!usbmod->is_record_running)
504 break;
505
506 memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
507 } /* main loop end */
508
509 ALOGD("%s: exiting USB capture thread",__func__);
510 return 0;
511}
512
513static void* usb_capture_launcher(void *adev)
514{
515 int32_t ret;
516
517 usbmod->is_record_running = true;
518 ret = usb_record_entry(adev);
519
520 if (ret) {
521 ALOGE("%s: failed with err:%d", __func__, ret);
522 usbmod->is_record_running = false;
523 }
524 return NULL;
525}
526
527void audio_extn_usb_init(void *adev)
528{
529 pthread_once(&alloc_usbmod_once_ctl, usb_alloc);
530
531 usbmod->is_playback_running = false;
532 usbmod->is_record_running = false;
533
534 usbmod->usb_pcm_playback_handle = NULL;
535 usbmod->proxy_pcm_playback_handle = NULL;
536
537 usbmod->usb_pcm_record_handle = NULL;
538 usbmod->proxy_pcm_record_handle = NULL;
539
540 usbmod->usb_card = 1;
541 usbmod->usb_device_id = 0;
542 usbmod->proxy_card = 0;
543 usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
544 usbmod->adev = (struct audio_device*)adev;
545}
546
547void audio_extn_usb_deinit()
548{
549 if (NULL != usbmod){
550 free(usbmod);
551 usbmod = NULL;
552 }
553}
554
555void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)
556{
557 /* Proxy port and USB headset are related to two different sound cards */
558 if (sndcard_idx == usbmod->usb_card) {
559 usbmod->usb_card = usbmod->proxy_card;
560 }
561
562 usbmod->proxy_card = sndcard_idx;
563}
564
565void audio_extn_usb_start_playback(void *adev)
566{
567 int32_t ret;
568
569 if (NULL == usbmod){
570 ALOGE("%s: USB device object is NULL", __func__);
571 return;
572 }
573
574 if (usbmod->is_playback_running){
575 ALOGE("%s: USB playback thread already running", __func__);
576 return;
577 }
578
579 ALOGD("%s: creating USB playback thread", __func__);
580 ret = pthread_create(&usbmod->usb_playback_thr, NULL,
581 usb_playback_launcher, (void*)adev);
582 if (ret)
583 ALOGE("%s: failed to create USB playback thread with err:%d",
584 __func__, ret);
585}
586
587void audio_extn_usb_stop_playback()
588{
589 int32_t ret;
590 ALOGD("%s: entry", __func__);
591
592 usbmod->is_playback_running = false;
593 if (NULL != usbmod->proxy_pcm_playback_handle)
594 pcm_stop(usbmod->proxy_pcm_playback_handle);
595
596 if (NULL != usbmod->usb_pcm_playback_handle)
597 pcm_stop(usbmod->usb_pcm_playback_handle);
598
599 if(usbmod->usb_playback_thr) {
600 ret = pthread_join(usbmod->usb_playback_thr,NULL);
601 ALOGE("%s: return for pthread_join = %d", __func__, ret);
602 usbmod->usb_playback_thr = (pthread_t)NULL;
603 }
604
605 pthread_mutex_lock(&usbmod->usb_playback_lock);
606 if (NULL != usbmod->usb_pcm_playback_handle){
607 pcm_close(usbmod->usb_pcm_playback_handle);
608 usbmod->usb_pcm_playback_handle = NULL;
609 }
610
611 if (NULL != usbmod->proxy_pcm_playback_handle){
612 pcm_close(usbmod->proxy_pcm_playback_handle);
613 usbmod->proxy_pcm_playback_handle = NULL;
614 }
615 pthread_mutex_unlock(&usbmod->usb_playback_lock);
616
617 ALOGD("%s: exiting",__func__);
618}
619
620void audio_extn_usb_start_capture(void *adev)
621{
622 int32_t ret;
623
624 if (NULL == usbmod){
625 ALOGE("%s: USB device object is NULL", __func__);
626 return;
627 }
628
629 if (usbmod->is_record_running){
630 ALOGE("%s: USB capture thread already running", __func__);
631 return;
632 }
633
634 ALOGD("%s: creating USB capture thread", __func__);
635 ret = pthread_create(&usbmod->usb_record_thr, NULL,
636 usb_capture_launcher, (void*)adev);
637 if (ret)
638 ALOGE("%s: failed to create USB capture thread with err:%d",
639 __func__, ret);
640}
641
642void audio_extn_usb_stop_capture()
643{
644 int32_t ret;
645 ALOGD("%s: entry", __func__);
646
647 usbmod->is_record_running = false;
648 if (NULL != usbmod->proxy_pcm_record_handle)
649 pcm_stop(usbmod->proxy_pcm_record_handle);
650
651 if (NULL != usbmod->usb_pcm_record_handle)
652 pcm_stop(usbmod->usb_pcm_record_handle);
653
654 if(usbmod->usb_record_thr) {
655 ret = pthread_join(usbmod->usb_record_thr,NULL);
656 ALOGE("%s: return for pthread_join = %d", __func__, ret);
657 usbmod->usb_record_thr = (pthread_t)NULL;
658 }
659
660 pthread_mutex_lock(&usbmod->usb_record_lock);
661 if (NULL != usbmod->usb_pcm_record_handle){
662 pcm_close(usbmod->usb_pcm_record_handle);
663 usbmod->usb_pcm_record_handle = NULL;
664 }
665
666 if (NULL != usbmod->proxy_pcm_record_handle){
667 pcm_close(usbmod->proxy_pcm_record_handle);
668 usbmod->proxy_pcm_record_handle = NULL;
669 }
670 pthread_mutex_unlock(&usbmod->usb_record_lock);
671
672 ALOGD("%s: exiting",__func__);
673}
674
675bool audio_extn_usb_is_proxy_inuse()
676{
677 if( usbmod->is_record_running || usbmod->is_playback_running)
678 return true;
679 else
680 return false;
681}
682#endif /*USB_HEADSET_ENABLED end*/