blob: 7416e92602c21bba2f59a6dc483c0bde01e881c0 [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
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;
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -070082 int endian;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080083};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070084
85struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080086 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070087 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -070088 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +053089 bool is_capture_supported;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070090};
91
92static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080093static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -070094static int usb_sidetone_gain = 0;
95
96static const char * const usb_sidetone_enable_str[] = {
97 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -070098 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -070099};
100
101static const char * const usb_sidetone_volume_str[] = {
102 "Sidetone Playback Volume",
103 "Mic Playback Volume",
104};
105
106static void usb_mixer_print_enum(struct mixer_ctl *ctl)
107{
108 unsigned int num_enums;
109 unsigned int i;
110 const char *string;
111
112 num_enums = mixer_ctl_get_num_enums(ctl);
113
114 for (i = 0; i < num_enums; i++) {
115 string = mixer_ctl_get_enum_string(ctl, i);
116 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
117 }
118}
119
120static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
121{
122 struct mixer_ctl *ctl;
123 enum mixer_ctl_type type;
124 unsigned int num_values;
125 unsigned int i;
126 int min, max;
127
128 if (isdigit(control[0]))
129 ctl = mixer_get_ctl(mixer, atoi(control));
130 else
131 ctl = mixer_get_ctl_by_name(mixer, control);
132
133 if (!ctl) {
134 fprintf(stderr, "Invalid mixer control\n");
135 return;
136 }
137
138 type = mixer_ctl_get_type(ctl);
139 num_values = mixer_ctl_get_num_values(ctl);
140
141 ALOGI("%s:", mixer_ctl_get_name(ctl));
142
143 for (i = 0; i < num_values; i++) {
144 switch (type) {
145 case MIXER_CTL_TYPE_INT:
146 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
147 break;
148 case MIXER_CTL_TYPE_BOOL:
149 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
150 break;
151 case MIXER_CTL_TYPE_ENUM:
152 usb_mixer_print_enum(ctl);
153 break;
154 case MIXER_CTL_TYPE_BYTE:
155 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
156 break;
157 default:
158 ALOGI(" unknown");
159 break;
160 }
161 }
162
163 if (type == MIXER_CTL_TYPE_INT) {
164 min = mixer_ctl_get_range_min(ctl);
165 max = mixer_ctl_get_range_max(ctl);
166 ALOGI(" (range %d->%d)", min, max);
167 }
168}
169
170static void usb_soundcard_list_controls(struct mixer *mixer)
171{
172 struct mixer_ctl *ctl;
173 const char *name, *type;
174 unsigned int num_ctls, num_values;
175 unsigned int i;
176
177 num_ctls = mixer_get_num_ctls(mixer);
178
179 ALOGI("Number of controls: %d\n", num_ctls);
180
181 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
182 for (i = 0; i < num_ctls; i++) {
183 ctl = mixer_get_ctl(mixer, i);
184 if (ctl != NULL) {
185 name = mixer_ctl_get_name(ctl);
186 type = mixer_ctl_get_type_string(ctl);
187 num_values = mixer_ctl_get_num_values(ctl);
188 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
189 if (name != NULL)
190 usb_soundcard_detail_control(mixer, name);
191 }
192 }
193}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700194
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800195static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
196 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700197{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800198 struct mixer_ctl *ctl;
199 unsigned int dev_token;
200 unsigned int pcm_device_number = 0;
201
202 /*
203 * usb_dev_token_id is 32 bit number and is defined as below:
204 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
205 */
206 dev_token = (card << 16 ) |
207 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
208
209 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
210 if (!ctl) {
211 ALOGE("%s: Could not get ctl for mixer cmd - %s",
212 __func__, dev_mixer_ctl_name);
213 return -EINVAL;
214 }
215 mixer_ctl_set_value(ctl, 0, dev_token);
216
217 return 0;
218}
219
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700220static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
221{
222 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
223 endian_mixer_ctl_name);
224 if (!ctl) {
225 ALOGE("%s: Could not get ctl for mixer cmd - %s",
226 __func__, endian_mixer_ctl_name);
227 return -EINVAL;
228 }
229
230 switch (endian) {
231 case 0:
232 case 1:
233 mixer_ctl_set_value(ctl, 0, endian);
234 break;
235 default:
236 ALOGW("%s: endianness(%d) not supported",
237 __func__, endian);
238 break;
239 }
240 return 0;
241}
242
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800243static int usb_get_sample_rates(char *rates_str,
244 struct usb_device_config *config)
245{
246 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700247 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800248 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700249
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800250 /* Sample rate string can be in any of the folloing two bit_widthes:
251 * Rates: 8000 - 48000 (continuous)
252 * Rates: 8000, 44100, 48000
253 * Support both the bit_widths
254 */
255 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700256 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
257 if (next_sr_string == NULL) {
258 ALOGE("%s: could not find min rates string", __func__);
259 return -EINVAL;
260 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800261 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700262 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700263 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800264 if (next_sr_string == NULL) {
265 ALOGE("%s: could not find max rates string", __func__);
266 return -EINVAL;
267 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700268 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800269
Kuirong Wang591a98a2016-06-27 12:41:41 -0700270 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800271 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700272 supported_sample_rates[i] <= max_sr) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800273 config->rates[sr_size++] = supported_sample_rates[i];
Kuirong Wang591a98a2016-06-27 12:41:41 -0700274 ALOGI_IF(usb_audio_debug_enable,
275 "%s: continuous sample rate supported_sample_rates[%d] %d",
276 __func__, i, supported_sample_rates[i]);
277 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800278 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700279 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800280 do {
281 sr = (uint32_t)atoi(next_sr_string);
282 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
283 if (supported_sample_rates[i] == sr) {
284 ALOGI_IF(usb_audio_debug_enable,
285 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
286 __func__, sr, i, supported_sample_rates[i]);
287 config->rates[sr_size++] = supported_sample_rates[i];
288 }
289 }
290 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
291 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700292 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800293 config->rate_size = sr_size;
294 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700295}
296
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800297static int usb_get_capability(int type,
298 struct usb_card_config *usb_card_info,
299 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700300{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700301 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800302 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800303 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700304 char *str_start = NULL;
305 char *str_end = NULL;
306 char *channel_start = NULL;
307 char *bit_width_start = NULL;
308 char *rates_str_start = NULL;
309 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700310 char *read_buf = NULL;
311 char *rates_str = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700312 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700313 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800314 char *bit_width_str = NULL;
315 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700316 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700317
Kuirong Wange9894162016-08-26 15:16:39 -0700318 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800319 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
320 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
321
Kuirong Wange9894162016-08-26 15:16:39 -0700322 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800323 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700324 if(ret < 0) {
325 ALOGE("%s: failed on snprintf (%d) to path %s\n",
326 __func__, ret, path);
327 goto done;
328 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700329
330 fd = open(path, O_RDONLY);
331 if (fd <0) {
332 ALOGE("%s: error failed to open config file %s error: %d\n",
333 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700334 ret = -EINVAL;
335 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700336 }
337
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800338 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700339
340 if (!read_buf) {
341 ALOGE("Failed to create read_buf");
342 ret = -ENOMEM;
343 goto done;
344 }
345
Kuirong Wange9894162016-08-26 15:16:39 -0700346 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
347 ALOGE("file read error\n");
348 goto done;
349 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800350 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
351 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700352 if (str_start == NULL) {
353 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800354 __func__, ((type == USB_PLAYBACK) ?
355 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700356 ret = -EINVAL;
357 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700358 }
Kuirong Wange9894162016-08-26 15:16:39 -0700359 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
360 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
361 if (str_end > str_start)
362 check = true;
363
364 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700365
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800366 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700367 str_start = strstr(str_start, "Altset");
368 if ((str_start == NULL) || (check && (str_start >= str_end))) {
369 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800370 break;
371 }
Kuirong Wange9894162016-08-26 15:16:39 -0700372 ALOGV("%s: remaining string %s\n", __func__, str_start);
373 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800374 usb_device_info = calloc(1, sizeof(struct usb_device_config));
375 if (usb_device_info == NULL) {
376 ALOGE("%s: error unable to allocate memory",
377 __func__);
378 ret = -ENOMEM;
379 break;
380 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800381 /* Bit bit_width parsing */
382 bit_width_start = strstr(str_start, "Format: ");
383 if (bit_width_start == NULL) {
384 ALOGI("%s: Could not find bit_width string", __func__);
385 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700386 continue;
387 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800388 target = strchr(bit_width_start, '\n');
389 if (target == NULL) {
390 ALOGI("%s:end of line not found", __func__);
391 free(usb_device_info);
392 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700393 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800394 size = target - bit_width_start;
395 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
396 ALOGE("%s: unable to allocate memory to hold bit width strings",
397 __func__);
398 ret = -EINVAL;
399 free(usb_device_info);
400 break;
401 }
402 memcpy(bit_width_str, bit_width_start, size);
403 bit_width_str[size] = '\0';
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700404
405 const char * formats[] = { "S32", "S24_3", "S24", "S16" };
406 const int bit_width[] = { 32, 24, 24, 16};
407 for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
408 const char * s = strstr(bit_width_str, formats[i]);
409 if (s) {
410 usb_device_info->bit_width = bit_width[i];
411 usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
412 break;
413 }
414 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800415
416 if (bit_width_str)
417 free(bit_width_str);
418
419 /* channels parsing */
420 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
421 if (channel_start == NULL) {
422 ALOGI("%s: could not find Channels string", __func__);
423 free(usb_device_info);
424 continue;
425 }
426 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
427 usb_device_info->channels = channels_no;
428
429 /* Sample rates parsing */
430 rates_str_start = strstr(str_start, "Rates: ");
431 if (rates_str_start == NULL) {
432 ALOGI("%s: cant find rates string", __func__);
433 free(usb_device_info);
434 continue;
435 }
436 target = strchr(rates_str_start, '\n');
437 if (target == NULL) {
438 ALOGI("%s: end of line not found", __func__);
439 free(usb_device_info);
440 continue;
441 }
442 size = target - rates_str_start;
443 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
444 ALOGE("%s: unable to allocate memory to hold sample rate strings",
445 __func__);
446 ret = -EINVAL;
447 free(usb_device_info);
448 break;
449 }
450 memcpy(rates_str, rates_str_start, size);
451 rates_str[size] = '\0';
452 ret = usb_get_sample_rates(rates_str, usb_device_info);
453 if (rates_str)
454 free(rates_str);
455 if (ret < 0) {
456 ALOGI("%s: error unable to get sample rate values",
457 __func__);
458 free(usb_device_info);
459 continue;
460 }
461 /* Add to list if every field is valid */
462 list_add_tail(&usb_card_info->usb_device_conf_list,
463 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700464 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700465
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700466done:
467 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700468 if (read_buf) free(read_buf);
469 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700470}
471
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800472static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
473 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700474{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800475 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700476
477 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800478 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
479 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800481 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700482 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800483 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700484 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800485exit:
486
487 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700488}
489
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800490static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
491 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700492{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800493 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700494
495 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800496 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
497 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700498 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800499 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700500 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800501 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700502 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700503
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800504exit:
505 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700506}
507
Kuirong Wang1cad7142016-05-24 15:21:56 -0700508static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
509{
510 struct mixer_ctl *ctl;
511 unsigned int index;
512
513 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
514 usb_card_info->usb_sidetone_index[index] = -1;
515
516 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
517 for (index = 0;
518 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
519 index++) {
520 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
521 usb_sidetone_enable_str[index]);
522 if (ctl) {
523 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
524 /* Disable device sidetone by default */
525 mixer_ctl_set_value(ctl, 0, false);
526 break;
527 }
528 }
529 for (index = 0;
530 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
531 index++) {
532 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
533 usb_sidetone_volume_str[index]);
534 if (ctl) {
535 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
536 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
537 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
538 break;
539 }
540 }
541
542 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
543 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
544
545 return;
546}
547
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800548static bool usb_valid_device(int device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700549{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800550 bool is_usb_device = false;
551 if ((device & AUDIO_DEVICE_OUT_USB_DEVICE) ||
552 (device & AUDIO_DEVICE_IN_USB_DEVICE))
553 is_usb_device = true;
554 return is_usb_device;
555}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700556
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800557static void usb_print_active_device(void){
558 struct listnode *node_i, *node_j;
559 struct usb_device_config *dev_info;
560 struct usb_card_config *card_info;
561 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700562
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800563 ALOGI("%s", __func__);
564 list_for_each(node_i, &usbmod->usb_card_conf_list) {
565 card_info = node_to_item(node_i, struct usb_card_config, list);
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700566 ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
567 __func__, card_info->usb_device_type,
568 card_info->usb_card, card_info->endian ? "BE" : "LE");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800569 list_for_each(node_j, &card_info->usb_device_conf_list) {
570 dev_info = node_to_item(node_j, struct usb_device_config, list);
571 ALOGI("%s: bit-width(%d) channel(%d)",
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700572 __func__, dev_info->bit_width, dev_info->channels);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800573 for (i = 0; i < dev_info->rate_size; i++)
574 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
575 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700576 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800577}
578
579static bool usb_get_best_match_for_bit_width(
580 struct listnode *dev_list,
581 unsigned int stream_bit_width,
582 unsigned int *bit_width)
583{
584 struct listnode *node_i;
585 struct usb_device_config *dev_info;
586 unsigned int candidate = 0;
587
588 list_for_each(node_i, dev_list) {
589 dev_info = node_to_item(node_i, struct usb_device_config, list);
590 ALOGI_IF(usb_audio_debug_enable,
591 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
592 __func__, dev_info->bit_width,
593 stream_bit_width, candidate);
594 if (dev_info->bit_width == stream_bit_width) {
595 *bit_width = dev_info->bit_width;
596 ALOGV("%s: Found match bit-width (%d)",
597 __func__, dev_info->bit_width);
598 goto exit;
599 } else if (candidate == 0) {
600 candidate = dev_info->bit_width;
601 }
602 /*
603 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
604 * higher bit width 32 is picked up instead of 16-bit
605 */
606 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
607 ABS_SUB(stream_bit_width, candidate)) {
608 candidate = dev_info->bit_width;
609 }
610 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
611 ABS_SUB(stream_bit_width, candidate)) &&
612 (dev_info->bit_width > candidate)) {
613 candidate = dev_info->bit_width;
614 }
615 }
616 ALOGV("%s: No match found, use the best candidate bw(%d)",
617 __func__, candidate);
618 *bit_width = candidate;
619exit:
620 return true;
621}
622
623static bool usb_get_best_match_for_channels(
624 struct listnode *dev_list,
625 unsigned int bit_width,
626 unsigned int stream_ch,
627 unsigned int *ch)
628{
629 struct listnode *node_i;
630 struct usb_device_config *dev_info;
631 unsigned int candidate = 0;
632
633 list_for_each(node_i, dev_list) {
634 dev_info = node_to_item(node_i, struct usb_device_config, list);
635 ALOGI_IF(usb_audio_debug_enable,
636 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
637 __func__, dev_info->channels, dev_info->bit_width,
638 stream_ch, bit_width, candidate);
639 if (dev_info->bit_width != bit_width)
640 continue;
641 if (dev_info->channels== stream_ch) {
642 *ch = dev_info->channels;
643 ALOGV("%s: Found match channels (%d)",
644 __func__, dev_info->channels);
645 goto exit;
646 } else if (candidate == 0)
647 candidate = dev_info->channels;
648 /*
649 * If stream channel is 4, USB supports both 3 and 5, then
650 * higher channel 5 is picked up instead of 3
651 */
652 else if (ABS_SUB(stream_ch, dev_info->channels) <
653 ABS_SUB(stream_ch, candidate)) {
654 candidate = dev_info->channels;
655 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
656 ABS_SUB(stream_ch, candidate)) &&
657 (dev_info->channels > candidate)) {
658 candidate = dev_info->channels;
659 }
660 }
661 ALOGV("%s: No match found, use the best candidate ch(%d)",
662 __func__, candidate);
663 *ch = candidate;
664exit:
665 return true;
666
667}
668
669static bool usb_sample_rate_multiple(
670 unsigned int stream_sample_rate,
671 unsigned int base)
672{
673 return (((stream_sample_rate / base) * base) == stream_sample_rate);
674}
675
676static bool usb_find_sample_rate_candidate(unsigned int base,
677 unsigned stream_rate,
678 unsigned int usb_rate,
679 unsigned int cur_candidate,
680 unsigned int *update_candidate)
681{
682 /* For sample rate, we should consider fracational sample rate as high priority.
683 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
684 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
685 */
686 if (!usb_sample_rate_multiple(cur_candidate, base) &&
687 usb_sample_rate_multiple(usb_rate, base)) {
688 *update_candidate = usb_rate;
689 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
690 usb_sample_rate_multiple(usb_rate, base)) {
691 if (ABS_SUB(stream_rate, usb_rate) <
692 ABS_SUB(stream_rate, cur_candidate)) {
693 *update_candidate = usb_rate;
694 } else if ((ABS_SUB(stream_rate, usb_rate) ==
695 ABS_SUB(stream_rate, cur_candidate)) &&
696 (usb_rate > cur_candidate)) {
697 *update_candidate = usb_rate;
698 }
699 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
700 !usb_sample_rate_multiple(usb_rate, base)) {
701 if (ABS_SUB(stream_rate, usb_rate) <
702 ABS_SUB(stream_rate, cur_candidate)) {
703 *update_candidate = usb_rate;
704 } else if ((ABS_SUB(stream_rate, usb_rate) ==
705 ABS_SUB(stream_rate, cur_candidate)) &&
706 (usb_rate > cur_candidate)) {
707 *update_candidate = usb_rate;
708 }
709 }
710 return true;
711}
712
713static bool usb_get_best_match_for_sample_rate(
714 struct listnode *dev_list,
715 unsigned int bit_width,
716 unsigned int ch,
717 unsigned int stream_sample_rate,
718 unsigned int *sr)
719{
720 struct listnode *node_i;
721 struct usb_device_config *dev_info;
722 unsigned int candidate = 48000;
723 unsigned int base = SAMPLE_RATE_8000;
724 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
725 unsigned int i;
726
727 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
728 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
729
730 list_for_each(node_i, dev_list) {
731 dev_info = node_to_item(node_i, struct usb_device_config, list);
732 ALOGI_IF(usb_audio_debug_enable,
733 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
734 __func__, dev_info->channels, dev_info->bit_width,
735 ch, bit_width, stream_sample_rate, candidate);
Ashish Jainb26edfb2016-08-25 00:10:11 +0530736 if ((dev_info->bit_width != bit_width) || dev_info->channels != ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800737 continue;
738
739 candidate = 0;
740 for (i = 0; i < dev_info->rate_size; i++) {
741 ALOGI_IF(usb_audio_debug_enable,
742 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
743 __func__, dev_info->channels,
744 dev_info->bit_width, dev_info->rates[i],
745 ch, bit_width, stream_sample_rate, candidate);
746 if (stream_sample_rate == dev_info->rates[i]) {
747 *sr = dev_info->rates[i];
748 ALOGV("%s: Found match sample rate (%d)",
749 __func__, dev_info->rates[i]);
750 goto exit;
751 } else if (candidate == 0) {
752 candidate = dev_info->rates[i];
753 /*
754 * For sample rate, we should consider fracational sample rate as high priority.
755 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
756 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
757 */
758 } else if (multiple_8k) {
759 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
760 stream_sample_rate,
761 dev_info->rates[i],
762 candidate,
763 &candidate);
764 } else {
765 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
766 stream_sample_rate,
767 dev_info->rates[i],
768 candidate,
769 &candidate);
770 }
771 }
772 }
773 ALOGV("%s: No match found, use the best candidate sr(%d)",
774 __func__, candidate);
775 *sr = candidate;
776exit:
777 return true;
778}
779
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800780static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
781 unsigned int *bit_width,
782 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530783 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800784{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800785 bool is_usb_supported = true;
786
787 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530788 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800789 if (list_empty(dev_list)) {
790 *sample_rate = 48000;
791 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530792 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800793 ALOGI("%s: list is empty,fall back to default setting", __func__);
794 goto exit;
795 }
796 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
797 usb_get_best_match_for_channels(dev_list,
798 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530799 *ch,
800 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800801 usb_get_best_match_for_sample_rate(dev_list,
802 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530803 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800804 *sample_rate,
805 sample_rate);
806exit:
807 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530808 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800809 return is_usb_supported;
810}
811
Kuirong Wang1cad7142016-05-24 15:21:56 -0700812static int usb_get_sidetone_gain(struct usb_card_config *card_info)
813{
814 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
815 if (gain > card_info->usb_sidetone_vol_max)
816 gain = card_info->usb_sidetone_vol_max;
817 return gain;
818}
819
820void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
821 char *value, int len)
822{
823 int err;
824
825 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
826 value, len);
827 if (err >= 0) {
828 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
829 ALOGV("%s: sidetone gain(%s) decimal %d",
830 __func__, value, usb_sidetone_gain);
831 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
832 }
833 return;
834}
835
836int audio_extn_usb_enable_sidetone(int device, bool enable)
837{
838 int ret = -ENODEV;
839 struct listnode *node_i;
840 struct usb_card_config *card_info;
841 int i;
842 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
843 __func__, device, enable);
844
845 list_for_each(node_i, &usbmod->usb_card_conf_list) {
846 card_info = node_to_item(node_i, struct usb_card_config, list);
847 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
848 __func__, card_info->usb_device_type, card_info->usb_card);
849 if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
850 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
851 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
852 card_info->usb_snd_mixer,
853 usb_sidetone_enable_str[i]);
854 if (ctl)
855 mixer_ctl_set_value(ctl, 0, enable);
856 else
857 break;
858
859 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
860 ctl = mixer_get_ctl_by_name(
861 card_info->usb_snd_mixer,
862 usb_sidetone_volume_str[i]);
863 if (ctl == NULL)
864 ALOGV("%s: sidetone gain mixer command is not found",
865 __func__);
866 else if (enable)
867 mixer_ctl_set_value(ctl, 0,
868 usb_get_sidetone_gain(card_info));
869 }
870 ret = 0;
871 break;
872 }
873 }
874 }
875 return ret;
876}
877
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800878bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
879 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700880 unsigned int *ch,
881 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800882{
883 struct listnode *node_i;
884 struct usb_card_config *card_info;
885 bool is_usb_supported = false;
886
Kuirong Wang27152a12016-11-11 10:20:30 -0800887 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
888 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800889 list_for_each(node_i, &usbmod->usb_card_conf_list) {
890 card_info = node_to_item(node_i, struct usb_card_config, list);
891 ALOGI_IF(usb_audio_debug_enable,
892 "%s: card_dev_type (0x%x), card_no(%d)",
893 __func__, card_info->usb_device_type, card_info->usb_card);
894 /* Currently only apply the first playback sound card configuration */
Kuirong Wang0b947f72016-09-29 11:03:09 -0700895 if ((is_playback && card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) ||
896 ((!is_playback) && card_info->usb_device_type == AUDIO_DEVICE_IN_USB_DEVICE)){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800897 is_usb_supported = usb_audio_backend_apply_policy(
898 &card_info->usb_device_conf_list,
899 bit_width,
900 sample_rate,
901 ch);
902 break;
903 }
904 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530905 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
906 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800907
908 return is_usb_supported;
909}
910
Ashish Jain3e37a702016-11-25 12:27:15 +0530911bool audio_extn_usb_is_capture_supported()
912{
913 if (usbmod == NULL) {
914 ALOGE("%s: USB device object is NULL", __func__);
915 return false;
916 }
917 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
918 return usbmod->is_capture_supported;
919}
920
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800921void audio_extn_usb_add_device(audio_devices_t device, int card)
922{
923 struct usb_card_config *usb_card_info;
924 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -0800925 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800926
927 property_get("audio.usb.enable.debug", check_debug_enable, NULL);
928 if (atoi(check_debug_enable)) {
929 usb_audio_debug_enable = true;
930 }
931
932 ALOGI_IF(usb_audio_debug_enable,
933 "%s: parameters device(0x%x), card(%d)",
934 __func__, device, card);
935 if (usbmod == NULL) {
936 ALOGE("%s: USB device object is NULL", __func__);
937 goto exit;
938 }
939
940 if (!(usb_valid_device(device)) || (card < 0)) {
941 ALOGE("%s:device(0x%x), card(%d)",
942 __func__, device, card);
943 goto exit;
944 }
945
Kuirong Wang27152a12016-11-11 10:20:30 -0800946 list_for_each(node_i, &usbmod->usb_card_conf_list) {
947 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
948 ALOGI_IF(usb_audio_debug_enable,
949 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
950 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
951 /* If we have cached the capability */
952 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
953 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
954 __func__, device, card);
955 goto exit;
956 }
957 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800958 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;
Ashish Jain3e37a702016-11-25 12:27:15 +0530977 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800978 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
979 goto exit;
980 }
981 }
982 /* free memory in error case */
983 if (usb_card_info != NULL)
984 free(usb_card_info);
985exit:
986 if (usb_audio_debug_enable)
987 usb_print_active_device();
988 return;
989}
990
991void audio_extn_usb_remove_device(audio_devices_t device, int card)
992{
993 struct listnode *node_i, *temp_i;
994 struct listnode *node_j, *temp_j;
995 struct usb_device_config *dev_info;
996 struct usb_card_config *card_info;
997 unsigned int i;
998
999 ALOGV("%s: device(0x%x), card(%d)",
1000 __func__, device, card);
1001
1002 if (usbmod == NULL) {
1003 ALOGE("%s: USB device object is NULL", __func__);
1004 goto exit;
1005 }
1006
1007 if (!(usb_valid_device(device)) || (card < 0)) {
1008 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1009 __func__, device, card);
1010 goto exit;
1011 }
1012 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1013 card_info = node_to_item(node_i, struct usb_card_config, list);
1014 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1015 __func__, card_info->usb_device_type, card_info->usb_card);
1016 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1017 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1018 dev_info = node_to_item(node_j, struct usb_device_config, list);
1019 ALOGV("%s: bit-width(%d) channel(%d)",
1020 __func__, dev_info->bit_width, dev_info->channels);
1021 for (i = 0; i < dev_info->rate_size; i++)
1022 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1023
1024 list_remove(node_j);
1025 free(node_to_item(node_j, struct usb_device_config, list));
1026 }
1027 list_remove(node_i);
1028 free(node_to_item(node_i, struct usb_card_config, list));
1029 }
1030 }
Ashish Jain3e37a702016-11-25 12:27:15 +05301031 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001032exit:
1033 if (usb_audio_debug_enable)
1034 usb_print_active_device();
1035
1036 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001037}
1038
1039void audio_extn_usb_init(void *adev)
1040{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001041 if (usbmod == NULL) {
1042 usbmod = calloc(1, sizeof(struct usb_module));
1043 if (usbmod == NULL) {
1044 ALOGE("%s: error unable to allocate memory", __func__);
1045 goto exit;
1046 }
1047 }
1048 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001049 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001050 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301051 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001052exit:
1053 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001054}
1055
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001056void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001057{
1058 if (NULL != usbmod){
1059 free(usbmod);
1060 usbmod = NULL;
1061 }
1062}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001063#endif /*USB_HEADSET_ENABLED end*/