blob: 3a63ffa339d1a180b8e758522162aa6abc3ba3e8 [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 Patakokilaf6d3c552014-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;
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700162 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;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700165 struct stat st;
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700166 char *read_buf = NULL;
167 char *rates_str = NULL;
168 char *rates_str_for_val = NULL;
169 int *rates_supported = NULL;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700170 char path[128];
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700171 int ret = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700172
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);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700182 ret = -EINVAL;
183 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700184 }
185
186 if (fstat(fd, &st) < 0) {
187 ALOGE("%s: error failed to stat %s error %d\n",
188 __func__, path, errno);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700189 ret = -EINVAL;
190 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700191 }
192
193 file_size = st.st_size;
194
Apoorv Raghuvanshi1d2ed3c2014-01-29 15:31:32 -0800195 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700196
197 if (!read_buf) {
198 ALOGE("Failed to create read_buf");
199 ret = -ENOMEM;
200 goto done;
201 }
202
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700203 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);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700208 ret = -EINVAL;
209 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700210 }
211
212 channel_start = strstr(str_start, "Channels:");
213 if (channel_start == NULL) {
214 ALOGE("%s: error could not find Channels information", __func__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700215 ret = -EINVAL;
216 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700217 }
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__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700223 ret = -EINVAL;
224 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700225 }
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__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700238 ret = -EINVAL;
239 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700240 }
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__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700246 ret = -EINVAL;
247 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700248 }
249
250 char *target = strchr(rates_str_start, '\n');
251 if (target == NULL) {
252 ALOGE("%s: error end of line not found", __func__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700253 ret = -EINVAL;
254 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700255 }
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__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700261 ret = -EINVAL;
262 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700263 }
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__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700268 ret = -EINVAL;
269 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700270 }
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__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700280 ret = -EINVAL;
281 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700282 }
283
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800284 rates_supported = (int *)malloc(sizeof(int) * size);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700285
286 if (!rates_supported) {
287 ALOGE("couldn't allocate mem for rates_supported");
288 ret = -EINVAL;
289 goto done;
290 }
291
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700292 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__);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700295 ret = -EINVAL;
296 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700297 }
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);
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700304 if (next_sr_string == NULL) {
305 rates_supported[i] = -1; // fill in an invalid sr for the rest
306 continue;
307 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700308 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
Haynes Mathew Georgebac2cba2014-06-30 13:56:18 -0700326done:
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;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700333}
334
335static 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;
Satish Babu Patakokilaf6d3c552014-03-26 15:02:12 +0530386 ALOGD("%s: proxy device %u:period %u:channels %u:sample", __func__,
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700387 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);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800394 if(usbmod->proxy_pcm_playback_handle
395 && !pcm_is_ready(usbmod->proxy_pcm_playback_handle)){
396 pcm_close(usbmod->proxy_pcm_playback_handle);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700397 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
Satish Babu Patakokilaf6d3c552014-03-26 15:02:12 +0530420 ALOGD("Init USB volume");
421 initPlaybackVolume();
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700422 /* 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
440static 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
454static 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);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -0800513 if(usbmod->proxy_pcm_record_handle
514 && !pcm_is_ready(usbmod->proxy_pcm_record_handle)){
515 pcm_close(usbmod->proxy_pcm_record_handle);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700516 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
556static 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
570void 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;
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -0700588
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);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700593}
594
595void audio_extn_usb_deinit()
596{
597 if (NULL != usbmod){
598 free(usbmod);
599 usbmod = NULL;
600 }
601}
602
603void 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
613void 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
635void 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
668void 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
690void 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
723bool 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*/