blob: a7b10d9b6f93bcb75b26adb899dbee4e6e89e388 [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[] =
50 {44100, 48000, 64000, 88200, 96000, 176400, 192000};
51
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_channel_mixer_ctl(int channel,
194 char *ch_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700195{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800196 struct mixer_ctl *ctl;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700197
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800198 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, ch_mixer_ctl_name);
199 if (!ctl) {
200 ALOGE("%s: Could not get ctl for mixer cmd - %s",
201 __func__, ch_mixer_ctl_name);
202 return -EINVAL;
Satish Babu Patakokila6c9fe832014-03-26 15:02:12 +0530203 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800204 switch (channel) {
205 case 1:
206 mixer_ctl_set_enum_by_string(ctl, "One");
207 break;
208 case 2:
209 mixer_ctl_set_enum_by_string(ctl, "Two");
210 break;
211 default:
212 ALOGV("%s: channel(%d) not supported, set as default 2 channels",
213 __func__, channel);
214 mixer_ctl_set_enum_by_string(ctl, "Two");
215 break;
216 }
217 return 0;
Satish Babu Patakokila6c9fe832014-03-26 15:02:12 +0530218}
219
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800220static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
221 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700222{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800223 struct mixer_ctl *ctl;
224 unsigned int dev_token;
225 unsigned int pcm_device_number = 0;
226
227 /*
228 * usb_dev_token_id is 32 bit number and is defined as below:
229 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
230 */
231 dev_token = (card << 16 ) |
232 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
233
234 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
235 if (!ctl) {
236 ALOGE("%s: Could not get ctl for mixer cmd - %s",
237 __func__, dev_mixer_ctl_name);
238 return -EINVAL;
239 }
240 mixer_ctl_set_value(ctl, 0, dev_token);
241
242 return 0;
243}
244
245static int usb_get_sample_rates(char *rates_str,
246 struct usb_device_config *config)
247{
248 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700249 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800250 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700251
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800252 /* Sample rate string can be in any of the folloing two bit_widthes:
253 * Rates: 8000 - 48000 (continuous)
254 * Rates: 8000, 44100, 48000
255 * Support both the bit_widths
256 */
257 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700258 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
259 if (next_sr_string == NULL) {
260 ALOGE("%s: could not find min rates string", __func__);
261 return -EINVAL;
262 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800263 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700264 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700265 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800266 if (next_sr_string == NULL) {
267 ALOGE("%s: could not find max rates string", __func__);
268 return -EINVAL;
269 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700270 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800271
Kuirong Wang591a98a2016-06-27 12:41:41 -0700272 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800273 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700274 supported_sample_rates[i] <= max_sr) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800275 config->rates[sr_size++] = supported_sample_rates[i];
Kuirong Wang591a98a2016-06-27 12:41:41 -0700276 ALOGI_IF(usb_audio_debug_enable,
277 "%s: continuous sample rate supported_sample_rates[%d] %d",
278 __func__, i, supported_sample_rates[i]);
279 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800280 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700281 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800282 do {
283 sr = (uint32_t)atoi(next_sr_string);
284 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
285 if (supported_sample_rates[i] == sr) {
286 ALOGI_IF(usb_audio_debug_enable,
287 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
288 __func__, sr, i, supported_sample_rates[i]);
289 config->rates[sr_size++] = supported_sample_rates[i];
290 }
291 }
292 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
293 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700294 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800295 config->rate_size = sr_size;
296 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700297}
298
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800299static int usb_get_capability(int type,
300 struct usb_card_config *usb_card_info,
301 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700302{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700303 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800304 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800305 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700306 char *str_start = NULL;
307 char *str_end = NULL;
308 char *channel_start = NULL;
309 char *bit_width_start = NULL;
310 char *rates_str_start = NULL;
311 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700312 char *read_buf = NULL;
313 char *rates_str = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700314 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700315 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800316 char *bit_width_str = NULL;
317 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700318 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700319
Kuirong Wange9894162016-08-26 15:16:39 -0700320 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800321 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
322 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
323
Kuirong Wange9894162016-08-26 15:16:39 -0700324 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800325 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700326 if(ret < 0) {
327 ALOGE("%s: failed on snprintf (%d) to path %s\n",
328 __func__, ret, path);
329 goto done;
330 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700331
332 fd = open(path, O_RDONLY);
333 if (fd <0) {
334 ALOGE("%s: error failed to open config file %s error: %d\n",
335 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700336 ret = -EINVAL;
337 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700338 }
339
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800340 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700341
342 if (!read_buf) {
343 ALOGE("Failed to create read_buf");
344 ret = -ENOMEM;
345 goto done;
346 }
347
Kuirong Wange9894162016-08-26 15:16:39 -0700348 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
349 ALOGE("file read error\n");
350 goto done;
351 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800352 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
353 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700354 if (str_start == NULL) {
355 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800356 __func__, ((type == USB_PLAYBACK) ?
357 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700358 ret = -EINVAL;
359 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700360 }
Kuirong Wange9894162016-08-26 15:16:39 -0700361 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
362 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
363 if (str_end > str_start)
364 check = true;
365
366 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700367
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800368 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700369 str_start = strstr(str_start, "Altset");
370 if ((str_start == NULL) || (check && (str_start >= str_end))) {
371 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800372 break;
373 }
Kuirong Wange9894162016-08-26 15:16:39 -0700374 ALOGV("%s: remaining string %s\n", __func__, str_start);
375 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800376 usb_device_info = calloc(1, sizeof(struct usb_device_config));
377 if (usb_device_info == NULL) {
378 ALOGE("%s: error unable to allocate memory",
379 __func__);
380 ret = -ENOMEM;
381 break;
382 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800383 /* Bit bit_width parsing */
384 bit_width_start = strstr(str_start, "Format: ");
385 if (bit_width_start == NULL) {
386 ALOGI("%s: Could not find bit_width string", __func__);
387 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700388 continue;
389 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800390 target = strchr(bit_width_start, '\n');
391 if (target == NULL) {
392 ALOGI("%s:end of line not found", __func__);
393 free(usb_device_info);
394 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700395 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800396 size = target - bit_width_start;
397 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
398 ALOGE("%s: unable to allocate memory to hold bit width strings",
399 __func__);
400 ret = -EINVAL;
401 free(usb_device_info);
402 break;
403 }
404 memcpy(bit_width_str, bit_width_start, size);
405 bit_width_str[size] = '\0';
406 if (strstr(bit_width_str, "S16_LE"))
407 usb_device_info->bit_width = 16;
408 else if (strstr(bit_width_str, "S24_LE"))
409 usb_device_info->bit_width = 24;
410 else if (strstr(bit_width_str, "S24_3LE"))
411 usb_device_info->bit_width = 24;
412 else if (strstr(bit_width_str, "S32_LE"))
413 usb_device_info->bit_width = 32;
414
415 if (bit_width_str)
416 free(bit_width_str);
417
418 /* channels parsing */
419 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
420 if (channel_start == NULL) {
421 ALOGI("%s: could not find Channels string", __func__);
422 free(usb_device_info);
423 continue;
424 }
425 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
426 usb_device_info->channels = channels_no;
427
428 /* Sample rates parsing */
429 rates_str_start = strstr(str_start, "Rates: ");
430 if (rates_str_start == NULL) {
431 ALOGI("%s: cant find rates string", __func__);
432 free(usb_device_info);
433 continue;
434 }
435 target = strchr(rates_str_start, '\n');
436 if (target == NULL) {
437 ALOGI("%s: end of line not found", __func__);
438 free(usb_device_info);
439 continue;
440 }
441 size = target - rates_str_start;
442 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
443 ALOGE("%s: unable to allocate memory to hold sample rate strings",
444 __func__);
445 ret = -EINVAL;
446 free(usb_device_info);
447 break;
448 }
449 memcpy(rates_str, rates_str_start, size);
450 rates_str[size] = '\0';
451 ret = usb_get_sample_rates(rates_str, usb_device_info);
452 if (rates_str)
453 free(rates_str);
454 if (ret < 0) {
455 ALOGI("%s: error unable to get sample rate values",
456 __func__);
457 free(usb_device_info);
458 continue;
459 }
460 /* Add to list if every field is valid */
461 list_add_tail(&usb_card_info->usb_device_conf_list,
462 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700463 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700464
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700465done:
466 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700467 if (read_buf) free(read_buf);
468 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700469}
470
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800471static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
472 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700473{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800474 int ret;
475 struct listnode *node_d;
476 struct usb_device_config *dev_info;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700477
478 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800479 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
480 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700481 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800482 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700483 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800484 /* Currently only use the first profile using to configure channel for simplification */
485 list_for_each(node_d, &usb_card_info->usb_device_conf_list) {
486 dev_info = node_to_item(node_d, struct usb_device_config, list);
487 if (dev_info != NULL) {
488 usb_set_channel_mixer_ctl(dev_info->channels, "USB_AUDIO_RX Channels");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700489 break;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800490 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700491 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800492 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
493
494exit:
495
496 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700497}
498
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800499static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
500 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700501{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800502 int ret;
503 struct listnode *node_d;
504 struct usb_device_config *dev_info;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700505
506 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800507 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
508 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700509 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800510 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800512 /* Currently only use the first profile using to configure channel for simplification */
513 list_for_each(node_d, &usb_card_info->usb_device_conf_list) {
514 dev_info = node_to_item(node_d, struct usb_device_config, list);
515 if (dev_info != NULL) {
516 usb_set_channel_mixer_ctl(dev_info->channels, "USB_AUDIO_TX Channels");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700517 break;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800518 }
519 }
520 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700521
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800522exit:
523 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700524}
525
Kuirong Wang1cad7142016-05-24 15:21:56 -0700526static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
527{
528 struct mixer_ctl *ctl;
529 unsigned int index;
530
531 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
532 usb_card_info->usb_sidetone_index[index] = -1;
533
534 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
535 for (index = 0;
536 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
537 index++) {
538 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
539 usb_sidetone_enable_str[index]);
540 if (ctl) {
541 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
542 /* Disable device sidetone by default */
543 mixer_ctl_set_value(ctl, 0, false);
544 break;
545 }
546 }
547 for (index = 0;
548 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
549 index++) {
550 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
551 usb_sidetone_volume_str[index]);
552 if (ctl) {
553 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
554 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
555 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
556 break;
557 }
558 }
559
560 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
561 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
562
563 return;
564}
565
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800566static bool usb_valid_device(int device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700567{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800568 bool is_usb_device = false;
569 if ((device & AUDIO_DEVICE_OUT_USB_DEVICE) ||
570 (device & AUDIO_DEVICE_IN_USB_DEVICE))
571 is_usb_device = true;
572 return is_usb_device;
573}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700574
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800575static void usb_print_active_device(void){
576 struct listnode *node_i, *node_j;
577 struct usb_device_config *dev_info;
578 struct usb_card_config *card_info;
579 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700580
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800581 ALOGI("%s", __func__);
582 list_for_each(node_i, &usbmod->usb_card_conf_list) {
583 card_info = node_to_item(node_i, struct usb_card_config, list);
584 ALOGI("%s: card_dev_type (0x%x), card_no(%d)",
585 __func__, card_info->usb_device_type, card_info->usb_card);
586 list_for_each(node_j, &card_info->usb_device_conf_list) {
587 dev_info = node_to_item(node_j, struct usb_device_config, list);
588 ALOGI("%s: bit-width(%d) channel(%d)",
589 __func__, dev_info->bit_width, dev_info->channels);
590 for (i = 0; i < dev_info->rate_size; i++)
591 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
592 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700593 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800594}
595
596static bool usb_get_best_match_for_bit_width(
597 struct listnode *dev_list,
598 unsigned int stream_bit_width,
599 unsigned int *bit_width)
600{
601 struct listnode *node_i;
602 struct usb_device_config *dev_info;
603 unsigned int candidate = 0;
604
605 list_for_each(node_i, dev_list) {
606 dev_info = node_to_item(node_i, struct usb_device_config, list);
607 ALOGI_IF(usb_audio_debug_enable,
608 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
609 __func__, dev_info->bit_width,
610 stream_bit_width, candidate);
611 if (dev_info->bit_width == stream_bit_width) {
612 *bit_width = dev_info->bit_width;
613 ALOGV("%s: Found match bit-width (%d)",
614 __func__, dev_info->bit_width);
615 goto exit;
616 } else if (candidate == 0) {
617 candidate = dev_info->bit_width;
618 }
619 /*
620 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
621 * higher bit width 32 is picked up instead of 16-bit
622 */
623 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
624 ABS_SUB(stream_bit_width, candidate)) {
625 candidate = dev_info->bit_width;
626 }
627 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
628 ABS_SUB(stream_bit_width, candidate)) &&
629 (dev_info->bit_width > candidate)) {
630 candidate = dev_info->bit_width;
631 }
632 }
633 ALOGV("%s: No match found, use the best candidate bw(%d)",
634 __func__, candidate);
635 *bit_width = candidate;
636exit:
637 return true;
638}
639
640static bool usb_get_best_match_for_channels(
641 struct listnode *dev_list,
642 unsigned int bit_width,
643 unsigned int stream_ch,
644 unsigned int *ch)
645{
646 struct listnode *node_i;
647 struct usb_device_config *dev_info;
648 unsigned int candidate = 0;
649
650 list_for_each(node_i, dev_list) {
651 dev_info = node_to_item(node_i, struct usb_device_config, list);
652 ALOGI_IF(usb_audio_debug_enable,
653 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
654 __func__, dev_info->channels, dev_info->bit_width,
655 stream_ch, bit_width, candidate);
656 if (dev_info->bit_width != bit_width)
657 continue;
658 if (dev_info->channels== stream_ch) {
659 *ch = dev_info->channels;
660 ALOGV("%s: Found match channels (%d)",
661 __func__, dev_info->channels);
662 goto exit;
663 } else if (candidate == 0)
664 candidate = dev_info->channels;
665 /*
666 * If stream channel is 4, USB supports both 3 and 5, then
667 * higher channel 5 is picked up instead of 3
668 */
669 else if (ABS_SUB(stream_ch, dev_info->channels) <
670 ABS_SUB(stream_ch, candidate)) {
671 candidate = dev_info->channels;
672 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
673 ABS_SUB(stream_ch, candidate)) &&
674 (dev_info->channels > candidate)) {
675 candidate = dev_info->channels;
676 }
677 }
678 ALOGV("%s: No match found, use the best candidate ch(%d)",
679 __func__, candidate);
680 *ch = candidate;
681exit:
682 return true;
683
684}
685
686static bool usb_sample_rate_multiple(
687 unsigned int stream_sample_rate,
688 unsigned int base)
689{
690 return (((stream_sample_rate / base) * base) == stream_sample_rate);
691}
692
693static bool usb_find_sample_rate_candidate(unsigned int base,
694 unsigned stream_rate,
695 unsigned int usb_rate,
696 unsigned int cur_candidate,
697 unsigned int *update_candidate)
698{
699 /* For sample rate, we should consider fracational sample rate as high priority.
700 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
701 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
702 */
703 if (!usb_sample_rate_multiple(cur_candidate, base) &&
704 usb_sample_rate_multiple(usb_rate, base)) {
705 *update_candidate = usb_rate;
706 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
707 usb_sample_rate_multiple(usb_rate, base)) {
708 if (ABS_SUB(stream_rate, usb_rate) <
709 ABS_SUB(stream_rate, cur_candidate)) {
710 *update_candidate = usb_rate;
711 } else if ((ABS_SUB(stream_rate, usb_rate) ==
712 ABS_SUB(stream_rate, cur_candidate)) &&
713 (usb_rate > cur_candidate)) {
714 *update_candidate = usb_rate;
715 }
716 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
717 !usb_sample_rate_multiple(usb_rate, base)) {
718 if (ABS_SUB(stream_rate, usb_rate) <
719 ABS_SUB(stream_rate, cur_candidate)) {
720 *update_candidate = usb_rate;
721 } else if ((ABS_SUB(stream_rate, usb_rate) ==
722 ABS_SUB(stream_rate, cur_candidate)) &&
723 (usb_rate > cur_candidate)) {
724 *update_candidate = usb_rate;
725 }
726 }
727 return true;
728}
729
730static bool usb_get_best_match_for_sample_rate(
731 struct listnode *dev_list,
732 unsigned int bit_width,
733 unsigned int ch,
734 unsigned int stream_sample_rate,
735 unsigned int *sr)
736{
737 struct listnode *node_i;
738 struct usb_device_config *dev_info;
739 unsigned int candidate = 48000;
740 unsigned int base = SAMPLE_RATE_8000;
741 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
742 unsigned int i;
743
744 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
745 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
746
747 list_for_each(node_i, dev_list) {
748 dev_info = node_to_item(node_i, struct usb_device_config, list);
749 ALOGI_IF(usb_audio_debug_enable,
750 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
751 __func__, dev_info->channels, dev_info->bit_width,
752 ch, bit_width, stream_sample_rate, candidate);
Ashish Jainb26edfb2016-08-25 00:10:11 +0530753 if ((dev_info->bit_width != bit_width) || dev_info->channels != ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800754 continue;
755
756 candidate = 0;
757 for (i = 0; i < dev_info->rate_size; i++) {
758 ALOGI_IF(usb_audio_debug_enable,
759 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
760 __func__, dev_info->channels,
761 dev_info->bit_width, dev_info->rates[i],
762 ch, bit_width, stream_sample_rate, candidate);
763 if (stream_sample_rate == dev_info->rates[i]) {
764 *sr = dev_info->rates[i];
765 ALOGV("%s: Found match sample rate (%d)",
766 __func__, dev_info->rates[i]);
767 goto exit;
768 } else if (candidate == 0) {
769 candidate = dev_info->rates[i];
770 /*
771 * For sample rate, we should consider fracational sample rate as high priority.
772 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
773 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
774 */
775 } else if (multiple_8k) {
776 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
777 stream_sample_rate,
778 dev_info->rates[i],
779 candidate,
780 &candidate);
781 } else {
782 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
783 stream_sample_rate,
784 dev_info->rates[i],
785 candidate,
786 &candidate);
787 }
788 }
789 }
790 ALOGV("%s: No match found, use the best candidate sr(%d)",
791 __func__, candidate);
792 *sr = candidate;
793exit:
794 return true;
795}
796
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800797static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
798 unsigned int *bit_width,
799 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530800 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800801{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800802 bool is_usb_supported = true;
803
804 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530805 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800806 if (list_empty(dev_list)) {
807 *sample_rate = 48000;
808 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530809 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800810 ALOGI("%s: list is empty,fall back to default setting", __func__);
811 goto exit;
812 }
813 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
814 usb_get_best_match_for_channels(dev_list,
815 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530816 *ch,
817 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800818 usb_get_best_match_for_sample_rate(dev_list,
819 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530820 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800821 *sample_rate,
822 sample_rate);
823exit:
824 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530825 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800826 return is_usb_supported;
827}
828
Kuirong Wang1cad7142016-05-24 15:21:56 -0700829static int usb_get_sidetone_gain(struct usb_card_config *card_info)
830{
831 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
832 if (gain > card_info->usb_sidetone_vol_max)
833 gain = card_info->usb_sidetone_vol_max;
834 return gain;
835}
836
837void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
838 char *value, int len)
839{
840 int err;
841
842 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
843 value, len);
844 if (err >= 0) {
845 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
846 ALOGV("%s: sidetone gain(%s) decimal %d",
847 __func__, value, usb_sidetone_gain);
848 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
849 }
850 return;
851}
852
853int audio_extn_usb_enable_sidetone(int device, bool enable)
854{
855 int ret = -ENODEV;
856 struct listnode *node_i;
857 struct usb_card_config *card_info;
858 int i;
859 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
860 __func__, device, enable);
861
862 list_for_each(node_i, &usbmod->usb_card_conf_list) {
863 card_info = node_to_item(node_i, struct usb_card_config, list);
864 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
865 __func__, card_info->usb_device_type, card_info->usb_card);
866 if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
867 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
868 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
869 card_info->usb_snd_mixer,
870 usb_sidetone_enable_str[i]);
871 if (ctl)
872 mixer_ctl_set_value(ctl, 0, enable);
873 else
874 break;
875
876 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
877 ctl = mixer_get_ctl_by_name(
878 card_info->usb_snd_mixer,
879 usb_sidetone_volume_str[i]);
880 if (ctl == NULL)
881 ALOGV("%s: sidetone gain mixer command is not found",
882 __func__);
883 else if (enable)
884 mixer_ctl_set_value(ctl, 0,
885 usb_get_sidetone_gain(card_info));
886 }
887 ret = 0;
888 break;
889 }
890 }
891 }
892 return ret;
893}
894
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800895bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
896 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700897 unsigned int *ch,
898 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800899{
900 struct listnode *node_i;
901 struct usb_card_config *card_info;
902 bool is_usb_supported = false;
903
904 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530905 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800906 list_for_each(node_i, &usbmod->usb_card_conf_list) {
907 card_info = node_to_item(node_i, struct usb_card_config, list);
908 ALOGI_IF(usb_audio_debug_enable,
909 "%s: card_dev_type (0x%x), card_no(%d)",
910 __func__, card_info->usb_device_type, card_info->usb_card);
911 /* Currently only apply the first playback sound card configuration */
Kuirong Wange9894162016-08-26 15:16:39 -0700912 if (is_playback && card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
913 is_usb_supported = usb_audio_backend_apply_policy(
914 &card_info->usb_device_conf_list,
915 bit_width,
916 sample_rate,
917 ch);
918 break;
919 } else if (card_info->usb_device_type == AUDIO_DEVICE_IN_USB_DEVICE ) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800920 is_usb_supported = usb_audio_backend_apply_policy(
921 &card_info->usb_device_conf_list,
922 bit_width,
923 sample_rate,
924 ch);
925 break;
926 }
927 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530928 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
929 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800930
931 return is_usb_supported;
932}
933
934void audio_extn_usb_add_device(audio_devices_t device, int card)
935{
936 struct usb_card_config *usb_card_info;
937 char check_debug_enable[PROPERTY_VALUE_MAX];
938
939 property_get("audio.usb.enable.debug", check_debug_enable, NULL);
940 if (atoi(check_debug_enable)) {
941 usb_audio_debug_enable = true;
942 }
943
944 ALOGI_IF(usb_audio_debug_enable,
945 "%s: parameters device(0x%x), card(%d)",
946 __func__, device, card);
947 if (usbmod == NULL) {
948 ALOGE("%s: USB device object is NULL", __func__);
949 goto exit;
950 }
951
952 if (!(usb_valid_device(device)) || (card < 0)) {
953 ALOGE("%s:device(0x%x), card(%d)",
954 __func__, device, card);
955 goto exit;
956 }
957
958 usb_card_info = calloc(1, sizeof(struct usb_card_config));
959 if (usb_card_info == NULL) {
960 ALOGE("%s: error unable to allocate memory",
961 __func__);
962 goto exit;
963 }
964 list_init(&usb_card_info->usb_device_conf_list);
965 if (device & AUDIO_DEVICE_OUT_USB_DEVICE) {
966 if (!usb_get_device_pb_config(usb_card_info, card)){
967 usb_card_info->usb_card = card;
968 usb_card_info->usb_device_type = AUDIO_DEVICE_OUT_USB_DEVICE;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700969 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800970 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
971 goto exit;
972 }
973 } else if (device & AUDIO_DEVICE_IN_USB_DEVICE) {
974 if (!usb_get_device_cap_config(usb_card_info, card)) {
975 usb_card_info->usb_card = card;
976 usb_card_info->usb_device_type = AUDIO_DEVICE_IN_USB_DEVICE;
977 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
978 goto exit;
979 }
980 }
981 /* free memory in error case */
982 if (usb_card_info != NULL)
983 free(usb_card_info);
984exit:
985 if (usb_audio_debug_enable)
986 usb_print_active_device();
987 return;
988}
989
990void audio_extn_usb_remove_device(audio_devices_t device, int card)
991{
992 struct listnode *node_i, *temp_i;
993 struct listnode *node_j, *temp_j;
994 struct usb_device_config *dev_info;
995 struct usb_card_config *card_info;
996 unsigned int i;
997
998 ALOGV("%s: device(0x%x), card(%d)",
999 __func__, device, card);
1000
1001 if (usbmod == NULL) {
1002 ALOGE("%s: USB device object is NULL", __func__);
1003 goto exit;
1004 }
1005
1006 if (!(usb_valid_device(device)) || (card < 0)) {
1007 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1008 __func__, device, card);
1009 goto exit;
1010 }
1011 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1012 card_info = node_to_item(node_i, struct usb_card_config, list);
1013 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1014 __func__, card_info->usb_device_type, card_info->usb_card);
1015 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1016 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1017 dev_info = node_to_item(node_j, struct usb_device_config, list);
1018 ALOGV("%s: bit-width(%d) channel(%d)",
1019 __func__, dev_info->bit_width, dev_info->channels);
1020 for (i = 0; i < dev_info->rate_size; i++)
1021 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1022
1023 list_remove(node_j);
1024 free(node_to_item(node_j, struct usb_device_config, list));
1025 }
1026 list_remove(node_i);
1027 free(node_to_item(node_i, struct usb_card_config, list));
1028 }
1029 }
1030exit:
1031 if (usb_audio_debug_enable)
1032 usb_print_active_device();
1033
1034 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001035}
1036
1037void audio_extn_usb_init(void *adev)
1038{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001039 if (usbmod == NULL) {
1040 usbmod = calloc(1, sizeof(struct usb_module));
1041 if (usbmod == NULL) {
1042 ALOGE("%s: error unable to allocate memory", __func__);
1043 goto exit;
1044 }
1045 }
1046 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001047 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001048 usbmod->sidetone_gain = usb_sidetone_gain;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001049exit:
1050 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001051}
1052
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001053void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001054{
1055 if (NULL != usbmod){
1056 free(usbmod);
1057 usbmod = NULL;
1058 }
1059}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001060#endif /*USB_HEADSET_ENABLED end*/