blob: 36fe484a41575fd98bda56be7e344841ff44ebbf [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;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070088};
89
90static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080091static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -070092static int usb_sidetone_gain = 0;
93
94static const char * const usb_sidetone_enable_str[] = {
95 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -070096 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -070097};
98
99static const char * const usb_sidetone_volume_str[] = {
100 "Sidetone Playback Volume",
101 "Mic Playback Volume",
102};
103
104static void usb_mixer_print_enum(struct mixer_ctl *ctl)
105{
106 unsigned int num_enums;
107 unsigned int i;
108 const char *string;
109
110 num_enums = mixer_ctl_get_num_enums(ctl);
111
112 for (i = 0; i < num_enums; i++) {
113 string = mixer_ctl_get_enum_string(ctl, i);
114 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
115 }
116}
117
118static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
119{
120 struct mixer_ctl *ctl;
121 enum mixer_ctl_type type;
122 unsigned int num_values;
123 unsigned int i;
124 int min, max;
125
126 if (isdigit(control[0]))
127 ctl = mixer_get_ctl(mixer, atoi(control));
128 else
129 ctl = mixer_get_ctl_by_name(mixer, control);
130
131 if (!ctl) {
132 fprintf(stderr, "Invalid mixer control\n");
133 return;
134 }
135
136 type = mixer_ctl_get_type(ctl);
137 num_values = mixer_ctl_get_num_values(ctl);
138
139 ALOGI("%s:", mixer_ctl_get_name(ctl));
140
141 for (i = 0; i < num_values; i++) {
142 switch (type) {
143 case MIXER_CTL_TYPE_INT:
144 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
145 break;
146 case MIXER_CTL_TYPE_BOOL:
147 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
148 break;
149 case MIXER_CTL_TYPE_ENUM:
150 usb_mixer_print_enum(ctl);
151 break;
152 case MIXER_CTL_TYPE_BYTE:
153 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
154 break;
155 default:
156 ALOGI(" unknown");
157 break;
158 }
159 }
160
161 if (type == MIXER_CTL_TYPE_INT) {
162 min = mixer_ctl_get_range_min(ctl);
163 max = mixer_ctl_get_range_max(ctl);
164 ALOGI(" (range %d->%d)", min, max);
165 }
166}
167
168static void usb_soundcard_list_controls(struct mixer *mixer)
169{
170 struct mixer_ctl *ctl;
171 const char *name, *type;
172 unsigned int num_ctls, num_values;
173 unsigned int i;
174
175 num_ctls = mixer_get_num_ctls(mixer);
176
177 ALOGI("Number of controls: %d\n", num_ctls);
178
179 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
180 for (i = 0; i < num_ctls; i++) {
181 ctl = mixer_get_ctl(mixer, i);
182 if (ctl != NULL) {
183 name = mixer_ctl_get_name(ctl);
184 type = mixer_ctl_get_type_string(ctl);
185 num_values = mixer_ctl_get_num_values(ctl);
186 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
187 if (name != NULL)
188 usb_soundcard_detail_control(mixer, name);
189 }
190 }
191}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700192
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800193static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
194 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700195{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800196 struct mixer_ctl *ctl;
197 unsigned int dev_token;
198 unsigned int pcm_device_number = 0;
199
200 /*
201 * usb_dev_token_id is 32 bit number and is defined as below:
202 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
203 */
204 dev_token = (card << 16 ) |
205 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
206
207 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
208 if (!ctl) {
209 ALOGE("%s: Could not get ctl for mixer cmd - %s",
210 __func__, dev_mixer_ctl_name);
211 return -EINVAL;
212 }
213 mixer_ctl_set_value(ctl, 0, dev_token);
214
215 return 0;
216}
217
218static int usb_get_sample_rates(char *rates_str,
219 struct usb_device_config *config)
220{
221 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700222 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800223 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700224
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800225 /* Sample rate string can be in any of the folloing two bit_widthes:
226 * Rates: 8000 - 48000 (continuous)
227 * Rates: 8000, 44100, 48000
228 * Support both the bit_widths
229 */
230 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700231 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
232 if (next_sr_string == NULL) {
233 ALOGE("%s: could not find min rates string", __func__);
234 return -EINVAL;
235 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800236 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700237 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700238 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800239 if (next_sr_string == NULL) {
240 ALOGE("%s: could not find max rates string", __func__);
241 return -EINVAL;
242 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700243 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800244
Kuirong Wang591a98a2016-06-27 12:41:41 -0700245 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800246 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700247 supported_sample_rates[i] <= max_sr) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800248 config->rates[sr_size++] = supported_sample_rates[i];
Kuirong Wang591a98a2016-06-27 12:41:41 -0700249 ALOGI_IF(usb_audio_debug_enable,
250 "%s: continuous sample rate supported_sample_rates[%d] %d",
251 __func__, i, supported_sample_rates[i]);
252 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800253 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700254 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800255 do {
256 sr = (uint32_t)atoi(next_sr_string);
257 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
258 if (supported_sample_rates[i] == sr) {
259 ALOGI_IF(usb_audio_debug_enable,
260 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
261 __func__, sr, i, supported_sample_rates[i]);
262 config->rates[sr_size++] = supported_sample_rates[i];
263 }
264 }
265 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
266 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700267 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800268 config->rate_size = sr_size;
269 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700270}
271
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800272static int usb_get_capability(int type,
273 struct usb_card_config *usb_card_info,
274 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700275{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700276 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800277 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800278 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700279 char *str_start = NULL;
280 char *str_end = NULL;
281 char *channel_start = NULL;
282 char *bit_width_start = NULL;
283 char *rates_str_start = NULL;
284 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700285 char *read_buf = NULL;
286 char *rates_str = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700287 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700288 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800289 char *bit_width_str = NULL;
290 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700291 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700292
Kuirong Wange9894162016-08-26 15:16:39 -0700293 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800294 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
295 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
296
Kuirong Wange9894162016-08-26 15:16:39 -0700297 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800298 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700299 if(ret < 0) {
300 ALOGE("%s: failed on snprintf (%d) to path %s\n",
301 __func__, ret, path);
302 goto done;
303 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700304
305 fd = open(path, O_RDONLY);
306 if (fd <0) {
307 ALOGE("%s: error failed to open config file %s error: %d\n",
308 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700309 ret = -EINVAL;
310 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700311 }
312
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800313 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700314
315 if (!read_buf) {
316 ALOGE("Failed to create read_buf");
317 ret = -ENOMEM;
318 goto done;
319 }
320
Kuirong Wange9894162016-08-26 15:16:39 -0700321 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
322 ALOGE("file read error\n");
323 goto done;
324 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800325 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
326 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700327 if (str_start == NULL) {
328 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800329 __func__, ((type == USB_PLAYBACK) ?
330 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700331 ret = -EINVAL;
332 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700333 }
Kuirong Wange9894162016-08-26 15:16:39 -0700334 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
335 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
336 if (str_end > str_start)
337 check = true;
338
339 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700340
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800341 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700342 str_start = strstr(str_start, "Altset");
343 if ((str_start == NULL) || (check && (str_start >= str_end))) {
344 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800345 break;
346 }
Kuirong Wange9894162016-08-26 15:16:39 -0700347 ALOGV("%s: remaining string %s\n", __func__, str_start);
348 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800349 usb_device_info = calloc(1, sizeof(struct usb_device_config));
350 if (usb_device_info == NULL) {
351 ALOGE("%s: error unable to allocate memory",
352 __func__);
353 ret = -ENOMEM;
354 break;
355 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800356 /* Bit bit_width parsing */
357 bit_width_start = strstr(str_start, "Format: ");
358 if (bit_width_start == NULL) {
359 ALOGI("%s: Could not find bit_width string", __func__);
360 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700361 continue;
362 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800363 target = strchr(bit_width_start, '\n');
364 if (target == NULL) {
365 ALOGI("%s:end of line not found", __func__);
366 free(usb_device_info);
367 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700368 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800369 size = target - bit_width_start;
370 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
371 ALOGE("%s: unable to allocate memory to hold bit width strings",
372 __func__);
373 ret = -EINVAL;
374 free(usb_device_info);
375 break;
376 }
377 memcpy(bit_width_str, bit_width_start, size);
378 bit_width_str[size] = '\0';
379 if (strstr(bit_width_str, "S16_LE"))
380 usb_device_info->bit_width = 16;
381 else if (strstr(bit_width_str, "S24_LE"))
382 usb_device_info->bit_width = 24;
383 else if (strstr(bit_width_str, "S24_3LE"))
384 usb_device_info->bit_width = 24;
385 else if (strstr(bit_width_str, "S32_LE"))
386 usb_device_info->bit_width = 32;
387
388 if (bit_width_str)
389 free(bit_width_str);
390
391 /* channels parsing */
392 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
393 if (channel_start == NULL) {
394 ALOGI("%s: could not find Channels string", __func__);
395 free(usb_device_info);
396 continue;
397 }
398 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
399 usb_device_info->channels = channels_no;
400
401 /* Sample rates parsing */
402 rates_str_start = strstr(str_start, "Rates: ");
403 if (rates_str_start == NULL) {
404 ALOGI("%s: cant find rates string", __func__);
405 free(usb_device_info);
406 continue;
407 }
408 target = strchr(rates_str_start, '\n');
409 if (target == NULL) {
410 ALOGI("%s: end of line not found", __func__);
411 free(usb_device_info);
412 continue;
413 }
414 size = target - rates_str_start;
415 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
416 ALOGE("%s: unable to allocate memory to hold sample rate strings",
417 __func__);
418 ret = -EINVAL;
419 free(usb_device_info);
420 break;
421 }
422 memcpy(rates_str, rates_str_start, size);
423 rates_str[size] = '\0';
424 ret = usb_get_sample_rates(rates_str, usb_device_info);
425 if (rates_str)
426 free(rates_str);
427 if (ret < 0) {
428 ALOGI("%s: error unable to get sample rate values",
429 __func__);
430 free(usb_device_info);
431 continue;
432 }
433 /* Add to list if every field is valid */
434 list_add_tail(&usb_card_info->usb_device_conf_list,
435 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700436 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700437
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700438done:
439 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700440 if (read_buf) free(read_buf);
441 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700442}
443
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800444static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
445 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700446{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800447 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700448
449 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800450 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
451 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700452 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800453 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700454 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800455 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
456
457exit:
458
459 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700460}
461
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800462static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
463 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700464{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800465 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700466
467 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800468 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
469 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700470 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800471 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700472 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800473 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700474
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800475exit:
476 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700477}
478
Kuirong Wang1cad7142016-05-24 15:21:56 -0700479static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
480{
481 struct mixer_ctl *ctl;
482 unsigned int index;
483
484 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
485 usb_card_info->usb_sidetone_index[index] = -1;
486
487 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
488 for (index = 0;
489 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
490 index++) {
491 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
492 usb_sidetone_enable_str[index]);
493 if (ctl) {
494 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
495 /* Disable device sidetone by default */
496 mixer_ctl_set_value(ctl, 0, false);
497 break;
498 }
499 }
500 for (index = 0;
501 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
502 index++) {
503 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
504 usb_sidetone_volume_str[index]);
505 if (ctl) {
506 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
507 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
508 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
509 break;
510 }
511 }
512
513 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
514 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
515
516 return;
517}
518
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800519static bool usb_valid_device(int device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700520{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800521 bool is_usb_device = false;
522 if ((device & AUDIO_DEVICE_OUT_USB_DEVICE) ||
523 (device & AUDIO_DEVICE_IN_USB_DEVICE))
524 is_usb_device = true;
525 return is_usb_device;
526}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700527
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800528static void usb_print_active_device(void){
529 struct listnode *node_i, *node_j;
530 struct usb_device_config *dev_info;
531 struct usb_card_config *card_info;
532 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700533
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800534 ALOGI("%s", __func__);
535 list_for_each(node_i, &usbmod->usb_card_conf_list) {
536 card_info = node_to_item(node_i, struct usb_card_config, list);
537 ALOGI("%s: card_dev_type (0x%x), card_no(%d)",
538 __func__, card_info->usb_device_type, card_info->usb_card);
539 list_for_each(node_j, &card_info->usb_device_conf_list) {
540 dev_info = node_to_item(node_j, struct usb_device_config, list);
541 ALOGI("%s: bit-width(%d) channel(%d)",
542 __func__, dev_info->bit_width, dev_info->channels);
543 for (i = 0; i < dev_info->rate_size; i++)
544 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
545 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700546 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800547}
548
549static bool usb_get_best_match_for_bit_width(
550 struct listnode *dev_list,
551 unsigned int stream_bit_width,
552 unsigned int *bit_width)
553{
554 struct listnode *node_i;
555 struct usb_device_config *dev_info;
556 unsigned int candidate = 0;
557
558 list_for_each(node_i, dev_list) {
559 dev_info = node_to_item(node_i, struct usb_device_config, list);
560 ALOGI_IF(usb_audio_debug_enable,
561 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
562 __func__, dev_info->bit_width,
563 stream_bit_width, candidate);
564 if (dev_info->bit_width == stream_bit_width) {
565 *bit_width = dev_info->bit_width;
566 ALOGV("%s: Found match bit-width (%d)",
567 __func__, dev_info->bit_width);
568 goto exit;
569 } else if (candidate == 0) {
570 candidate = dev_info->bit_width;
571 }
572 /*
573 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
574 * higher bit width 32 is picked up instead of 16-bit
575 */
576 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
577 ABS_SUB(stream_bit_width, candidate)) {
578 candidate = dev_info->bit_width;
579 }
580 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
581 ABS_SUB(stream_bit_width, candidate)) &&
582 (dev_info->bit_width > candidate)) {
583 candidate = dev_info->bit_width;
584 }
585 }
586 ALOGV("%s: No match found, use the best candidate bw(%d)",
587 __func__, candidate);
588 *bit_width = candidate;
589exit:
590 return true;
591}
592
593static bool usb_get_best_match_for_channels(
594 struct listnode *dev_list,
595 unsigned int bit_width,
596 unsigned int stream_ch,
597 unsigned int *ch)
598{
599 struct listnode *node_i;
600 struct usb_device_config *dev_info;
601 unsigned int candidate = 0;
602
603 list_for_each(node_i, dev_list) {
604 dev_info = node_to_item(node_i, struct usb_device_config, list);
605 ALOGI_IF(usb_audio_debug_enable,
606 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
607 __func__, dev_info->channels, dev_info->bit_width,
608 stream_ch, bit_width, candidate);
609 if (dev_info->bit_width != bit_width)
610 continue;
611 if (dev_info->channels== stream_ch) {
612 *ch = dev_info->channels;
613 ALOGV("%s: Found match channels (%d)",
614 __func__, dev_info->channels);
615 goto exit;
616 } else if (candidate == 0)
617 candidate = dev_info->channels;
618 /*
619 * If stream channel is 4, USB supports both 3 and 5, then
620 * higher channel 5 is picked up instead of 3
621 */
622 else if (ABS_SUB(stream_ch, dev_info->channels) <
623 ABS_SUB(stream_ch, candidate)) {
624 candidate = dev_info->channels;
625 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
626 ABS_SUB(stream_ch, candidate)) &&
627 (dev_info->channels > candidate)) {
628 candidate = dev_info->channels;
629 }
630 }
631 ALOGV("%s: No match found, use the best candidate ch(%d)",
632 __func__, candidate);
633 *ch = candidate;
634exit:
635 return true;
636
637}
638
639static bool usb_sample_rate_multiple(
640 unsigned int stream_sample_rate,
641 unsigned int base)
642{
643 return (((stream_sample_rate / base) * base) == stream_sample_rate);
644}
645
646static bool usb_find_sample_rate_candidate(unsigned int base,
647 unsigned stream_rate,
648 unsigned int usb_rate,
649 unsigned int cur_candidate,
650 unsigned int *update_candidate)
651{
652 /* For sample rate, we should consider fracational sample rate as high priority.
653 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
654 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
655 */
656 if (!usb_sample_rate_multiple(cur_candidate, base) &&
657 usb_sample_rate_multiple(usb_rate, base)) {
658 *update_candidate = usb_rate;
659 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
660 usb_sample_rate_multiple(usb_rate, base)) {
661 if (ABS_SUB(stream_rate, usb_rate) <
662 ABS_SUB(stream_rate, cur_candidate)) {
663 *update_candidate = usb_rate;
664 } else if ((ABS_SUB(stream_rate, usb_rate) ==
665 ABS_SUB(stream_rate, cur_candidate)) &&
666 (usb_rate > cur_candidate)) {
667 *update_candidate = usb_rate;
668 }
669 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
670 !usb_sample_rate_multiple(usb_rate, base)) {
671 if (ABS_SUB(stream_rate, usb_rate) <
672 ABS_SUB(stream_rate, cur_candidate)) {
673 *update_candidate = usb_rate;
674 } else if ((ABS_SUB(stream_rate, usb_rate) ==
675 ABS_SUB(stream_rate, cur_candidate)) &&
676 (usb_rate > cur_candidate)) {
677 *update_candidate = usb_rate;
678 }
679 }
680 return true;
681}
682
683static bool usb_get_best_match_for_sample_rate(
684 struct listnode *dev_list,
685 unsigned int bit_width,
686 unsigned int ch,
687 unsigned int stream_sample_rate,
688 unsigned int *sr)
689{
690 struct listnode *node_i;
691 struct usb_device_config *dev_info;
692 unsigned int candidate = 48000;
693 unsigned int base = SAMPLE_RATE_8000;
694 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
695 unsigned int i;
696
697 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
698 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
699
700 list_for_each(node_i, dev_list) {
701 dev_info = node_to_item(node_i, struct usb_device_config, list);
702 ALOGI_IF(usb_audio_debug_enable,
703 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
704 __func__, dev_info->channels, dev_info->bit_width,
705 ch, bit_width, stream_sample_rate, candidate);
Ashish Jainb26edfb2016-08-25 00:10:11 +0530706 if ((dev_info->bit_width != bit_width) || dev_info->channels != ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800707 continue;
708
709 candidate = 0;
710 for (i = 0; i < dev_info->rate_size; i++) {
711 ALOGI_IF(usb_audio_debug_enable,
712 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
713 __func__, dev_info->channels,
714 dev_info->bit_width, dev_info->rates[i],
715 ch, bit_width, stream_sample_rate, candidate);
716 if (stream_sample_rate == dev_info->rates[i]) {
717 *sr = dev_info->rates[i];
718 ALOGV("%s: Found match sample rate (%d)",
719 __func__, dev_info->rates[i]);
720 goto exit;
721 } else if (candidate == 0) {
722 candidate = dev_info->rates[i];
723 /*
724 * For sample rate, we should consider fracational sample rate as high priority.
725 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
726 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
727 */
728 } else if (multiple_8k) {
729 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
730 stream_sample_rate,
731 dev_info->rates[i],
732 candidate,
733 &candidate);
734 } else {
735 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
736 stream_sample_rate,
737 dev_info->rates[i],
738 candidate,
739 &candidate);
740 }
741 }
742 }
743 ALOGV("%s: No match found, use the best candidate sr(%d)",
744 __func__, candidate);
745 *sr = candidate;
746exit:
747 return true;
748}
749
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800750static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
751 unsigned int *bit_width,
752 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530753 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800754{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800755 bool is_usb_supported = true;
756
757 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530758 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800759 if (list_empty(dev_list)) {
760 *sample_rate = 48000;
761 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530762 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800763 ALOGI("%s: list is empty,fall back to default setting", __func__);
764 goto exit;
765 }
766 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
767 usb_get_best_match_for_channels(dev_list,
768 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530769 *ch,
770 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800771 usb_get_best_match_for_sample_rate(dev_list,
772 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530773 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800774 *sample_rate,
775 sample_rate);
776exit:
777 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530778 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800779 return is_usb_supported;
780}
781
Kuirong Wang1cad7142016-05-24 15:21:56 -0700782static int usb_get_sidetone_gain(struct usb_card_config *card_info)
783{
784 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
785 if (gain > card_info->usb_sidetone_vol_max)
786 gain = card_info->usb_sidetone_vol_max;
787 return gain;
788}
789
790void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
791 char *value, int len)
792{
793 int err;
794
795 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
796 value, len);
797 if (err >= 0) {
798 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
799 ALOGV("%s: sidetone gain(%s) decimal %d",
800 __func__, value, usb_sidetone_gain);
801 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
802 }
803 return;
804}
805
806int audio_extn_usb_enable_sidetone(int device, bool enable)
807{
808 int ret = -ENODEV;
809 struct listnode *node_i;
810 struct usb_card_config *card_info;
811 int i;
812 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
813 __func__, device, enable);
814
815 list_for_each(node_i, &usbmod->usb_card_conf_list) {
816 card_info = node_to_item(node_i, struct usb_card_config, list);
817 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
818 __func__, card_info->usb_device_type, card_info->usb_card);
819 if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
820 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
821 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
822 card_info->usb_snd_mixer,
823 usb_sidetone_enable_str[i]);
824 if (ctl)
825 mixer_ctl_set_value(ctl, 0, enable);
826 else
827 break;
828
829 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
830 ctl = mixer_get_ctl_by_name(
831 card_info->usb_snd_mixer,
832 usb_sidetone_volume_str[i]);
833 if (ctl == NULL)
834 ALOGV("%s: sidetone gain mixer command is not found",
835 __func__);
836 else if (enable)
837 mixer_ctl_set_value(ctl, 0,
838 usb_get_sidetone_gain(card_info));
839 }
840 ret = 0;
841 break;
842 }
843 }
844 }
845 return ret;
846}
847
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800848bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
849 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700850 unsigned int *ch,
851 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800852{
853 struct listnode *node_i;
854 struct usb_card_config *card_info;
855 bool is_usb_supported = false;
856
Kuirong Wang27152a12016-11-11 10:20:30 -0800857 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
858 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800859 list_for_each(node_i, &usbmod->usb_card_conf_list) {
860 card_info = node_to_item(node_i, struct usb_card_config, list);
861 ALOGI_IF(usb_audio_debug_enable,
862 "%s: card_dev_type (0x%x), card_no(%d)",
863 __func__, card_info->usb_device_type, card_info->usb_card);
864 /* Currently only apply the first playback sound card configuration */
Kuirong Wang0b947f72016-09-29 11:03:09 -0700865 if ((is_playback && card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) ||
866 ((!is_playback) && card_info->usb_device_type == AUDIO_DEVICE_IN_USB_DEVICE)){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800867 is_usb_supported = usb_audio_backend_apply_policy(
868 &card_info->usb_device_conf_list,
869 bit_width,
870 sample_rate,
871 ch);
872 break;
873 }
874 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530875 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
876 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800877
878 return is_usb_supported;
879}
880
881void audio_extn_usb_add_device(audio_devices_t device, int card)
882{
883 struct usb_card_config *usb_card_info;
884 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -0800885 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800886
887 property_get("audio.usb.enable.debug", check_debug_enable, NULL);
888 if (atoi(check_debug_enable)) {
889 usb_audio_debug_enable = true;
890 }
891
892 ALOGI_IF(usb_audio_debug_enable,
893 "%s: parameters device(0x%x), card(%d)",
894 __func__, device, card);
895 if (usbmod == NULL) {
896 ALOGE("%s: USB device object is NULL", __func__);
897 goto exit;
898 }
899
900 if (!(usb_valid_device(device)) || (card < 0)) {
901 ALOGE("%s:device(0x%x), card(%d)",
902 __func__, device, card);
903 goto exit;
904 }
905
Kuirong Wang27152a12016-11-11 10:20:30 -0800906 list_for_each(node_i, &usbmod->usb_card_conf_list) {
907 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
908 ALOGI_IF(usb_audio_debug_enable,
909 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
910 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
911 /* If we have cached the capability */
912 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
913 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
914 __func__, device, card);
915 goto exit;
916 }
917 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800918 usb_card_info = calloc(1, sizeof(struct usb_card_config));
919 if (usb_card_info == NULL) {
920 ALOGE("%s: error unable to allocate memory",
921 __func__);
922 goto exit;
923 }
924 list_init(&usb_card_info->usb_device_conf_list);
925 if (device & AUDIO_DEVICE_OUT_USB_DEVICE) {
926 if (!usb_get_device_pb_config(usb_card_info, card)){
927 usb_card_info->usb_card = card;
928 usb_card_info->usb_device_type = AUDIO_DEVICE_OUT_USB_DEVICE;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700929 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800930 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
931 goto exit;
932 }
933 } else if (device & AUDIO_DEVICE_IN_USB_DEVICE) {
934 if (!usb_get_device_cap_config(usb_card_info, card)) {
935 usb_card_info->usb_card = card;
936 usb_card_info->usb_device_type = AUDIO_DEVICE_IN_USB_DEVICE;
937 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
938 goto exit;
939 }
940 }
941 /* free memory in error case */
942 if (usb_card_info != NULL)
943 free(usb_card_info);
944exit:
945 if (usb_audio_debug_enable)
946 usb_print_active_device();
947 return;
948}
949
950void audio_extn_usb_remove_device(audio_devices_t device, int card)
951{
952 struct listnode *node_i, *temp_i;
953 struct listnode *node_j, *temp_j;
954 struct usb_device_config *dev_info;
955 struct usb_card_config *card_info;
956 unsigned int i;
957
958 ALOGV("%s: device(0x%x), card(%d)",
959 __func__, device, card);
960
961 if (usbmod == NULL) {
962 ALOGE("%s: USB device object is NULL", __func__);
963 goto exit;
964 }
965
966 if (!(usb_valid_device(device)) || (card < 0)) {
967 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
968 __func__, device, card);
969 goto exit;
970 }
971 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
972 card_info = node_to_item(node_i, struct usb_card_config, list);
973 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
974 __func__, card_info->usb_device_type, card_info->usb_card);
975 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
976 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
977 dev_info = node_to_item(node_j, struct usb_device_config, list);
978 ALOGV("%s: bit-width(%d) channel(%d)",
979 __func__, dev_info->bit_width, dev_info->channels);
980 for (i = 0; i < dev_info->rate_size; i++)
981 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
982
983 list_remove(node_j);
984 free(node_to_item(node_j, struct usb_device_config, list));
985 }
986 list_remove(node_i);
987 free(node_to_item(node_i, struct usb_card_config, list));
988 }
989 }
990exit:
991 if (usb_audio_debug_enable)
992 usb_print_active_device();
993
994 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700995}
996
997void audio_extn_usb_init(void *adev)
998{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800999 if (usbmod == NULL) {
1000 usbmod = calloc(1, sizeof(struct usb_module));
1001 if (usbmod == NULL) {
1002 ALOGE("%s: error unable to allocate memory", __func__);
1003 goto exit;
1004 }
1005 }
1006 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001007 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001008 usbmod->sidetone_gain = usb_sidetone_gain;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001009exit:
1010 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001011}
1012
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001013void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001014{
1015 if (NULL != usbmod){
1016 free(usbmod);
1017 usbmod = NULL;
1018 }
1019}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001020#endif /*USB_HEADSET_ENABLED end*/