blob: 532797358f5b4ebbb8f64aeed2806520c68198ab [file] [log] [blame]
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001/*
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -07002 * Copyright (c) 2013, 2016-2017 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
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053039#ifdef DYNAMIC_LOG_ENABLED
40#include <log_xml_parser.h>
41#define LOG_MASK HAL_MOD_FILE_USB
42#include <log_utils.h>
43#endif
44
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070045#ifdef USB_HEADSET_ENABLED
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080046#define USB_BUFF_SIZE 2048
47#define CHANNEL_NUMBER_STR "Channels: "
48#define PLAYBACK_PROFILE_STR "Playback:"
49#define CAPTURE_PROFILE_STR "Capture:"
Kuirong Wang1cad7142016-05-24 15:21:56 -070050#define USB_SIDETONE_GAIN_STR "usb_sidetone_gain"
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080051#define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A)))
52#define SAMPLE_RATE_8000 8000
53#define SAMPLE_RATE_11025 11025
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080054// Supported sample rates for USB
55static uint32_t supported_sample_rates[] =
vivek mehta460565b2017-03-21 23:28:37 -070056 {44100, 48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000};
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080057
58#define MAX_SAMPLE_RATE_SIZE sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
59
60enum usb_usecase_type{
61 USB_PLAYBACK = 0,
62 USB_CAPTURE,
63};
64
Kuirong Wang1cad7142016-05-24 15:21:56 -070065enum {
66 USB_SIDETONE_ENABLE_INDEX = 0,
67 USB_SIDETONE_VOLUME_INDEX,
68 USB_SIDETONE_MAX_INDEX,
69};
70
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080071struct usb_device_config {
72 struct listnode list;
73 unsigned int bit_width;
74 unsigned int channels;
75 unsigned int rate_size;
76 unsigned int rates[MAX_SAMPLE_RATE_SIZE];
77};
78
79struct usb_card_config {
80 struct listnode list;
81 audio_devices_t usb_device_type;
82 int usb_card;
83 struct listnode usb_device_conf_list;
Kuirong Wang1cad7142016-05-24 15:21:56 -070084 struct mixer *usb_snd_mixer;
85 int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
86 int usb_sidetone_vol_min;
87 int usb_sidetone_vol_max;
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -070088 int endian;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080089};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070090
91struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080092 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070093 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -070094 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +053095 bool is_capture_supported;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070096};
97
98static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080099static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700100static int usb_sidetone_gain = 0;
101
102static const char * const usb_sidetone_enable_str[] = {
103 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -0700104 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -0700105};
106
107static const char * const usb_sidetone_volume_str[] = {
108 "Sidetone Playback Volume",
109 "Mic Playback Volume",
110};
111
112static void usb_mixer_print_enum(struct mixer_ctl *ctl)
113{
114 unsigned int num_enums;
115 unsigned int i;
116 const char *string;
117
118 num_enums = mixer_ctl_get_num_enums(ctl);
119
120 for (i = 0; i < num_enums; i++) {
121 string = mixer_ctl_get_enum_string(ctl, i);
122 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
123 }
124}
125
126static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
127{
128 struct mixer_ctl *ctl;
129 enum mixer_ctl_type type;
130 unsigned int num_values;
131 unsigned int i;
132 int min, max;
133
134 if (isdigit(control[0]))
135 ctl = mixer_get_ctl(mixer, atoi(control));
136 else
137 ctl = mixer_get_ctl_by_name(mixer, control);
138
139 if (!ctl) {
140 fprintf(stderr, "Invalid mixer control\n");
141 return;
142 }
143
144 type = mixer_ctl_get_type(ctl);
145 num_values = mixer_ctl_get_num_values(ctl);
146
147 ALOGI("%s:", mixer_ctl_get_name(ctl));
148
149 for (i = 0; i < num_values; i++) {
150 switch (type) {
151 case MIXER_CTL_TYPE_INT:
152 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
153 break;
154 case MIXER_CTL_TYPE_BOOL:
155 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
156 break;
157 case MIXER_CTL_TYPE_ENUM:
158 usb_mixer_print_enum(ctl);
159 break;
160 case MIXER_CTL_TYPE_BYTE:
161 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
162 break;
163 default:
164 ALOGI(" unknown");
165 break;
166 }
167 }
168
169 if (type == MIXER_CTL_TYPE_INT) {
170 min = mixer_ctl_get_range_min(ctl);
171 max = mixer_ctl_get_range_max(ctl);
172 ALOGI(" (range %d->%d)", min, max);
173 }
174}
175
176static void usb_soundcard_list_controls(struct mixer *mixer)
177{
178 struct mixer_ctl *ctl;
179 const char *name, *type;
180 unsigned int num_ctls, num_values;
181 unsigned int i;
182
183 num_ctls = mixer_get_num_ctls(mixer);
184
185 ALOGI("Number of controls: %d\n", num_ctls);
186
187 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
188 for (i = 0; i < num_ctls; i++) {
189 ctl = mixer_get_ctl(mixer, i);
190 if (ctl != NULL) {
191 name = mixer_ctl_get_name(ctl);
192 type = mixer_ctl_get_type_string(ctl);
193 num_values = mixer_ctl_get_num_values(ctl);
194 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
195 if (name != NULL)
196 usb_soundcard_detail_control(mixer, name);
197 }
198 }
199}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700200
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800201static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
202 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700203{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800204 struct mixer_ctl *ctl;
205 unsigned int dev_token;
206 unsigned int pcm_device_number = 0;
207
208 /*
209 * usb_dev_token_id is 32 bit number and is defined as below:
210 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
211 */
212 dev_token = (card << 16 ) |
213 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
214
215 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
216 if (!ctl) {
217 ALOGE("%s: Could not get ctl for mixer cmd - %s",
218 __func__, dev_mixer_ctl_name);
219 return -EINVAL;
220 }
221 mixer_ctl_set_value(ctl, 0, dev_token);
222
223 return 0;
224}
225
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700226static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
227{
228 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
229 endian_mixer_ctl_name);
230 if (!ctl) {
231 ALOGE("%s: Could not get ctl for mixer cmd - %s",
232 __func__, endian_mixer_ctl_name);
233 return -EINVAL;
234 }
235
236 switch (endian) {
237 case 0:
238 case 1:
239 mixer_ctl_set_value(ctl, 0, endian);
240 break;
241 default:
242 ALOGW("%s: endianness(%d) not supported",
243 __func__, endian);
244 break;
245 }
246 return 0;
247}
248
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800249static int usb_get_sample_rates(char *rates_str,
250 struct usb_device_config *config)
251{
252 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700253 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800254 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700255
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800256 /* Sample rate string can be in any of the folloing two bit_widthes:
257 * Rates: 8000 - 48000 (continuous)
258 * Rates: 8000, 44100, 48000
259 * Support both the bit_widths
260 */
261 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700262 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
263 if (next_sr_string == NULL) {
264 ALOGE("%s: could not find min rates string", __func__);
265 return -EINVAL;
266 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800267 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700268 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700269 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800270 if (next_sr_string == NULL) {
271 ALOGE("%s: could not find max rates string", __func__);
272 return -EINVAL;
273 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700274 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800275
Kuirong Wang591a98a2016-06-27 12:41:41 -0700276 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800277 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700278 supported_sample_rates[i] <= max_sr) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800279 config->rates[sr_size++] = supported_sample_rates[i];
Kuirong Wang591a98a2016-06-27 12:41:41 -0700280 ALOGI_IF(usb_audio_debug_enable,
281 "%s: continuous sample rate supported_sample_rates[%d] %d",
282 __func__, i, supported_sample_rates[i]);
283 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800284 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700285 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800286 do {
287 sr = (uint32_t)atoi(next_sr_string);
288 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
289 if (supported_sample_rates[i] == sr) {
290 ALOGI_IF(usb_audio_debug_enable,
291 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
292 __func__, sr, i, supported_sample_rates[i]);
293 config->rates[sr_size++] = supported_sample_rates[i];
294 }
295 }
296 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
297 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700298 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800299 config->rate_size = sr_size;
300 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700301}
302
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800303static int usb_get_capability(int type,
304 struct usb_card_config *usb_card_info,
305 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700306{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700307 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800308 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800309 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700310 char *str_start = NULL;
311 char *str_end = NULL;
312 char *channel_start = NULL;
313 char *bit_width_start = NULL;
314 char *rates_str_start = NULL;
315 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700316 char *read_buf = NULL;
317 char *rates_str = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700318 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700319 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800320 char *bit_width_str = NULL;
321 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700322 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700323
Kuirong Wange9894162016-08-26 15:16:39 -0700324 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800325 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
326 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
327
Kuirong Wange9894162016-08-26 15:16:39 -0700328 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800329 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700330 if(ret < 0) {
331 ALOGE("%s: failed on snprintf (%d) to path %s\n",
332 __func__, ret, path);
333 goto done;
334 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700335
336 fd = open(path, O_RDONLY);
337 if (fd <0) {
338 ALOGE("%s: error failed to open config file %s error: %d\n",
339 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700340 ret = -EINVAL;
341 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700342 }
343
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800344 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700345
346 if (!read_buf) {
347 ALOGE("Failed to create read_buf");
348 ret = -ENOMEM;
349 goto done;
350 }
351
Kuirong Wange9894162016-08-26 15:16:39 -0700352 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
353 ALOGE("file read error\n");
354 goto done;
355 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800356 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
357 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700358 if (str_start == NULL) {
359 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800360 __func__, ((type == USB_PLAYBACK) ?
361 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700362 ret = -EINVAL;
363 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700364 }
Kuirong Wange9894162016-08-26 15:16:39 -0700365 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
366 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
367 if (str_end > str_start)
368 check = true;
369
370 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700371
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800372 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700373 str_start = strstr(str_start, "Altset");
374 if ((str_start == NULL) || (check && (str_start >= str_end))) {
375 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800376 break;
377 }
Kuirong Wange9894162016-08-26 15:16:39 -0700378 ALOGV("%s: remaining string %s\n", __func__, str_start);
379 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800380 usb_device_info = calloc(1, sizeof(struct usb_device_config));
381 if (usb_device_info == NULL) {
382 ALOGE("%s: error unable to allocate memory",
383 __func__);
384 ret = -ENOMEM;
385 break;
386 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800387 /* Bit bit_width parsing */
388 bit_width_start = strstr(str_start, "Format: ");
389 if (bit_width_start == NULL) {
390 ALOGI("%s: Could not find bit_width string", __func__);
391 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700392 continue;
393 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800394 target = strchr(bit_width_start, '\n');
395 if (target == NULL) {
396 ALOGI("%s:end of line not found", __func__);
397 free(usb_device_info);
398 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700399 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800400 size = target - bit_width_start;
401 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
402 ALOGE("%s: unable to allocate memory to hold bit width strings",
403 __func__);
404 ret = -EINVAL;
405 free(usb_device_info);
406 break;
407 }
408 memcpy(bit_width_str, bit_width_start, size);
409 bit_width_str[size] = '\0';
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700410
411 const char * formats[] = { "S32", "S24_3", "S24", "S16" };
412 const int bit_width[] = { 32, 24, 24, 16};
413 for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
414 const char * s = strstr(bit_width_str, formats[i]);
415 if (s) {
416 usb_device_info->bit_width = bit_width[i];
417 usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
418 break;
419 }
420 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800421
422 if (bit_width_str)
423 free(bit_width_str);
424
425 /* channels parsing */
426 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
427 if (channel_start == NULL) {
428 ALOGI("%s: could not find Channels string", __func__);
429 free(usb_device_info);
430 continue;
431 }
432 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
433 usb_device_info->channels = channels_no;
434
435 /* Sample rates parsing */
436 rates_str_start = strstr(str_start, "Rates: ");
437 if (rates_str_start == NULL) {
438 ALOGI("%s: cant find rates string", __func__);
439 free(usb_device_info);
440 continue;
441 }
442 target = strchr(rates_str_start, '\n');
443 if (target == NULL) {
444 ALOGI("%s: end of line not found", __func__);
445 free(usb_device_info);
446 continue;
447 }
448 size = target - rates_str_start;
449 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
450 ALOGE("%s: unable to allocate memory to hold sample rate strings",
451 __func__);
452 ret = -EINVAL;
453 free(usb_device_info);
454 break;
455 }
456 memcpy(rates_str, rates_str_start, size);
457 rates_str[size] = '\0';
458 ret = usb_get_sample_rates(rates_str, usb_device_info);
459 if (rates_str)
460 free(rates_str);
461 if (ret < 0) {
462 ALOGI("%s: error unable to get sample rate values",
463 __func__);
464 free(usb_device_info);
465 continue;
466 }
467 /* Add to list if every field is valid */
468 list_add_tail(&usb_card_info->usb_device_conf_list,
469 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700470 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700471
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700472done:
473 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700474 if (read_buf) free(read_buf);
475 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700476}
477
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800478static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
479 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800481 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700482
483 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800484 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
485 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700486 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800487 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700488 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800489 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700490 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800491exit:
492
493 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700494}
495
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800496static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
497 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700498{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800499 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700500
501 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800502 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
503 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700504 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800505 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700506 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800507 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700508 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700509
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800510exit:
511 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700512}
513
Kuirong Wang1cad7142016-05-24 15:21:56 -0700514static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
515{
516 struct mixer_ctl *ctl;
517 unsigned int index;
518
519 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
520 usb_card_info->usb_sidetone_index[index] = -1;
521
522 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
523 for (index = 0;
524 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
525 index++) {
526 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
527 usb_sidetone_enable_str[index]);
528 if (ctl) {
529 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
530 /* Disable device sidetone by default */
531 mixer_ctl_set_value(ctl, 0, false);
532 break;
533 }
534 }
535 for (index = 0;
536 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
537 index++) {
538 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
539 usb_sidetone_volume_str[index]);
540 if (ctl) {
541 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
542 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
543 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
544 break;
545 }
546 }
547
548 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
549 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
550
551 return;
552}
553
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800554static bool usb_valid_device(int device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700555{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800556 bool is_usb_device = false;
557 if ((device & AUDIO_DEVICE_OUT_USB_DEVICE) ||
558 (device & AUDIO_DEVICE_IN_USB_DEVICE))
559 is_usb_device = true;
560 return is_usb_device;
561}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700562
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800563static void usb_print_active_device(void){
564 struct listnode *node_i, *node_j;
565 struct usb_device_config *dev_info;
566 struct usb_card_config *card_info;
567 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700568
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800569 ALOGI("%s", __func__);
570 list_for_each(node_i, &usbmod->usb_card_conf_list) {
571 card_info = node_to_item(node_i, struct usb_card_config, list);
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700572 ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
573 __func__, card_info->usb_device_type,
574 card_info->usb_card, card_info->endian ? "BE" : "LE");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800575 list_for_each(node_j, &card_info->usb_device_conf_list) {
576 dev_info = node_to_item(node_j, struct usb_device_config, list);
577 ALOGI("%s: bit-width(%d) channel(%d)",
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700578 __func__, dev_info->bit_width, dev_info->channels);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800579 for (i = 0; i < dev_info->rate_size; i++)
580 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
581 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700582 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800583}
584
585static bool usb_get_best_match_for_bit_width(
586 struct listnode *dev_list,
587 unsigned int stream_bit_width,
588 unsigned int *bit_width)
589{
590 struct listnode *node_i;
591 struct usb_device_config *dev_info;
592 unsigned int candidate = 0;
593
594 list_for_each(node_i, dev_list) {
595 dev_info = node_to_item(node_i, struct usb_device_config, list);
596 ALOGI_IF(usb_audio_debug_enable,
597 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
598 __func__, dev_info->bit_width,
599 stream_bit_width, candidate);
600 if (dev_info->bit_width == stream_bit_width) {
601 *bit_width = dev_info->bit_width;
602 ALOGV("%s: Found match bit-width (%d)",
603 __func__, dev_info->bit_width);
604 goto exit;
605 } else if (candidate == 0) {
606 candidate = dev_info->bit_width;
607 }
608 /*
609 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
610 * higher bit width 32 is picked up instead of 16-bit
611 */
612 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
613 ABS_SUB(stream_bit_width, candidate)) {
614 candidate = dev_info->bit_width;
615 }
616 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
617 ABS_SUB(stream_bit_width, candidate)) &&
618 (dev_info->bit_width > candidate)) {
619 candidate = dev_info->bit_width;
620 }
621 }
622 ALOGV("%s: No match found, use the best candidate bw(%d)",
623 __func__, candidate);
624 *bit_width = candidate;
625exit:
626 return true;
627}
628
629static bool usb_get_best_match_for_channels(
630 struct listnode *dev_list,
631 unsigned int bit_width,
632 unsigned int stream_ch,
633 unsigned int *ch)
634{
635 struct listnode *node_i;
636 struct usb_device_config *dev_info;
637 unsigned int candidate = 0;
638
639 list_for_each(node_i, dev_list) {
640 dev_info = node_to_item(node_i, struct usb_device_config, list);
641 ALOGI_IF(usb_audio_debug_enable,
642 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
643 __func__, dev_info->channels, dev_info->bit_width,
644 stream_ch, bit_width, candidate);
645 if (dev_info->bit_width != bit_width)
646 continue;
647 if (dev_info->channels== stream_ch) {
648 *ch = dev_info->channels;
649 ALOGV("%s: Found match channels (%d)",
650 __func__, dev_info->channels);
651 goto exit;
652 } else if (candidate == 0)
653 candidate = dev_info->channels;
654 /*
655 * If stream channel is 4, USB supports both 3 and 5, then
656 * higher channel 5 is picked up instead of 3
657 */
658 else if (ABS_SUB(stream_ch, dev_info->channels) <
659 ABS_SUB(stream_ch, candidate)) {
660 candidate = dev_info->channels;
661 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
662 ABS_SUB(stream_ch, candidate)) &&
663 (dev_info->channels > candidate)) {
664 candidate = dev_info->channels;
665 }
666 }
667 ALOGV("%s: No match found, use the best candidate ch(%d)",
668 __func__, candidate);
669 *ch = candidate;
670exit:
671 return true;
672
673}
674
675static bool usb_sample_rate_multiple(
676 unsigned int stream_sample_rate,
677 unsigned int base)
678{
679 return (((stream_sample_rate / base) * base) == stream_sample_rate);
680}
681
682static bool usb_find_sample_rate_candidate(unsigned int base,
683 unsigned stream_rate,
684 unsigned int usb_rate,
685 unsigned int cur_candidate,
686 unsigned int *update_candidate)
687{
688 /* For sample rate, we should consider fracational sample rate as high priority.
689 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
690 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
691 */
692 if (!usb_sample_rate_multiple(cur_candidate, base) &&
693 usb_sample_rate_multiple(usb_rate, base)) {
694 *update_candidate = usb_rate;
695 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
696 usb_sample_rate_multiple(usb_rate, base)) {
697 if (ABS_SUB(stream_rate, usb_rate) <
698 ABS_SUB(stream_rate, cur_candidate)) {
699 *update_candidate = usb_rate;
700 } else if ((ABS_SUB(stream_rate, usb_rate) ==
701 ABS_SUB(stream_rate, cur_candidate)) &&
702 (usb_rate > cur_candidate)) {
703 *update_candidate = usb_rate;
704 }
705 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
706 !usb_sample_rate_multiple(usb_rate, base)) {
707 if (ABS_SUB(stream_rate, usb_rate) <
708 ABS_SUB(stream_rate, cur_candidate)) {
709 *update_candidate = usb_rate;
710 } else if ((ABS_SUB(stream_rate, usb_rate) ==
711 ABS_SUB(stream_rate, cur_candidate)) &&
712 (usb_rate > cur_candidate)) {
713 *update_candidate = usb_rate;
714 }
715 }
716 return true;
717}
718
719static bool usb_get_best_match_for_sample_rate(
720 struct listnode *dev_list,
721 unsigned int bit_width,
722 unsigned int ch,
723 unsigned int stream_sample_rate,
724 unsigned int *sr)
725{
726 struct listnode *node_i;
727 struct usb_device_config *dev_info;
728 unsigned int candidate = 48000;
729 unsigned int base = SAMPLE_RATE_8000;
730 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
731 unsigned int i;
732
733 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
734 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
735
736 list_for_each(node_i, dev_list) {
737 dev_info = node_to_item(node_i, struct usb_device_config, list);
738 ALOGI_IF(usb_audio_debug_enable,
739 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
740 __func__, dev_info->channels, dev_info->bit_width,
741 ch, bit_width, stream_sample_rate, candidate);
Ashish Jainb26edfb2016-08-25 00:10:11 +0530742 if ((dev_info->bit_width != bit_width) || dev_info->channels != ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800743 continue;
744
745 candidate = 0;
746 for (i = 0; i < dev_info->rate_size; i++) {
747 ALOGI_IF(usb_audio_debug_enable,
748 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
749 __func__, dev_info->channels,
750 dev_info->bit_width, dev_info->rates[i],
751 ch, bit_width, stream_sample_rate, candidate);
752 if (stream_sample_rate == dev_info->rates[i]) {
753 *sr = dev_info->rates[i];
754 ALOGV("%s: Found match sample rate (%d)",
755 __func__, dev_info->rates[i]);
756 goto exit;
757 } else if (candidate == 0) {
758 candidate = dev_info->rates[i];
759 /*
760 * For sample rate, we should consider fracational sample rate as high priority.
761 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
762 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
763 */
764 } else if (multiple_8k) {
765 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
766 stream_sample_rate,
767 dev_info->rates[i],
768 candidate,
769 &candidate);
770 } else {
771 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
772 stream_sample_rate,
773 dev_info->rates[i],
774 candidate,
775 &candidate);
776 }
777 }
778 }
779 ALOGV("%s: No match found, use the best candidate sr(%d)",
780 __func__, candidate);
781 *sr = candidate;
782exit:
783 return true;
784}
785
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800786static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
787 unsigned int *bit_width,
788 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530789 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800790{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800791 bool is_usb_supported = true;
792
793 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530794 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800795 if (list_empty(dev_list)) {
796 *sample_rate = 48000;
797 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530798 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800799 ALOGI("%s: list is empty,fall back to default setting", __func__);
800 goto exit;
801 }
802 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
803 usb_get_best_match_for_channels(dev_list,
804 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530805 *ch,
806 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800807 usb_get_best_match_for_sample_rate(dev_list,
808 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530809 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800810 *sample_rate,
811 sample_rate);
812exit:
813 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530814 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800815 return is_usb_supported;
816}
817
Kuirong Wang1cad7142016-05-24 15:21:56 -0700818static int usb_get_sidetone_gain(struct usb_card_config *card_info)
819{
820 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
821 if (gain > card_info->usb_sidetone_vol_max)
822 gain = card_info->usb_sidetone_vol_max;
823 return gain;
824}
825
826void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
827 char *value, int len)
828{
829 int err;
830
831 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
832 value, len);
833 if (err >= 0) {
834 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
835 ALOGV("%s: sidetone gain(%s) decimal %d",
836 __func__, value, usb_sidetone_gain);
837 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
838 }
839 return;
840}
841
842int audio_extn_usb_enable_sidetone(int device, bool enable)
843{
844 int ret = -ENODEV;
845 struct listnode *node_i;
846 struct usb_card_config *card_info;
847 int i;
848 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
849 __func__, device, enable);
850
851 list_for_each(node_i, &usbmod->usb_card_conf_list) {
852 card_info = node_to_item(node_i, struct usb_card_config, list);
853 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
854 __func__, card_info->usb_device_type, card_info->usb_card);
855 if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
856 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
857 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
858 card_info->usb_snd_mixer,
859 usb_sidetone_enable_str[i]);
860 if (ctl)
861 mixer_ctl_set_value(ctl, 0, enable);
862 else
863 break;
864
865 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
866 ctl = mixer_get_ctl_by_name(
867 card_info->usb_snd_mixer,
868 usb_sidetone_volume_str[i]);
869 if (ctl == NULL)
870 ALOGV("%s: sidetone gain mixer command is not found",
871 __func__);
872 else if (enable)
873 mixer_ctl_set_value(ctl, 0,
874 usb_get_sidetone_gain(card_info));
875 }
876 ret = 0;
877 break;
878 }
879 }
880 }
881 return ret;
882}
883
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800884bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
885 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700886 unsigned int *ch,
887 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800888{
889 struct listnode *node_i;
890 struct usb_card_config *card_info;
891 bool is_usb_supported = false;
892
Kuirong Wang27152a12016-11-11 10:20:30 -0800893 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
894 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800895 list_for_each(node_i, &usbmod->usb_card_conf_list) {
896 card_info = node_to_item(node_i, struct usb_card_config, list);
897 ALOGI_IF(usb_audio_debug_enable,
898 "%s: card_dev_type (0x%x), card_no(%d)",
899 __func__, card_info->usb_device_type, card_info->usb_card);
900 /* Currently only apply the first playback sound card configuration */
Kuirong Wang0b947f72016-09-29 11:03:09 -0700901 if ((is_playback && card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) ||
902 ((!is_playback) && card_info->usb_device_type == AUDIO_DEVICE_IN_USB_DEVICE)){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800903 is_usb_supported = usb_audio_backend_apply_policy(
904 &card_info->usb_device_conf_list,
905 bit_width,
906 sample_rate,
907 ch);
908 break;
909 }
910 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530911 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
912 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800913
914 return is_usb_supported;
915}
916
Ashish Jain3e37a702016-11-25 12:27:15 +0530917bool audio_extn_usb_is_capture_supported()
918{
919 if (usbmod == NULL) {
920 ALOGE("%s: USB device object is NULL", __func__);
921 return false;
922 }
923 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
924 return usbmod->is_capture_supported;
925}
926
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800927void audio_extn_usb_add_device(audio_devices_t device, int card)
928{
929 struct usb_card_config *usb_card_info;
930 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -0800931 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800932
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700933 property_get("vendor.audio.usb.enable.debug", check_debug_enable, NULL);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800934 if (atoi(check_debug_enable)) {
935 usb_audio_debug_enable = true;
936 }
937
938 ALOGI_IF(usb_audio_debug_enable,
939 "%s: parameters device(0x%x), card(%d)",
940 __func__, device, card);
941 if (usbmod == NULL) {
942 ALOGE("%s: USB device object is NULL", __func__);
943 goto exit;
944 }
945
946 if (!(usb_valid_device(device)) || (card < 0)) {
947 ALOGE("%s:device(0x%x), card(%d)",
948 __func__, device, card);
949 goto exit;
950 }
951
Kuirong Wang27152a12016-11-11 10:20:30 -0800952 list_for_each(node_i, &usbmod->usb_card_conf_list) {
953 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
954 ALOGI_IF(usb_audio_debug_enable,
955 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
956 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
957 /* If we have cached the capability */
958 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
959 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
960 __func__, device, card);
961 goto exit;
962 }
963 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800964 usb_card_info = calloc(1, sizeof(struct usb_card_config));
965 if (usb_card_info == NULL) {
966 ALOGE("%s: error unable to allocate memory",
967 __func__);
968 goto exit;
969 }
970 list_init(&usb_card_info->usb_device_conf_list);
971 if (device & AUDIO_DEVICE_OUT_USB_DEVICE) {
972 if (!usb_get_device_pb_config(usb_card_info, card)){
973 usb_card_info->usb_card = card;
974 usb_card_info->usb_device_type = AUDIO_DEVICE_OUT_USB_DEVICE;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700975 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800976 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
977 goto exit;
978 }
979 } else if (device & AUDIO_DEVICE_IN_USB_DEVICE) {
980 if (!usb_get_device_cap_config(usb_card_info, card)) {
981 usb_card_info->usb_card = card;
982 usb_card_info->usb_device_type = AUDIO_DEVICE_IN_USB_DEVICE;
Ashish Jain3e37a702016-11-25 12:27:15 +0530983 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800984 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
985 goto exit;
986 }
987 }
988 /* free memory in error case */
989 if (usb_card_info != NULL)
990 free(usb_card_info);
991exit:
992 if (usb_audio_debug_enable)
993 usb_print_active_device();
994 return;
995}
996
997void audio_extn_usb_remove_device(audio_devices_t device, int card)
998{
999 struct listnode *node_i, *temp_i;
1000 struct listnode *node_j, *temp_j;
1001 struct usb_device_config *dev_info;
1002 struct usb_card_config *card_info;
1003 unsigned int i;
1004
1005 ALOGV("%s: device(0x%x), card(%d)",
1006 __func__, device, card);
1007
1008 if (usbmod == NULL) {
1009 ALOGE("%s: USB device object is NULL", __func__);
1010 goto exit;
1011 }
1012
1013 if (!(usb_valid_device(device)) || (card < 0)) {
1014 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1015 __func__, device, card);
1016 goto exit;
1017 }
1018 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1019 card_info = node_to_item(node_i, struct usb_card_config, list);
1020 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1021 __func__, card_info->usb_device_type, card_info->usb_card);
1022 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1023 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1024 dev_info = node_to_item(node_j, struct usb_device_config, list);
1025 ALOGV("%s: bit-width(%d) channel(%d)",
1026 __func__, dev_info->bit_width, dev_info->channels);
1027 for (i = 0; i < dev_info->rate_size; i++)
1028 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1029
1030 list_remove(node_j);
1031 free(node_to_item(node_j, struct usb_device_config, list));
1032 }
1033 list_remove(node_i);
1034 free(node_to_item(node_i, struct usb_card_config, list));
1035 }
1036 }
Ashish Jain3e37a702016-11-25 12:27:15 +05301037 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001038exit:
1039 if (usb_audio_debug_enable)
1040 usb_print_active_device();
1041
1042 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001043}
1044
1045void audio_extn_usb_init(void *adev)
1046{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001047 if (usbmod == NULL) {
1048 usbmod = calloc(1, sizeof(struct usb_module));
1049 if (usbmod == NULL) {
1050 ALOGE("%s: error unable to allocate memory", __func__);
1051 goto exit;
1052 }
1053 }
1054 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001055 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001056 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301057 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001058exit:
1059 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001060}
1061
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001062void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001063{
1064 if (NULL != usbmod){
1065 free(usbmod);
1066 usbmod = NULL;
1067 }
1068}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001069#endif /*USB_HEADSET_ENABLED end*/