blob: d0225ece17b6f3a0b8a7655c0902c5bbcf65714b [file] [log] [blame]
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001/*
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002 * Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07003 * 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>
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070032#include <system/audio.h>
33#include <tinyalsa/asoundlib.h>
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080034#include <audio_hw.h>
35#include <cutils/properties.h>
Kuirong Wang1cad7142016-05-24 15:21:56 -070036#include <ctype.h>
37#include <math.h>
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070038
39#ifdef USB_HEADSET_ENABLED
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080040#define USB_BUFF_SIZE 2048
41#define CHANNEL_NUMBER_STR "Channels: "
42#define PLAYBACK_PROFILE_STR "Playback:"
43#define CAPTURE_PROFILE_STR "Capture:"
Kuirong Wang1cad7142016-05-24 15:21:56 -070044#define USB_SIDETONE_GAIN_STR "usb_sidetone_gain"
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080045#define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A)))
46#define SAMPLE_RATE_8000 8000
47#define SAMPLE_RATE_11025 11025
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080048// Supported sample rates for USB
49static uint32_t supported_sample_rates[] =
Ashish Jain058165c2016-09-28 23:18:48 +053050 {44100, 48000, 64000, 88200, 96000, 176400, 192000, 384000};
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080051
52#define MAX_SAMPLE_RATE_SIZE sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
53
54enum usb_usecase_type{
55 USB_PLAYBACK = 0,
56 USB_CAPTURE,
57};
58
Kuirong Wang1cad7142016-05-24 15:21:56 -070059enum {
60 USB_SIDETONE_ENABLE_INDEX = 0,
61 USB_SIDETONE_VOLUME_INDEX,
62 USB_SIDETONE_MAX_INDEX,
63};
64
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080065struct usb_device_config {
66 struct listnode list;
67 unsigned int bit_width;
68 unsigned int channels;
69 unsigned int rate_size;
70 unsigned int rates[MAX_SAMPLE_RATE_SIZE];
71};
72
73struct usb_card_config {
74 struct listnode list;
75 audio_devices_t usb_device_type;
76 int usb_card;
77 struct listnode usb_device_conf_list;
Kuirong Wang1cad7142016-05-24 15:21:56 -070078 struct mixer *usb_snd_mixer;
79 int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
80 int usb_sidetone_vol_min;
81 int usb_sidetone_vol_max;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080082};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070083
84struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080085 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070086 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -070087 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +053088 bool is_capture_supported;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070089};
90
91static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080092static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -070093static int usb_sidetone_gain = 0;
94
95static const char * const usb_sidetone_enable_str[] = {
96 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -070097 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -070098};
99
100static const char * const usb_sidetone_volume_str[] = {
101 "Sidetone Playback Volume",
102 "Mic Playback Volume",
103};
104
105static void usb_mixer_print_enum(struct mixer_ctl *ctl)
106{
107 unsigned int num_enums;
108 unsigned int i;
109 const char *string;
110
111 num_enums = mixer_ctl_get_num_enums(ctl);
112
113 for (i = 0; i < num_enums; i++) {
114 string = mixer_ctl_get_enum_string(ctl, i);
115 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
116 }
117}
118
119static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
120{
121 struct mixer_ctl *ctl;
122 enum mixer_ctl_type type;
123 unsigned int num_values;
124 unsigned int i;
125 int min, max;
126
127 if (isdigit(control[0]))
128 ctl = mixer_get_ctl(mixer, atoi(control));
129 else
130 ctl = mixer_get_ctl_by_name(mixer, control);
131
132 if (!ctl) {
133 fprintf(stderr, "Invalid mixer control\n");
134 return;
135 }
136
137 type = mixer_ctl_get_type(ctl);
138 num_values = mixer_ctl_get_num_values(ctl);
139
140 ALOGI("%s:", mixer_ctl_get_name(ctl));
141
142 for (i = 0; i < num_values; i++) {
143 switch (type) {
144 case MIXER_CTL_TYPE_INT:
145 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
146 break;
147 case MIXER_CTL_TYPE_BOOL:
148 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
149 break;
150 case MIXER_CTL_TYPE_ENUM:
151 usb_mixer_print_enum(ctl);
152 break;
153 case MIXER_CTL_TYPE_BYTE:
154 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
155 break;
156 default:
157 ALOGI(" unknown");
158 break;
159 }
160 }
161
162 if (type == MIXER_CTL_TYPE_INT) {
163 min = mixer_ctl_get_range_min(ctl);
164 max = mixer_ctl_get_range_max(ctl);
165 ALOGI(" (range %d->%d)", min, max);
166 }
167}
168
169static void usb_soundcard_list_controls(struct mixer *mixer)
170{
171 struct mixer_ctl *ctl;
172 const char *name, *type;
173 unsigned int num_ctls, num_values;
174 unsigned int i;
175
176 num_ctls = mixer_get_num_ctls(mixer);
177
178 ALOGI("Number of controls: %d\n", num_ctls);
179
180 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
181 for (i = 0; i < num_ctls; i++) {
182 ctl = mixer_get_ctl(mixer, i);
183 if (ctl != NULL) {
184 name = mixer_ctl_get_name(ctl);
185 type = mixer_ctl_get_type_string(ctl);
186 num_values = mixer_ctl_get_num_values(ctl);
187 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
188 if (name != NULL)
189 usb_soundcard_detail_control(mixer, name);
190 }
191 }
192}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700193
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800194static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
195 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700196{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800197 struct mixer_ctl *ctl;
198 unsigned int dev_token;
199 unsigned int pcm_device_number = 0;
200
201 /*
202 * usb_dev_token_id is 32 bit number and is defined as below:
203 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
204 */
205 dev_token = (card << 16 ) |
206 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
207
208 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
209 if (!ctl) {
210 ALOGE("%s: Could not get ctl for mixer cmd - %s",
211 __func__, dev_mixer_ctl_name);
212 return -EINVAL;
213 }
214 mixer_ctl_set_value(ctl, 0, dev_token);
215
216 return 0;
217}
218
219static int usb_get_sample_rates(char *rates_str,
220 struct usb_device_config *config)
221{
222 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700223 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800224 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700225
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800226 /* Sample rate string can be in any of the folloing two bit_widthes:
227 * Rates: 8000 - 48000 (continuous)
228 * Rates: 8000, 44100, 48000
229 * Support both the bit_widths
230 */
231 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700232 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
233 if (next_sr_string == NULL) {
234 ALOGE("%s: could not find min rates string", __func__);
235 return -EINVAL;
236 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800237 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700238 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700239 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800240 if (next_sr_string == NULL) {
241 ALOGE("%s: could not find max rates string", __func__);
242 return -EINVAL;
243 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700244 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800245
Kuirong Wang591a98a2016-06-27 12:41:41 -0700246 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800247 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700248 supported_sample_rates[i] <= max_sr) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800249 config->rates[sr_size++] = supported_sample_rates[i];
Kuirong Wang591a98a2016-06-27 12:41:41 -0700250 ALOGI_IF(usb_audio_debug_enable,
251 "%s: continuous sample rate supported_sample_rates[%d] %d",
252 __func__, i, supported_sample_rates[i]);
253 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800254 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700255 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800256 do {
257 sr = (uint32_t)atoi(next_sr_string);
258 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
259 if (supported_sample_rates[i] == sr) {
260 ALOGI_IF(usb_audio_debug_enable,
261 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
262 __func__, sr, i, supported_sample_rates[i]);
263 config->rates[sr_size++] = supported_sample_rates[i];
264 }
265 }
266 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
267 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700268 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800269 config->rate_size = sr_size;
270 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700271}
272
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800273static int usb_get_capability(int type,
274 struct usb_card_config *usb_card_info,
275 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700276{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700277 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800278 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800279 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700280 char *str_start = NULL;
281 char *str_end = NULL;
282 char *channel_start = NULL;
283 char *bit_width_start = NULL;
284 char *rates_str_start = NULL;
285 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700286 char *read_buf = NULL;
287 char *rates_str = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700288 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700289 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800290 char *bit_width_str = NULL;
291 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700292 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700293
Kuirong Wange9894162016-08-26 15:16:39 -0700294 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800295 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
296 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
297
Kuirong Wange9894162016-08-26 15:16:39 -0700298 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800299 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700300 if(ret < 0) {
301 ALOGE("%s: failed on snprintf (%d) to path %s\n",
302 __func__, ret, path);
303 goto done;
304 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700305
306 fd = open(path, O_RDONLY);
307 if (fd <0) {
308 ALOGE("%s: error failed to open config file %s error: %d\n",
309 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700310 ret = -EINVAL;
311 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700312 }
313
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800314 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700315
316 if (!read_buf) {
317 ALOGE("Failed to create read_buf");
318 ret = -ENOMEM;
319 goto done;
320 }
321
Kuirong Wange9894162016-08-26 15:16:39 -0700322 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
323 ALOGE("file read error\n");
324 goto done;
325 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800326 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
327 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700328 if (str_start == NULL) {
329 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800330 __func__, ((type == USB_PLAYBACK) ?
331 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700332 ret = -EINVAL;
333 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700334 }
Kuirong Wange9894162016-08-26 15:16:39 -0700335 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
336 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
337 if (str_end > str_start)
338 check = true;
339
340 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700341
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800342 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700343 str_start = strstr(str_start, "Altset");
344 if ((str_start == NULL) || (check && (str_start >= str_end))) {
345 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800346 break;
347 }
Kuirong Wange9894162016-08-26 15:16:39 -0700348 ALOGV("%s: remaining string %s\n", __func__, str_start);
349 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800350 usb_device_info = calloc(1, sizeof(struct usb_device_config));
351 if (usb_device_info == NULL) {
352 ALOGE("%s: error unable to allocate memory",
353 __func__);
354 ret = -ENOMEM;
355 break;
356 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800357 /* Bit bit_width parsing */
358 bit_width_start = strstr(str_start, "Format: ");
359 if (bit_width_start == NULL) {
360 ALOGI("%s: Could not find bit_width string", __func__);
361 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700362 continue;
363 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800364 target = strchr(bit_width_start, '\n');
365 if (target == NULL) {
366 ALOGI("%s:end of line not found", __func__);
367 free(usb_device_info);
368 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700369 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800370 size = target - bit_width_start;
371 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
372 ALOGE("%s: unable to allocate memory to hold bit width strings",
373 __func__);
374 ret = -EINVAL;
375 free(usb_device_info);
376 break;
377 }
378 memcpy(bit_width_str, bit_width_start, size);
379 bit_width_str[size] = '\0';
380 if (strstr(bit_width_str, "S16_LE"))
381 usb_device_info->bit_width = 16;
382 else if (strstr(bit_width_str, "S24_LE"))
383 usb_device_info->bit_width = 24;
384 else if (strstr(bit_width_str, "S24_3LE"))
385 usb_device_info->bit_width = 24;
386 else if (strstr(bit_width_str, "S32_LE"))
387 usb_device_info->bit_width = 32;
388
389 if (bit_width_str)
390 free(bit_width_str);
391
392 /* channels parsing */
393 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
394 if (channel_start == NULL) {
395 ALOGI("%s: could not find Channels string", __func__);
396 free(usb_device_info);
397 continue;
398 }
399 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
400 usb_device_info->channels = channels_no;
401
402 /* Sample rates parsing */
403 rates_str_start = strstr(str_start, "Rates: ");
404 if (rates_str_start == NULL) {
405 ALOGI("%s: cant find rates string", __func__);
406 free(usb_device_info);
407 continue;
408 }
409 target = strchr(rates_str_start, '\n');
410 if (target == NULL) {
411 ALOGI("%s: end of line not found", __func__);
412 free(usb_device_info);
413 continue;
414 }
415 size = target - rates_str_start;
416 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
417 ALOGE("%s: unable to allocate memory to hold sample rate strings",
418 __func__);
419 ret = -EINVAL;
420 free(usb_device_info);
421 break;
422 }
423 memcpy(rates_str, rates_str_start, size);
424 rates_str[size] = '\0';
425 ret = usb_get_sample_rates(rates_str, usb_device_info);
426 if (rates_str)
427 free(rates_str);
428 if (ret < 0) {
429 ALOGI("%s: error unable to get sample rate values",
430 __func__);
431 free(usb_device_info);
432 continue;
433 }
434 /* Add to list if every field is valid */
435 list_add_tail(&usb_card_info->usb_device_conf_list,
436 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700437 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700438
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700439done:
440 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700441 if (read_buf) free(read_buf);
442 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700443}
444
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800445static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
446 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700447{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800448 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700449
450 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800451 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
452 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700453 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800454 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700455 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800456 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
457
458exit:
459
460 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700461}
462
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800463static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
464 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700465{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800466 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700467
468 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800469 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
470 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700471 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800472 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700473 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800474 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700475
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800476exit:
477 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700478}
479
Kuirong Wang1cad7142016-05-24 15:21:56 -0700480static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
481{
482 struct mixer_ctl *ctl;
483 unsigned int index;
484
485 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
486 usb_card_info->usb_sidetone_index[index] = -1;
487
488 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
489 for (index = 0;
490 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
491 index++) {
492 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
493 usb_sidetone_enable_str[index]);
494 if (ctl) {
495 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
496 /* Disable device sidetone by default */
497 mixer_ctl_set_value(ctl, 0, false);
498 break;
499 }
500 }
501 for (index = 0;
502 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
503 index++) {
504 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
505 usb_sidetone_volume_str[index]);
506 if (ctl) {
507 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
508 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
509 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
510 break;
511 }
512 }
513
514 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
515 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
516
517 return;
518}
519
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800520static bool usb_valid_device(int device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700521{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800522 bool is_usb_device = false;
523 if ((device & AUDIO_DEVICE_OUT_USB_DEVICE) ||
524 (device & AUDIO_DEVICE_IN_USB_DEVICE))
525 is_usb_device = true;
526 return is_usb_device;
527}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700528
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800529static void usb_print_active_device(void){
530 struct listnode *node_i, *node_j;
531 struct usb_device_config *dev_info;
532 struct usb_card_config *card_info;
533 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700534
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800535 ALOGI("%s", __func__);
536 list_for_each(node_i, &usbmod->usb_card_conf_list) {
537 card_info = node_to_item(node_i, struct usb_card_config, list);
538 ALOGI("%s: card_dev_type (0x%x), card_no(%d)",
539 __func__, card_info->usb_device_type, card_info->usb_card);
540 list_for_each(node_j, &card_info->usb_device_conf_list) {
541 dev_info = node_to_item(node_j, struct usb_device_config, list);
542 ALOGI("%s: bit-width(%d) channel(%d)",
543 __func__, dev_info->bit_width, dev_info->channels);
544 for (i = 0; i < dev_info->rate_size; i++)
545 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
546 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700547 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800548}
549
550static bool usb_get_best_match_for_bit_width(
551 struct listnode *dev_list,
552 unsigned int stream_bit_width,
553 unsigned int *bit_width)
554{
555 struct listnode *node_i;
556 struct usb_device_config *dev_info;
557 unsigned int candidate = 0;
558
559 list_for_each(node_i, dev_list) {
560 dev_info = node_to_item(node_i, struct usb_device_config, list);
561 ALOGI_IF(usb_audio_debug_enable,
562 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
563 __func__, dev_info->bit_width,
564 stream_bit_width, candidate);
565 if (dev_info->bit_width == stream_bit_width) {
566 *bit_width = dev_info->bit_width;
567 ALOGV("%s: Found match bit-width (%d)",
568 __func__, dev_info->bit_width);
569 goto exit;
570 } else if (candidate == 0) {
571 candidate = dev_info->bit_width;
572 }
573 /*
574 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
575 * higher bit width 32 is picked up instead of 16-bit
576 */
577 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
578 ABS_SUB(stream_bit_width, candidate)) {
579 candidate = dev_info->bit_width;
580 }
581 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
582 ABS_SUB(stream_bit_width, candidate)) &&
583 (dev_info->bit_width > candidate)) {
584 candidate = dev_info->bit_width;
585 }
586 }
587 ALOGV("%s: No match found, use the best candidate bw(%d)",
588 __func__, candidate);
589 *bit_width = candidate;
590exit:
591 return true;
592}
593
594static bool usb_get_best_match_for_channels(
595 struct listnode *dev_list,
596 unsigned int bit_width,
597 unsigned int stream_ch,
598 unsigned int *ch)
599{
600 struct listnode *node_i;
601 struct usb_device_config *dev_info;
602 unsigned int candidate = 0;
603
604 list_for_each(node_i, dev_list) {
605 dev_info = node_to_item(node_i, struct usb_device_config, list);
606 ALOGI_IF(usb_audio_debug_enable,
607 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
608 __func__, dev_info->channels, dev_info->bit_width,
609 stream_ch, bit_width, candidate);
610 if (dev_info->bit_width != bit_width)
611 continue;
612 if (dev_info->channels== stream_ch) {
613 *ch = dev_info->channels;
614 ALOGV("%s: Found match channels (%d)",
615 __func__, dev_info->channels);
616 goto exit;
617 } else if (candidate == 0)
618 candidate = dev_info->channels;
619 /*
620 * If stream channel is 4, USB supports both 3 and 5, then
621 * higher channel 5 is picked up instead of 3
622 */
623 else if (ABS_SUB(stream_ch, dev_info->channels) <
624 ABS_SUB(stream_ch, candidate)) {
625 candidate = dev_info->channels;
626 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
627 ABS_SUB(stream_ch, candidate)) &&
628 (dev_info->channels > candidate)) {
629 candidate = dev_info->channels;
630 }
631 }
632 ALOGV("%s: No match found, use the best candidate ch(%d)",
633 __func__, candidate);
634 *ch = candidate;
635exit:
636 return true;
637
638}
639
640static bool usb_sample_rate_multiple(
641 unsigned int stream_sample_rate,
642 unsigned int base)
643{
644 return (((stream_sample_rate / base) * base) == stream_sample_rate);
645}
646
647static bool usb_find_sample_rate_candidate(unsigned int base,
648 unsigned stream_rate,
649 unsigned int usb_rate,
650 unsigned int cur_candidate,
651 unsigned int *update_candidate)
652{
653 /* For sample rate, we should consider fracational sample rate as high priority.
654 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
655 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
656 */
657 if (!usb_sample_rate_multiple(cur_candidate, base) &&
658 usb_sample_rate_multiple(usb_rate, base)) {
659 *update_candidate = usb_rate;
660 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
661 usb_sample_rate_multiple(usb_rate, base)) {
662 if (ABS_SUB(stream_rate, usb_rate) <
663 ABS_SUB(stream_rate, cur_candidate)) {
664 *update_candidate = usb_rate;
665 } else if ((ABS_SUB(stream_rate, usb_rate) ==
666 ABS_SUB(stream_rate, cur_candidate)) &&
667 (usb_rate > cur_candidate)) {
668 *update_candidate = usb_rate;
669 }
670 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
671 !usb_sample_rate_multiple(usb_rate, base)) {
672 if (ABS_SUB(stream_rate, usb_rate) <
673 ABS_SUB(stream_rate, cur_candidate)) {
674 *update_candidate = usb_rate;
675 } else if ((ABS_SUB(stream_rate, usb_rate) ==
676 ABS_SUB(stream_rate, cur_candidate)) &&
677 (usb_rate > cur_candidate)) {
678 *update_candidate = usb_rate;
679 }
680 }
681 return true;
682}
683
684static bool usb_get_best_match_for_sample_rate(
685 struct listnode *dev_list,
686 unsigned int bit_width,
687 unsigned int ch,
688 unsigned int stream_sample_rate,
689 unsigned int *sr)
690{
691 struct listnode *node_i;
692 struct usb_device_config *dev_info;
693 unsigned int candidate = 48000;
694 unsigned int base = SAMPLE_RATE_8000;
695 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
696 unsigned int i;
697
698 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
699 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
700
701 list_for_each(node_i, dev_list) {
702 dev_info = node_to_item(node_i, struct usb_device_config, list);
703 ALOGI_IF(usb_audio_debug_enable,
704 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
705 __func__, dev_info->channels, dev_info->bit_width,
706 ch, bit_width, stream_sample_rate, candidate);
Ashish Jainb26edfb2016-08-25 00:10:11 +0530707 if ((dev_info->bit_width != bit_width) || dev_info->channels != ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800708 continue;
709
710 candidate = 0;
711 for (i = 0; i < dev_info->rate_size; i++) {
712 ALOGI_IF(usb_audio_debug_enable,
713 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
714 __func__, dev_info->channels,
715 dev_info->bit_width, dev_info->rates[i],
716 ch, bit_width, stream_sample_rate, candidate);
717 if (stream_sample_rate == dev_info->rates[i]) {
718 *sr = dev_info->rates[i];
719 ALOGV("%s: Found match sample rate (%d)",
720 __func__, dev_info->rates[i]);
721 goto exit;
722 } else if (candidate == 0) {
723 candidate = dev_info->rates[i];
724 /*
725 * For sample rate, we should consider fracational sample rate as high priority.
726 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
727 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
728 */
729 } else if (multiple_8k) {
730 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
731 stream_sample_rate,
732 dev_info->rates[i],
733 candidate,
734 &candidate);
735 } else {
736 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
737 stream_sample_rate,
738 dev_info->rates[i],
739 candidate,
740 &candidate);
741 }
742 }
743 }
744 ALOGV("%s: No match found, use the best candidate sr(%d)",
745 __func__, candidate);
746 *sr = candidate;
747exit:
748 return true;
749}
750
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800751static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
752 unsigned int *bit_width,
753 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530754 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800755{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800756 bool is_usb_supported = true;
757
758 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530759 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800760 if (list_empty(dev_list)) {
761 *sample_rate = 48000;
762 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530763 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800764 ALOGI("%s: list is empty,fall back to default setting", __func__);
765 goto exit;
766 }
767 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
768 usb_get_best_match_for_channels(dev_list,
769 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530770 *ch,
771 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800772 usb_get_best_match_for_sample_rate(dev_list,
773 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530774 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800775 *sample_rate,
776 sample_rate);
777exit:
778 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530779 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800780 return is_usb_supported;
781}
782
Kuirong Wang1cad7142016-05-24 15:21:56 -0700783static int usb_get_sidetone_gain(struct usb_card_config *card_info)
784{
785 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
786 if (gain > card_info->usb_sidetone_vol_max)
787 gain = card_info->usb_sidetone_vol_max;
788 return gain;
789}
790
791void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
792 char *value, int len)
793{
794 int err;
795
796 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
797 value, len);
798 if (err >= 0) {
799 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
800 ALOGV("%s: sidetone gain(%s) decimal %d",
801 __func__, value, usb_sidetone_gain);
802 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
803 }
804 return;
805}
806
807int audio_extn_usb_enable_sidetone(int device, bool enable)
808{
809 int ret = -ENODEV;
810 struct listnode *node_i;
811 struct usb_card_config *card_info;
812 int i;
813 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
814 __func__, device, enable);
815
816 list_for_each(node_i, &usbmod->usb_card_conf_list) {
817 card_info = node_to_item(node_i, struct usb_card_config, list);
818 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
819 __func__, card_info->usb_device_type, card_info->usb_card);
820 if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
821 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
822 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
823 card_info->usb_snd_mixer,
824 usb_sidetone_enable_str[i]);
825 if (ctl)
826 mixer_ctl_set_value(ctl, 0, enable);
827 else
828 break;
829
830 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
831 ctl = mixer_get_ctl_by_name(
832 card_info->usb_snd_mixer,
833 usb_sidetone_volume_str[i]);
834 if (ctl == NULL)
835 ALOGV("%s: sidetone gain mixer command is not found",
836 __func__);
837 else if (enable)
838 mixer_ctl_set_value(ctl, 0,
839 usb_get_sidetone_gain(card_info));
840 }
841 ret = 0;
842 break;
843 }
844 }
845 }
846 return ret;
847}
848
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800849bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
850 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700851 unsigned int *ch,
852 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800853{
854 struct listnode *node_i;
855 struct usb_card_config *card_info;
856 bool is_usb_supported = false;
857
Kuirong Wang27152a12016-11-11 10:20:30 -0800858 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
859 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800860 list_for_each(node_i, &usbmod->usb_card_conf_list) {
861 card_info = node_to_item(node_i, struct usb_card_config, list);
862 ALOGI_IF(usb_audio_debug_enable,
863 "%s: card_dev_type (0x%x), card_no(%d)",
864 __func__, card_info->usb_device_type, card_info->usb_card);
865 /* Currently only apply the first playback sound card configuration */
Kuirong Wang0b947f72016-09-29 11:03:09 -0700866 if ((is_playback && card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) ||
867 ((!is_playback) && card_info->usb_device_type == AUDIO_DEVICE_IN_USB_DEVICE)){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800868 is_usb_supported = usb_audio_backend_apply_policy(
869 &card_info->usb_device_conf_list,
870 bit_width,
871 sample_rate,
872 ch);
873 break;
874 }
875 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530876 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
877 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800878
879 return is_usb_supported;
880}
881
Ashish Jain3e37a702016-11-25 12:27:15 +0530882bool audio_extn_usb_is_capture_supported()
883{
884 if (usbmod == NULL) {
885 ALOGE("%s: USB device object is NULL", __func__);
886 return false;
887 }
888 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
889 return usbmod->is_capture_supported;
890}
891
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800892void audio_extn_usb_add_device(audio_devices_t device, int card)
893{
894 struct usb_card_config *usb_card_info;
895 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -0800896 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800897
898 property_get("audio.usb.enable.debug", check_debug_enable, NULL);
899 if (atoi(check_debug_enable)) {
900 usb_audio_debug_enable = true;
901 }
902
903 ALOGI_IF(usb_audio_debug_enable,
904 "%s: parameters device(0x%x), card(%d)",
905 __func__, device, card);
906 if (usbmod == NULL) {
907 ALOGE("%s: USB device object is NULL", __func__);
908 goto exit;
909 }
910
911 if (!(usb_valid_device(device)) || (card < 0)) {
912 ALOGE("%s:device(0x%x), card(%d)",
913 __func__, device, card);
914 goto exit;
915 }
916
Kuirong Wang27152a12016-11-11 10:20:30 -0800917 list_for_each(node_i, &usbmod->usb_card_conf_list) {
918 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
919 ALOGI_IF(usb_audio_debug_enable,
920 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
921 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
922 /* If we have cached the capability */
923 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
924 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
925 __func__, device, card);
926 goto exit;
927 }
928 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800929 usb_card_info = calloc(1, sizeof(struct usb_card_config));
930 if (usb_card_info == NULL) {
931 ALOGE("%s: error unable to allocate memory",
932 __func__);
933 goto exit;
934 }
935 list_init(&usb_card_info->usb_device_conf_list);
936 if (device & AUDIO_DEVICE_OUT_USB_DEVICE) {
937 if (!usb_get_device_pb_config(usb_card_info, card)){
938 usb_card_info->usb_card = card;
939 usb_card_info->usb_device_type = AUDIO_DEVICE_OUT_USB_DEVICE;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700940 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800941 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
942 goto exit;
943 }
944 } else if (device & AUDIO_DEVICE_IN_USB_DEVICE) {
945 if (!usb_get_device_cap_config(usb_card_info, card)) {
946 usb_card_info->usb_card = card;
947 usb_card_info->usb_device_type = AUDIO_DEVICE_IN_USB_DEVICE;
Ashish Jain3e37a702016-11-25 12:27:15 +0530948 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800949 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
950 goto exit;
951 }
952 }
953 /* free memory in error case */
954 if (usb_card_info != NULL)
955 free(usb_card_info);
956exit:
957 if (usb_audio_debug_enable)
958 usb_print_active_device();
959 return;
960}
961
962void audio_extn_usb_remove_device(audio_devices_t device, int card)
963{
964 struct listnode *node_i, *temp_i;
965 struct listnode *node_j, *temp_j;
966 struct usb_device_config *dev_info;
967 struct usb_card_config *card_info;
968 unsigned int i;
969
970 ALOGV("%s: device(0x%x), card(%d)",
971 __func__, device, card);
972
973 if (usbmod == NULL) {
974 ALOGE("%s: USB device object is NULL", __func__);
975 goto exit;
976 }
977
978 if (!(usb_valid_device(device)) || (card < 0)) {
979 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
980 __func__, device, card);
981 goto exit;
982 }
983 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
984 card_info = node_to_item(node_i, struct usb_card_config, list);
985 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
986 __func__, card_info->usb_device_type, card_info->usb_card);
987 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
988 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
989 dev_info = node_to_item(node_j, struct usb_device_config, list);
990 ALOGV("%s: bit-width(%d) channel(%d)",
991 __func__, dev_info->bit_width, dev_info->channels);
992 for (i = 0; i < dev_info->rate_size; i++)
993 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
994
995 list_remove(node_j);
996 free(node_to_item(node_j, struct usb_device_config, list));
997 }
998 list_remove(node_i);
999 free(node_to_item(node_i, struct usb_card_config, list));
1000 }
1001 }
Ashish Jain3e37a702016-11-25 12:27:15 +05301002 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001003exit:
1004 if (usb_audio_debug_enable)
1005 usb_print_active_device();
1006
1007 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001008}
1009
1010void audio_extn_usb_init(void *adev)
1011{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001012 if (usbmod == NULL) {
1013 usbmod = calloc(1, sizeof(struct usb_module));
1014 if (usbmod == NULL) {
1015 ALOGE("%s: error unable to allocate memory", __func__);
1016 goto exit;
1017 }
1018 }
1019 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001020 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001021 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301022 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001023exit:
1024 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001025}
1026
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001027void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001028{
1029 if (NULL != usbmod){
1030 free(usbmod);
1031 usbmod = NULL;
1032 }
1033}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001034#endif /*USB_HEADSET_ENABLED end*/