1 /*
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 
54 struct 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 
80 static struct usb_module *usbmod = NULL;
81 static pthread_once_t alloc_usbmod_once_ctl = PTHREAD_ONCE_INIT;
82 
83 struct 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 
usb_alloc()94 static void usb_alloc()
95 {
96     usbmod = calloc(1, sizeof(struct usb_module));
97 }
98 
99 // 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.
initPlaybackVolume()101 static 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 ((ctl) && (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 
usb_get_numof_rates(char * rates_str)135 static 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 0;
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 
usb_get_capability(char * type,int32_t * channels,int32_t * sample_rate)153 static 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=-1, i, channels_playback;
163     char *str_start, *channel_start, *rates_str_start, *next_sr_str,
164          *next_sr_string, *temp_ptr;
165     struct stat st;
166     char *read_buf = NULL;
167     char *rates_str = NULL;
168     char *rates_str_for_val = NULL;
169     int  *rates_supported = NULL;
170     char path[128];
171     int ret = 0;
172 
173     memset(&st, 0x0, sizeof(struct stat));
174     *sample_rate = 0;
175     snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
176              usbmod->usb_card);
177 
178     fd = open(path, O_RDONLY);
179     if (fd <0) {
180         ALOGE("%s: error failed to open config file %s error: %d\n",
181               __func__, path, errno);
182         ret = -EINVAL;
183         goto done;
184     }
185 
186     if (fstat(fd, &st) < 0) {
187         ALOGE("%s: error failed to stat %s error %d\n",
188              __func__, path, errno);
189         ret = -EINVAL;
190         goto done;
191     }
192 
193     file_size = st.st_size;
194 
195     read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
196 
197     if (!read_buf) {
198         ALOGE("Failed to create read_buf");
199         ret = -ENOMEM;
200         goto done;
201     }
202 
203     err = read(fd, read_buf, USB_BUFF_SIZE);
204     str_start = strstr(read_buf, type);
205     if (str_start == NULL) {
206         ALOGE("%s: error %s section not found in usb config file",
207                __func__, type);
208         ret = -EINVAL;
209         goto done;
210     }
211 
212     channel_start = strstr(str_start, "Channels:");
213     if (channel_start == NULL) {
214         ALOGE("%s: error could not find Channels information", __func__);
215         ret = -EINVAL;
216         goto done;
217     }
218 
219     channel_start = strstr(channel_start, " ");
220     if (channel_start == NULL) {
221         ALOGE("%s: error channel section not found in usb config file",
222                __func__);
223         ret = -EINVAL;
224         goto done;
225     }
226 
227     channels_playback = atoi(channel_start);
228     if (channels_playback == 1) {
229         *channels = 1;
230     } else {
231         *channels = 2;
232     }
233 
234     ALOGD("%s: channels supported by device: %d", __func__, *channels);
235     rates_str_start = strstr(str_start, "Rates:");
236     if (rates_str_start == NULL) {
237         ALOGE("%s: error cant find rates information", __func__);
238         ret = -EINVAL;
239         goto done;
240     }
241 
242     rates_str_start = strstr(rates_str_start, " ");
243     if (rates_str_start == NULL) {
244         ALOGE("%s: error channel section not found in usb config file",
245                __func__);
246         ret = -EINVAL;
247         goto done;
248     }
249 
250     char *target = strchr(rates_str_start, '\n');
251     if (target == NULL) {
252         ALOGE("%s: error end of line not found", __func__);
253         ret = -EINVAL;
254         goto done;
255     }
256 
257     size = target - rates_str_start;
258     if ((rates_str = (char *)malloc(size + 1)) == NULL) {
259         ALOGE("%s: error unable to allocate memory to hold sample rate strings",
260               __func__);
261         ret = -EINVAL;
262         goto done;
263     }
264 
265     if ((rates_str_for_val = (char *)malloc(size + 1)) == NULL) {
266         ALOGE("%s: error unable to allocate memory to hold sample rate string",
267                __func__);
268         ret = -EINVAL;
269         goto done;
270     }
271 
272     memcpy(rates_str, rates_str_start, size);
273     memcpy(rates_str_for_val, rates_str_start, size);
274     rates_str[size] = '\0';
275     rates_str_for_val[size] = '\0';
276 
277     size = usb_get_numof_rates(rates_str);
278     if (!size) {
279         ALOGE("%s: error could not get rate size, returning", __func__);
280         ret = -EINVAL;
281         goto done;
282     }
283 
284     rates_supported = (int *)malloc(sizeof(int) * size);
285 
286     if (!rates_supported) {
287         ALOGE("couldn't allocate mem for rates_supported");
288         ret = -EINVAL;
289         goto done;
290     }
291 
292     next_sr_string = strtok_r(rates_str_for_val, " ,", &temp_ptr);
293     if (next_sr_string == NULL) {
294         ALOGE("%s: error could not get first rate val", __func__);
295         ret = -EINVAL;
296         goto done;
297     }
298 
299     rates_supported[0] = atoi(next_sr_string);
300     ALOGD("%s: rates_supported[0] for playback: %d",
301            __func__, rates_supported[0]);
302     for (i = 1; i<size; i++) {
303         next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
304         if (next_sr_string == NULL) {
305             rates_supported[i] = -1; // fill in an invalid sr for the rest
306             continue;
307         }
308         rates_supported[i] = atoi(next_sr_string);
309         ALOGD("rates_supported[%d] for playback: %d",i, rates_supported[i]);
310     }
311 
312     for (i = 0; i<size; i++) {
313         if ((rates_supported[i] > *sample_rate) &&
314             (rates_supported[i] <= 48000)) {
315             /* Sample Rate should be one of the proxy supported rates only
316                This is because proxy port is used to read from/write to DSP */
317             if ((rates_supported[i] == USB_PROXY_RATE_8000) ||
318                 (rates_supported[i] == USB_PROXY_RATE_16000) ||
319                 (rates_supported[i] == USB_PROXY_RATE_48000)) {
320                 *sample_rate = rates_supported[i];
321             }
322         }
323     }
324     ALOGD("%s: sample_rate: %d", __func__, *sample_rate);
325 
326 done:
327     if (fd >= 0) close(fd);
328     if (rates_str_for_val) free(rates_str_for_val);
329     if (rates_str) free(rates_str);
330     if (rates_supported) free(rates_supported);
331     if (read_buf) free(read_buf);
332     return ret;
333 }
334 
usb_playback_entry(void * adev)335 static int32_t usb_playback_entry(void *adev)
336 {
337     unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
338     int32_t ret, bytes, proxy_open_retry_count;
339 
340     ALOGD("%s: entry", __func__);
341     /* update audio device pointer */
342     usbmod->adev = (struct audio_device*)adev;
343     proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
344 
345     /* get capabilities */
346     pthread_mutex_lock(&usbmod->usb_playback_lock);
347     ret = usb_get_capability((char *)"Playback:",
348             &usbmod->channels_playback, &usbmod->sample_rate_playback);
349     if (ret) {
350         ALOGE("%s: could not get playback capabilities from usb device",
351                __func__);
352         pthread_mutex_unlock(&usbmod->usb_playback_lock);
353         return -EINVAL;
354     }
355     /* update config for usb
356        1 pcm frame(sample)= 4 bytes since two channels*/
357     pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
358     pcm_config_usbmod.channels = usbmod->channels_playback;
359     pcm_config_usbmod.rate = usbmod->sample_rate_playback;
360     ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
361           pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
362           pcm_config_usbmod.rate);
363 
364     usbmod->usb_pcm_playback_handle = pcm_open(usbmod->usb_card, \
365                                     usbmod->usb_device_id, PCM_OUT |
366                                     PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
367 
368     if ((usbmod->usb_pcm_playback_handle \
369         && !pcm_is_ready(usbmod->usb_pcm_playback_handle))
370         || (!usbmod->is_playback_running)) {
371         ALOGE("%s: failed: %s", __func__,
372                pcm_get_error(usbmod->usb_pcm_playback_handle));
373         pcm_close(usbmod->usb_pcm_playback_handle);
374         usbmod->usb_pcm_playback_handle = NULL;
375         pthread_mutex_unlock(&usbmod->usb_playback_lock);
376         return -ENOMEM;
377     }
378     ALOGD("%s: USB configured for playback", __func__);
379 
380     /* update config for proxy*/
381     pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/3;
382     pcm_config_usbmod.rate = usbmod->sample_rate_playback;
383     pcm_config_usbmod.channels = usbmod->channels_playback;
384     pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT;
385     usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
386     ALOGD("%s: proxy device %u:period %u:channels %u:sample", __func__,
387           pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
388           pcm_config_usbmod.rate);
389 
390     while(proxy_open_retry_count){
391         usbmod->proxy_pcm_playback_handle = pcm_open(usbmod->proxy_card,
392                                             usbmod->proxy_device_id, PCM_IN |
393                                      PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
394         if(usbmod->proxy_pcm_playback_handle
395             && !pcm_is_ready(usbmod->proxy_pcm_playback_handle)){
396                      pcm_close(usbmod->proxy_pcm_playback_handle);
397                      proxy_open_retry_count--;
398                      usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
399                      ALOGE("%s: pcm_open for proxy failed retrying = %d",
400                             __func__, proxy_open_retry_count);
401                 }
402                 else{
403                   break;
404                 }
405     }
406 
407     if ((usbmod->proxy_pcm_playback_handle
408         && !pcm_is_ready(usbmod->proxy_pcm_playback_handle))
409         || (!usbmod->is_playback_running)) {
410         ALOGE("%s: failed: %s", __func__,
411                pcm_get_error(usbmod->proxy_pcm_playback_handle));
412         pcm_close(usbmod->proxy_pcm_playback_handle);
413         usbmod->proxy_pcm_playback_handle = NULL;
414         pthread_mutex_unlock(&usbmod->usb_playback_lock);
415         return -ENOMEM;
416     }
417     ALOGD("%s: PROXY configured for playback", __func__);
418     pthread_mutex_unlock(&usbmod->usb_playback_lock);
419 
420     ALOGD("Init USB volume");
421     initPlaybackVolume();
422     /* main loop to read from proxy and write to usb */
423     while (usbmod->is_playback_running) {
424         /* read data from proxy */
425         ret = pcm_mmap_read(usbmod->proxy_pcm_playback_handle,
426                                  (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
427         /* Write to usb */
428         ret = pcm_mmap_write(usbmod->usb_pcm_playback_handle,
429                                 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
430         if(!usbmod->is_playback_running)
431             break;
432 
433         memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
434     } /* main loop end */
435 
436     ALOGD("%s: exiting USB playback thread",__func__);
437     return 0;
438 }
439 
usb_playback_launcher(void * adev)440 static void* usb_playback_launcher(void *adev)
441 {
442     int32_t ret;
443 
444     usbmod->is_playback_running = true;
445     ret = usb_playback_entry(adev);
446 
447     if (ret) {
448         ALOGE("%s: failed with err:%d", __func__, ret);
449         usbmod->is_playback_running = false;
450     }
451     return NULL;
452 }
453 
usb_record_entry(void * adev)454 static int32_t usb_record_entry(void *adev)
455 {
456     unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
457     int32_t ret, bytes, proxy_open_retry_count;
458     ALOGD("%s: entry", __func__);
459 
460     /* update audio device pointer */
461     usbmod->adev = (struct audio_device*)adev;
462     proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
463 
464     /* get capabilities */
465     pthread_mutex_lock(&usbmod->usb_record_lock);
466     ret = usb_get_capability((char *)"Capture:",
467             &usbmod->channels_record, &usbmod->sample_rate_record);
468     if (ret) {
469         ALOGE("%s: could not get capture capabilities from usb device",
470                __func__);
471         pthread_mutex_unlock(&usbmod->usb_record_lock);
472         return -EINVAL;
473     }
474     /* update config for usb
475        1 pcm frame(sample)= 4 bytes since two channels*/
476     pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
477     pcm_config_usbmod.channels = usbmod->channels_record;
478     pcm_config_usbmod.rate = usbmod->sample_rate_record;
479     ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
480           pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
481           pcm_config_usbmod.rate);
482 
483     usbmod->usb_pcm_record_handle = pcm_open(usbmod->usb_card, \
484                                     usbmod->usb_device_id, PCM_IN |
485                                     PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
486 
487     if ((usbmod->usb_pcm_record_handle \
488         && !pcm_is_ready(usbmod->usb_pcm_record_handle))
489         || (!usbmod->is_record_running)) {
490         ALOGE("%s: failed: %s", __func__,
491                pcm_get_error(usbmod->usb_pcm_record_handle));
492         pcm_close(usbmod->usb_pcm_record_handle);
493         usbmod->usb_pcm_record_handle = NULL;
494         pthread_mutex_unlock(&usbmod->usb_record_lock);
495         return -ENOMEM;
496     }
497     ALOGD("%s: USB configured for capture", __func__);
498 
499     /* update config for proxy*/
500     pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/4;
501     pcm_config_usbmod.rate = usbmod->sample_rate_record;
502     pcm_config_usbmod.channels = usbmod->channels_record;
503     pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT * 2;
504     usbmod->proxy_device_id = AFE_PROXY_CAPTURE_DEVICE;
505     ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
506           pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
507           pcm_config_usbmod.rate);
508 
509     while(proxy_open_retry_count){
510         usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
511                                             usbmod->proxy_device_id, PCM_OUT |
512                                      PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
513         if(usbmod->proxy_pcm_record_handle
514             && !pcm_is_ready(usbmod->proxy_pcm_record_handle)){
515                      pcm_close(usbmod->proxy_pcm_record_handle);
516                      proxy_open_retry_count--;
517                      usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
518                      ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
519                             __func__, proxy_open_retry_count);
520                 }
521                 else{
522                   break;
523                 }
524     }
525     if ((usbmod->proxy_pcm_record_handle
526         && !pcm_is_ready(usbmod->proxy_pcm_record_handle))
527         || (!usbmod->is_record_running)) {
528         ALOGE("%s: failed: %s", __func__,
529                pcm_get_error(usbmod->proxy_pcm_record_handle));
530         pcm_close(usbmod->proxy_pcm_record_handle);
531         usbmod->proxy_pcm_record_handle = NULL;
532         pthread_mutex_unlock(&usbmod->usb_record_lock);
533         return -ENOMEM;
534     }
535     ALOGD("%s: PROXY configured for capture", __func__);
536     pthread_mutex_unlock(&usbmod->usb_record_lock);
537 
538     /* main loop to read from usb and write to proxy */
539     while (usbmod->is_record_running) {
540         /* read data from usb */
541         ret = pcm_mmap_read(usbmod->usb_pcm_record_handle,
542                                  (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
543         /* Write to proxy */
544         ret = pcm_mmap_write(usbmod->proxy_pcm_record_handle,
545                                 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
546         if(!usbmod->is_record_running)
547             break;
548 
549         memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
550     } /* main loop end */
551 
552     ALOGD("%s: exiting USB capture thread",__func__);
553     return 0;
554 }
555 
usb_capture_launcher(void * adev)556 static void* usb_capture_launcher(void *adev)
557 {
558     int32_t ret;
559 
560     usbmod->is_record_running = true;
561     ret = usb_record_entry(adev);
562 
563     if (ret) {
564         ALOGE("%s: failed with err:%d", __func__, ret);
565         usbmod->is_record_running = false;
566     }
567     return NULL;
568 }
569 
audio_extn_usb_init(void * adev)570 void audio_extn_usb_init(void *adev)
571 {
572     pthread_once(&alloc_usbmod_once_ctl, usb_alloc);
573 
574     usbmod->is_playback_running = false;
575     usbmod->is_record_running = false;
576 
577     usbmod->usb_pcm_playback_handle = NULL;
578     usbmod->proxy_pcm_playback_handle = NULL;
579 
580     usbmod->usb_pcm_record_handle = NULL;
581     usbmod->proxy_pcm_record_handle = NULL;
582 
583     usbmod->usb_card = 1;
584     usbmod->usb_device_id = 0;
585     usbmod->proxy_card = 0;
586     usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
587     usbmod->adev = (struct audio_device*)adev;
588 
589      pthread_mutex_init(&usbmod->usb_playback_lock,
590                         (const pthread_mutexattr_t *) NULL);
591      pthread_mutex_init(&usbmod->usb_record_lock,
592                         (const pthread_mutexattr_t *) NULL);
593 }
594 
audio_extn_usb_deinit()595 void audio_extn_usb_deinit()
596 {
597     if (NULL != usbmod){
598         free(usbmod);
599         usbmod = NULL;
600     }
601 }
602 
audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)603 void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)
604 {
605     /* Proxy port and USB headset are related to two different sound cards */
606     if (sndcard_idx == usbmod->usb_card) {
607         usbmod->usb_card = usbmod->proxy_card;
608     }
609 
610     usbmod->proxy_card = sndcard_idx;
611 }
612 
audio_extn_usb_start_playback(void * adev)613 void audio_extn_usb_start_playback(void *adev)
614 {
615     int32_t ret;
616 
617     if (NULL == usbmod){
618         ALOGE("%s: USB device object is NULL", __func__);
619         return;
620     }
621 
622     if (usbmod->is_playback_running){
623         ALOGE("%s: USB playback thread already running", __func__);
624         return;
625     }
626 
627     ALOGD("%s: creating USB playback thread", __func__);
628     ret = pthread_create(&usbmod->usb_playback_thr, NULL,
629                          usb_playback_launcher, (void*)adev);
630     if (ret)
631         ALOGE("%s: failed to create USB playback thread with err:%d",
632               __func__, ret);
633 }
634 
audio_extn_usb_stop_playback()635 void audio_extn_usb_stop_playback()
636 {
637     int32_t ret;
638     ALOGD("%s: entry", __func__);
639 
640     usbmod->is_playback_running = false;
641     if (NULL != usbmod->proxy_pcm_playback_handle)
642         pcm_stop(usbmod->proxy_pcm_playback_handle);
643 
644     if (NULL != usbmod->usb_pcm_playback_handle)
645         pcm_stop(usbmod->usb_pcm_playback_handle);
646 
647     if(usbmod->usb_playback_thr) {
648         ret = pthread_join(usbmod->usb_playback_thr,NULL);
649         ALOGE("%s: return for pthread_join = %d", __func__, ret);
650         usbmod->usb_playback_thr = (pthread_t)NULL;
651     }
652 
653     pthread_mutex_lock(&usbmod->usb_playback_lock);
654     if (NULL != usbmod->usb_pcm_playback_handle){
655         pcm_close(usbmod->usb_pcm_playback_handle);
656         usbmod->usb_pcm_playback_handle = NULL;
657     }
658 
659     if (NULL != usbmod->proxy_pcm_playback_handle){
660         pcm_close(usbmod->proxy_pcm_playback_handle);
661         usbmod->proxy_pcm_playback_handle = NULL;
662     }
663     pthread_mutex_unlock(&usbmod->usb_playback_lock);
664 
665     ALOGD("%s: exiting",__func__);
666 }
667 
audio_extn_usb_start_capture(void * adev)668 void audio_extn_usb_start_capture(void *adev)
669 {
670     int32_t ret;
671 
672     if (NULL == usbmod){
673         ALOGE("%s: USB device object is NULL", __func__);
674         return;
675     }
676 
677     if (usbmod->is_record_running){
678         ALOGE("%s: USB capture thread already running", __func__);
679         return;
680     }
681 
682     ALOGD("%s: creating USB capture thread", __func__);
683     ret = pthread_create(&usbmod->usb_record_thr, NULL,
684                          usb_capture_launcher, (void*)adev);
685     if (ret)
686         ALOGE("%s: failed to create USB capture thread with err:%d",
687               __func__, ret);
688 }
689 
audio_extn_usb_stop_capture()690 void audio_extn_usb_stop_capture()
691 {
692     int32_t ret;
693     ALOGD("%s: entry", __func__);
694 
695     usbmod->is_record_running = false;
696     if (NULL != usbmod->proxy_pcm_record_handle)
697         pcm_stop(usbmod->proxy_pcm_record_handle);
698 
699     if (NULL != usbmod->usb_pcm_record_handle)
700         pcm_stop(usbmod->usb_pcm_record_handle);
701 
702     if(usbmod->usb_record_thr) {
703         ret = pthread_join(usbmod->usb_record_thr,NULL);
704         ALOGE("%s: return for pthread_join = %d", __func__, ret);
705         usbmod->usb_record_thr = (pthread_t)NULL;
706     }
707 
708     pthread_mutex_lock(&usbmod->usb_record_lock);
709     if (NULL != usbmod->usb_pcm_record_handle){
710         pcm_close(usbmod->usb_pcm_record_handle);
711         usbmod->usb_pcm_record_handle = NULL;
712     }
713 
714     if (NULL != usbmod->proxy_pcm_record_handle){
715         pcm_close(usbmod->proxy_pcm_record_handle);
716         usbmod->proxy_pcm_record_handle = NULL;
717     }
718     pthread_mutex_unlock(&usbmod->usb_record_lock);
719 
720     ALOGD("%s: exiting",__func__);
721 }
722 
audio_extn_usb_is_proxy_inuse()723 bool audio_extn_usb_is_proxy_inuse()
724 {
725     if( usbmod->is_record_running || usbmod->is_playback_running)
726         return true;
727     else
728         return false;
729 }
730 #endif /*USB_HEADSET_ENABLED end*/
731