blob: 281b445fc6e0283db64be8a15f4115069605c302 [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
Satish Babu Patakokila6c9fe832014-03-26 15:02:12 +053099// Some USB audio accessories have a really low default volume set. Look for a suitable
100// volume control and set the volume to default volume level.
101static void initPlaybackVolume() {
102 ALOGD("initPlaybackVolume");
103 struct mixer *usbMixer = mixer_open(1);
104
105 if (usbMixer) {
106 struct mixer_ctl *ctl = NULL;
107 unsigned int usbPlaybackVolume;
108 unsigned int i;
109 unsigned int num_ctls = mixer_get_num_ctls(usbMixer);
110
111 // Look for the first control named ".*Playback Volume" that isn't for a microphone
112 for (i = 0; i < num_ctls; i++) {
113 ctl = mixer_get_ctl(usbMixer, i);
114 if (strstr((const char *)mixer_ctl_get_name(ctl), "Playback Volume") &&
115 !strstr((const char *)mixer_ctl_get_name(ctl), "Mic")) {
116 break;
117 }
118 }
119 if (ctl != NULL) {
120 ALOGD("Found a volume control for USB: %s", mixer_ctl_get_name(ctl) );
121 usbPlaybackVolume = mixer_ctl_get_value(ctl, 0);
122 ALOGD("Value got from mixer_ctl_get is:%u", usbPlaybackVolume);
123 if (mixer_ctl_set_value(ctl,0,usbPlaybackVolume) < 0) {
124 ALOGE("Failed to set volume; default volume might be used");
125 }
126 } else {
127 ALOGE("No playback volume control found; default volume will be used");
128 }
129 mixer_close(usbMixer);
130 } else {
131 ALOGE("Failed to open mixer for card 1");
132 }
133}
134
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700135static int usb_get_numof_rates(char *rates_str)
136{
137 int i, size = 0;
138 char *next_sr_string, *temp_ptr;
139 next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);
140
141 if (next_sr_string == NULL) {
142 ALOGE("%s: get_numof_rates: could not find rates string", __func__);
143 return (int)NULL;
144 }
145
146 for (i = 1; next_sr_string != NULL; i++) {
147 size ++;
148 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
149 }
150 return size;
151}
152
153static int usb_get_capability(char *type, int32_t *channels,
154 int32_t *sample_rate)
155{
156 ALOGD("%s: for %s", __func__, type);
157 long unsigned file_size;
158 FILE *fp;
159 char *buffer;
160 int32_t err = 1;
161 int32_t size = 0;
162 int32_t fd, i, channels_playback;
163 char *read_buf, *str_start, *channel_start, *rates_str, *rates_str_for_val,
164 *rates_str_start, *next_sr_str, *test, *next_sr_string, *temp_ptr;
165 struct stat st;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800166 int *rates_supported;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700167 char path[128];
168
169 memset(&st, 0x0, sizeof(struct stat));
170 *sample_rate = 0;
171 snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
172 usbmod->usb_card);
173
174 fd = open(path, O_RDONLY);
175 if (fd <0) {
176 ALOGE("%s: error failed to open config file %s error: %d\n",
177 __func__, path, errno);
178 close(fd);
179 return -EINVAL;
180 }
181
182 if (fstat(fd, &st) < 0) {
183 ALOGE("%s: error failed to stat %s error %d\n",
184 __func__, path, errno);
185 close(fd);
186 return -EINVAL;
187 }
188
189 file_size = st.st_size;
190
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800191 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700192 err = read(fd, read_buf, USB_BUFF_SIZE);
193 str_start = strstr(read_buf, type);
194 if (str_start == NULL) {
195 ALOGE("%s: error %s section not found in usb config file",
196 __func__, type);
197 close(fd);
198 free(read_buf);
199 return -EINVAL;
200 }
201
202 channel_start = strstr(str_start, "Channels:");
203 if (channel_start == NULL) {
204 ALOGE("%s: error could not find Channels information", __func__);
205 close(fd);
206 free(read_buf);
207 return -EINVAL;
208 }
209
210 channel_start = strstr(channel_start, " ");
211 if (channel_start == NULL) {
212 ALOGE("%s: error channel section not found in usb config file",
213 __func__);
214 close(fd);
215 free(read_buf);
216 return -EINVAL;
217 }
218
219 channels_playback = atoi(channel_start);
220 if (channels_playback == 1) {
221 *channels = 1;
222 } else {
223 *channels = 2;
224 }
225
226 ALOGD("%s: channels supported by device: %d", __func__, *channels);
227 rates_str_start = strstr(str_start, "Rates:");
228 if (rates_str_start == NULL) {
229 ALOGE("%s: error cant find rates information", __func__);
230 close(fd);
231 free(read_buf);
232 return -EINVAL;
233 }
234
235 rates_str_start = strstr(rates_str_start, " ");
236 if (rates_str_start == NULL) {
237 ALOGE("%s: error channel section not found in usb config file",
238 __func__);
239 close(fd);
240 free(read_buf);
241 return -EINVAL;
242 }
243
244 char *target = strchr(rates_str_start, '\n');
245 if (target == NULL) {
246 ALOGE("%s: error end of line not found", __func__);
247 close(fd);
248 free(read_buf);
249 return -EINVAL;
250 }
251
252 size = target - rates_str_start;
253 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
254 ALOGE("%s: error unable to allocate memory to hold sample rate strings",
255 __func__);
256 close(fd);
257 free(read_buf);
258 return -ENOMEM;
259 }
260
261 if ((rates_str_for_val = (char *)malloc(size + 1)) == NULL) {
262 ALOGE("%s: error unable to allocate memory to hold sample rate string",
263 __func__);
264 close(fd);
265 free(rates_str);
266 free(read_buf);
267 return -ENOMEM;
268 }
269
270 memcpy(rates_str, rates_str_start, size);
271 memcpy(rates_str_for_val, rates_str_start, size);
272 rates_str[size] = '\0';
273 rates_str_for_val[size] = '\0';
274
275 size = usb_get_numof_rates(rates_str);
276 if (!size) {
277 ALOGE("%s: error could not get rate size, returning", __func__);
278 close(fd);
279 free(rates_str_for_val);
280 free(rates_str);
281 free(read_buf);
282 return -EINVAL;
283 }
284
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800285 rates_supported = (int *)malloc(sizeof(int) * size);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700286 next_sr_string = strtok_r(rates_str_for_val, " ,", &temp_ptr);
287 if (next_sr_string == NULL) {
288 ALOGE("%s: error could not get first rate val", __func__);
289 close(fd);
290 free(rates_str_for_val);
291 free(rates_str);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800292 free(rates_supported);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700293 free(read_buf);
294 return -EINVAL;
295 }
296
297 rates_supported[0] = atoi(next_sr_string);
298 ALOGD("%s: rates_supported[0] for playback: %d",
299 __func__, rates_supported[0]);
300 for (i = 1; i<size; i++) {
301 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
302 rates_supported[i] = atoi(next_sr_string);
303 ALOGD("rates_supported[%d] for playback: %d",i, rates_supported[i]);
304 }
305
306 for (i = 0; i<size; i++) {
307 if ((rates_supported[i] > *sample_rate) &&
308 (rates_supported[i] <= 48000)) {
309 /* Sample Rate should be one of the proxy supported rates only
310 This is because proxy port is used to read from/write to DSP */
311 if ((rates_supported[i] == USB_PROXY_RATE_8000) ||
312 (rates_supported[i] == USB_PROXY_RATE_16000) ||
313 (rates_supported[i] == USB_PROXY_RATE_48000)) {
314 *sample_rate = rates_supported[i];
315 }
316 }
317 }
318 ALOGD("%s: sample_rate: %d", __func__, *sample_rate);
319
320 close(fd);
321 free(rates_str_for_val);
322 free(rates_str);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800323 free(rates_supported);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700324 free(read_buf);
325 return 0;
326}
327
328static int32_t usb_playback_entry(void *adev)
329{
330 unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
331 int32_t ret, bytes, proxy_open_retry_count;
332
333 ALOGD("%s: entry", __func__);
334 /* update audio device pointer */
335 usbmod->adev = (struct audio_device*)adev;
336 proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
337
338 /* get capabilities */
339 pthread_mutex_lock(&usbmod->usb_playback_lock);
340 ret = usb_get_capability((char *)"Playback:",
341 &usbmod->channels_playback, &usbmod->sample_rate_playback);
342 if (ret) {
343 ALOGE("%s: could not get playback capabilities from usb device",
344 __func__);
345 pthread_mutex_unlock(&usbmod->usb_playback_lock);
346 return -EINVAL;
347 }
348 /* update config for usb
349 1 pcm frame(sample)= 4 bytes since two channels*/
350 pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
351 pcm_config_usbmod.channels = usbmod->channels_playback;
352 pcm_config_usbmod.rate = usbmod->sample_rate_playback;
353 ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
354 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
355 pcm_config_usbmod.rate);
356
357 usbmod->usb_pcm_playback_handle = pcm_open(usbmod->usb_card, \
358 usbmod->usb_device_id, PCM_OUT |
359 PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
360
361 if ((usbmod->usb_pcm_playback_handle \
362 && !pcm_is_ready(usbmod->usb_pcm_playback_handle))
363 || (!usbmod->is_playback_running)) {
364 ALOGE("%s: failed: %s", __func__,
365 pcm_get_error(usbmod->usb_pcm_playback_handle));
366 pcm_close(usbmod->usb_pcm_playback_handle);
367 usbmod->usb_pcm_playback_handle = NULL;
368 pthread_mutex_unlock(&usbmod->usb_playback_lock);
369 return -ENOMEM;
370 }
371 ALOGD("%s: USB configured for playback", __func__);
372
373 /* update config for proxy*/
374 pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/3;
375 pcm_config_usbmod.rate = usbmod->sample_rate_playback;
376 pcm_config_usbmod.channels = usbmod->channels_playback;
377 pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT;
378 usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
Satish Babu Patakokila6c9fe832014-03-26 15:02:12 +0530379 ALOGD("%s: proxy device %u:period %u:channels %u:sample", __func__,
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700380 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
381 pcm_config_usbmod.rate);
382
383 while(proxy_open_retry_count){
384 usbmod->proxy_pcm_playback_handle = pcm_open(usbmod->proxy_card,
385 usbmod->proxy_device_id, PCM_IN |
386 PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800387 if(usbmod->proxy_pcm_playback_handle
388 && !pcm_is_ready(usbmod->proxy_pcm_playback_handle)){
389 pcm_close(usbmod->proxy_pcm_playback_handle);
390 usbmod->proxy_pcm_playback_handle = NULL;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700391 proxy_open_retry_count--;
392 usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
393 ALOGE("%s: pcm_open for proxy failed retrying = %d",
394 __func__, proxy_open_retry_count);
395 }
396 else{
397 break;
398 }
399 }
400
401 if ((usbmod->proxy_pcm_playback_handle
402 && !pcm_is_ready(usbmod->proxy_pcm_playback_handle))
403 || (!usbmod->is_playback_running)) {
404 ALOGE("%s: failed: %s", __func__,
405 pcm_get_error(usbmod->proxy_pcm_playback_handle));
406 pcm_close(usbmod->proxy_pcm_playback_handle);
407 usbmod->proxy_pcm_playback_handle = NULL;
408 pthread_mutex_unlock(&usbmod->usb_playback_lock);
409 return -ENOMEM;
410 }
411 ALOGD("%s: PROXY configured for playback", __func__);
412 pthread_mutex_unlock(&usbmod->usb_playback_lock);
413
Satish Babu Patakokila6c9fe832014-03-26 15:02:12 +0530414 ALOGD("Init USB volume");
415 initPlaybackVolume();
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700416 /* main loop to read from proxy and write to usb */
417 while (usbmod->is_playback_running) {
418 /* read data from proxy */
419 ret = pcm_mmap_read(usbmod->proxy_pcm_playback_handle,
420 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
421 /* Write to usb */
422 ret = pcm_mmap_write(usbmod->usb_pcm_playback_handle,
423 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
424 if(!usbmod->is_playback_running)
425 break;
426
427 memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
428 } /* main loop end */
429
430 ALOGD("%s: exiting USB playback thread",__func__);
431 return 0;
432}
433
434static void* usb_playback_launcher(void *adev)
435{
436 int32_t ret;
437
438 usbmod->is_playback_running = true;
439 ret = usb_playback_entry(adev);
440
441 if (ret) {
442 ALOGE("%s: failed with err:%d", __func__, ret);
443 usbmod->is_playback_running = false;
444 }
445 return NULL;
446}
447
448static int32_t usb_record_entry(void *adev)
449{
450 unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
451 int32_t ret, bytes, proxy_open_retry_count;
452 ALOGD("%s: entry", __func__);
453
454 /* update audio device pointer */
455 usbmod->adev = (struct audio_device*)adev;
456 proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
457
458 /* get capabilities */
459 pthread_mutex_lock(&usbmod->usb_record_lock);
460 ret = usb_get_capability((char *)"Capture:",
461 &usbmod->channels_record, &usbmod->sample_rate_record);
462 if (ret) {
463 ALOGE("%s: could not get capture capabilities from usb device",
464 __func__);
465 pthread_mutex_unlock(&usbmod->usb_record_lock);
466 return -EINVAL;
467 }
468 /* update config for usb
469 1 pcm frame(sample)= 4 bytes since two channels*/
470 pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
471 pcm_config_usbmod.channels = usbmod->channels_record;
472 pcm_config_usbmod.rate = usbmod->sample_rate_record;
473 ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
474 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
475 pcm_config_usbmod.rate);
476
477 usbmod->usb_pcm_record_handle = pcm_open(usbmod->usb_card, \
478 usbmod->usb_device_id, PCM_IN |
479 PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
480
481 if ((usbmod->usb_pcm_record_handle \
482 && !pcm_is_ready(usbmod->usb_pcm_record_handle))
483 || (!usbmod->is_record_running)) {
484 ALOGE("%s: failed: %s", __func__,
485 pcm_get_error(usbmod->usb_pcm_record_handle));
486 pcm_close(usbmod->usb_pcm_record_handle);
487 usbmod->usb_pcm_record_handle = NULL;
488 pthread_mutex_unlock(&usbmod->usb_record_lock);
489 return -ENOMEM;
490 }
491 ALOGD("%s: USB configured for capture", __func__);
492
493 /* update config for proxy*/
494 pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/4;
495 pcm_config_usbmod.rate = usbmod->sample_rate_record;
496 pcm_config_usbmod.channels = usbmod->channels_record;
497 pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT * 2;
498 usbmod->proxy_device_id = AFE_PROXY_CAPTURE_DEVICE;
499 ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
500 pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
501 pcm_config_usbmod.rate);
502
503 while(proxy_open_retry_count){
504 usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
505 usbmod->proxy_device_id, PCM_OUT |
506 PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800507 if(usbmod->proxy_pcm_record_handle
508 && !pcm_is_ready(usbmod->proxy_pcm_record_handle)){
509 pcm_close(usbmod->proxy_pcm_record_handle);
510 usbmod->proxy_pcm_record_handle = NULL;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511 proxy_open_retry_count--;
512 usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
513 ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
514 __func__, proxy_open_retry_count);
515 }
516 else{
517 break;
518 }
519 }
520 if ((usbmod->proxy_pcm_record_handle
521 && !pcm_is_ready(usbmod->proxy_pcm_record_handle))
522 || (!usbmod->is_record_running)) {
523 ALOGE("%s: failed: %s", __func__,
524 pcm_get_error(usbmod->proxy_pcm_record_handle));
525 pcm_close(usbmod->proxy_pcm_record_handle);
526 usbmod->proxy_pcm_record_handle = NULL;
527 pthread_mutex_unlock(&usbmod->usb_record_lock);
528 return -ENOMEM;
529 }
530 ALOGD("%s: PROXY configured for capture", __func__);
531 pthread_mutex_unlock(&usbmod->usb_record_lock);
532
533 /* main loop to read from usb and write to proxy */
534 while (usbmod->is_record_running) {
535 /* read data from usb */
536 ret = pcm_mmap_read(usbmod->usb_pcm_record_handle,
537 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
538 /* Write to proxy */
539 ret = pcm_mmap_write(usbmod->proxy_pcm_record_handle,
540 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
541 if(!usbmod->is_record_running)
542 break;
543
544 memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
545 } /* main loop end */
546
547 ALOGD("%s: exiting USB capture thread",__func__);
548 return 0;
549}
550
551static void* usb_capture_launcher(void *adev)
552{
553 int32_t ret;
554
555 usbmod->is_record_running = true;
556 ret = usb_record_entry(adev);
557
558 if (ret) {
559 ALOGE("%s: failed with err:%d", __func__, ret);
560 usbmod->is_record_running = false;
561 }
562 return NULL;
563}
564
565void audio_extn_usb_init(void *adev)
566{
567 pthread_once(&alloc_usbmod_once_ctl, usb_alloc);
568
569 usbmod->is_playback_running = false;
570 usbmod->is_record_running = false;
571
572 usbmod->usb_pcm_playback_handle = NULL;
573 usbmod->proxy_pcm_playback_handle = NULL;
574
575 usbmod->usb_pcm_record_handle = NULL;
576 usbmod->proxy_pcm_record_handle = NULL;
577
578 usbmod->usb_card = 1;
579 usbmod->usb_device_id = 0;
580 usbmod->proxy_card = 0;
581 usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
582 usbmod->adev = (struct audio_device*)adev;
583}
584
585void audio_extn_usb_deinit()
586{
587 if (NULL != usbmod){
588 free(usbmod);
589 usbmod = NULL;
590 }
591}
592
593void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)
594{
595 /* Proxy port and USB headset are related to two different sound cards */
596 if (sndcard_idx == usbmod->usb_card) {
597 usbmod->usb_card = usbmod->proxy_card;
598 }
599
600 usbmod->proxy_card = sndcard_idx;
601}
602
603void audio_extn_usb_start_playback(void *adev)
604{
605 int32_t ret;
606
607 if (NULL == usbmod){
608 ALOGE("%s: USB device object is NULL", __func__);
609 return;
610 }
611
612 if (usbmod->is_playback_running){
613 ALOGE("%s: USB playback thread already running", __func__);
614 return;
615 }
616
617 ALOGD("%s: creating USB playback thread", __func__);
618 ret = pthread_create(&usbmod->usb_playback_thr, NULL,
619 usb_playback_launcher, (void*)adev);
620 if (ret)
621 ALOGE("%s: failed to create USB playback thread with err:%d",
622 __func__, ret);
623}
624
625void audio_extn_usb_stop_playback()
626{
627 int32_t ret;
628 ALOGD("%s: entry", __func__);
629
630 usbmod->is_playback_running = false;
631 if (NULL != usbmod->proxy_pcm_playback_handle)
632 pcm_stop(usbmod->proxy_pcm_playback_handle);
633
634 if (NULL != usbmod->usb_pcm_playback_handle)
635 pcm_stop(usbmod->usb_pcm_playback_handle);
636
637 if(usbmod->usb_playback_thr) {
638 ret = pthread_join(usbmod->usb_playback_thr,NULL);
639 ALOGE("%s: return for pthread_join = %d", __func__, ret);
640 usbmod->usb_playback_thr = (pthread_t)NULL;
641 }
642
643 pthread_mutex_lock(&usbmod->usb_playback_lock);
644 if (NULL != usbmod->usb_pcm_playback_handle){
645 pcm_close(usbmod->usb_pcm_playback_handle);
646 usbmod->usb_pcm_playback_handle = NULL;
647 }
648
649 if (NULL != usbmod->proxy_pcm_playback_handle){
650 pcm_close(usbmod->proxy_pcm_playback_handle);
651 usbmod->proxy_pcm_playback_handle = NULL;
652 }
653 pthread_mutex_unlock(&usbmod->usb_playback_lock);
654
655 ALOGD("%s: exiting",__func__);
656}
657
658void audio_extn_usb_start_capture(void *adev)
659{
660 int32_t ret;
661
662 if (NULL == usbmod){
663 ALOGE("%s: USB device object is NULL", __func__);
664 return;
665 }
666
667 if (usbmod->is_record_running){
668 ALOGE("%s: USB capture thread already running", __func__);
669 return;
670 }
671
672 ALOGD("%s: creating USB capture thread", __func__);
673 ret = pthread_create(&usbmod->usb_record_thr, NULL,
674 usb_capture_launcher, (void*)adev);
675 if (ret)
676 ALOGE("%s: failed to create USB capture thread with err:%d",
677 __func__, ret);
678}
679
680void audio_extn_usb_stop_capture()
681{
682 int32_t ret;
683 ALOGD("%s: entry", __func__);
684
685 usbmod->is_record_running = false;
686 if (NULL != usbmod->proxy_pcm_record_handle)
687 pcm_stop(usbmod->proxy_pcm_record_handle);
688
689 if (NULL != usbmod->usb_pcm_record_handle)
690 pcm_stop(usbmod->usb_pcm_record_handle);
691
692 if(usbmod->usb_record_thr) {
693 ret = pthread_join(usbmod->usb_record_thr,NULL);
694 ALOGE("%s: return for pthread_join = %d", __func__, ret);
695 usbmod->usb_record_thr = (pthread_t)NULL;
696 }
697
698 pthread_mutex_lock(&usbmod->usb_record_lock);
699 if (NULL != usbmod->usb_pcm_record_handle){
700 pcm_close(usbmod->usb_pcm_record_handle);
701 usbmod->usb_pcm_record_handle = NULL;
702 }
703
704 if (NULL != usbmod->proxy_pcm_record_handle){
705 pcm_close(usbmod->proxy_pcm_record_handle);
706 usbmod->proxy_pcm_record_handle = NULL;
707 }
708 pthread_mutex_unlock(&usbmod->usb_record_lock);
709
710 ALOGD("%s: exiting",__func__);
711}
712
713bool audio_extn_usb_is_proxy_inuse()
714{
715 if( usbmod->is_record_running || usbmod->is_playback_running)
716 return true;
717 else
718 return false;
719}
720#endif /*USB_HEADSET_ENABLED end*/