blob: e8b72b0bccdc9de2bafb7a44ec81a40f38e5c81b [file] [log] [blame]
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001/*
Weiyin Jiangcba6f962018-03-18 11:52:05 +08002 * Copyright (c) 2013, 2016-2018 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>
Vinay Vermaaddfa4a2018-04-29 14:03:38 +053038#include <unistd.h>
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070039
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053040#ifdef DYNAMIC_LOG_ENABLED
41#include <log_xml_parser.h>
42#define LOG_MASK HAL_MOD_FILE_USB
43#include <log_utils.h>
44#endif
45
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070046#ifdef USB_HEADSET_ENABLED
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080047#define USB_BUFF_SIZE 2048
48#define CHANNEL_NUMBER_STR "Channels: "
49#define PLAYBACK_PROFILE_STR "Playback:"
50#define CAPTURE_PROFILE_STR "Capture:"
Kuirong Wang1cad7142016-05-24 15:21:56 -070051#define USB_SIDETONE_GAIN_STR "usb_sidetone_gain"
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080052#define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A)))
53#define SAMPLE_RATE_8000 8000
54#define SAMPLE_RATE_11025 11025
Weiyin Jiangcba6f962018-03-18 11:52:05 +080055#define SAMPLE_RATE_192000 192000
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080056// Supported sample rates for USB
57static uint32_t supported_sample_rates[] =
Haynes Mathew George484e8d22017-07-31 18:55:17 -070058 {384000, 352800, 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 22050, 16000, 11025, 8000};
59static uint32_t supported_sample_rates_mask[2];
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080060
61#define MAX_SAMPLE_RATE_SIZE sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
62
Haynes Mathew George484e8d22017-07-31 18:55:17 -070063#define _MAX(x, y) (((x) >= (y)) ? (x) : (y))
64#define _MIN(x, y) (((x) <= (y)) ? (x) : (y))
65
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080066enum usb_usecase_type{
67 USB_PLAYBACK = 0,
68 USB_CAPTURE,
69};
70
Kuirong Wang1cad7142016-05-24 15:21:56 -070071enum {
72 USB_SIDETONE_ENABLE_INDEX = 0,
73 USB_SIDETONE_VOLUME_INDEX,
74 USB_SIDETONE_MAX_INDEX,
75};
76
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080077struct usb_device_config {
78 struct listnode list;
79 unsigned int bit_width;
80 unsigned int channels;
81 unsigned int rate_size;
82 unsigned int rates[MAX_SAMPLE_RATE_SIZE];
83};
84
85struct usb_card_config {
86 struct listnode list;
87 audio_devices_t usb_device_type;
88 int usb_card;
89 struct listnode usb_device_conf_list;
Kuirong Wang1cad7142016-05-24 15:21:56 -070090 struct mixer *usb_snd_mixer;
91 int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
92 int usb_sidetone_vol_min;
93 int usb_sidetone_vol_max;
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -070094 int endian;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080095};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070096
97struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080098 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070099 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700100 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +0530101 bool is_capture_supported;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700102};
103
104static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800105static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700106static int usb_sidetone_gain = 0;
107
108static const char * const usb_sidetone_enable_str[] = {
109 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -0700110 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -0700111};
112
113static const char * const usb_sidetone_volume_str[] = {
114 "Sidetone Playback Volume",
115 "Mic Playback Volume",
116};
117
118static void usb_mixer_print_enum(struct mixer_ctl *ctl)
119{
120 unsigned int num_enums;
121 unsigned int i;
122 const char *string;
123
124 num_enums = mixer_ctl_get_num_enums(ctl);
125
126 for (i = 0; i < num_enums; i++) {
127 string = mixer_ctl_get_enum_string(ctl, i);
128 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
129 }
130}
131
132static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
133{
134 struct mixer_ctl *ctl;
135 enum mixer_ctl_type type;
136 unsigned int num_values;
137 unsigned int i;
138 int min, max;
139
140 if (isdigit(control[0]))
141 ctl = mixer_get_ctl(mixer, atoi(control));
142 else
143 ctl = mixer_get_ctl_by_name(mixer, control);
144
145 if (!ctl) {
146 fprintf(stderr, "Invalid mixer control\n");
147 return;
148 }
149
150 type = mixer_ctl_get_type(ctl);
151 num_values = mixer_ctl_get_num_values(ctl);
152
153 ALOGI("%s:", mixer_ctl_get_name(ctl));
154
155 for (i = 0; i < num_values; i++) {
156 switch (type) {
157 case MIXER_CTL_TYPE_INT:
158 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
159 break;
160 case MIXER_CTL_TYPE_BOOL:
161 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
162 break;
163 case MIXER_CTL_TYPE_ENUM:
164 usb_mixer_print_enum(ctl);
165 break;
166 case MIXER_CTL_TYPE_BYTE:
167 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
168 break;
169 default:
170 ALOGI(" unknown");
171 break;
172 }
173 }
174
175 if (type == MIXER_CTL_TYPE_INT) {
176 min = mixer_ctl_get_range_min(ctl);
177 max = mixer_ctl_get_range_max(ctl);
178 ALOGI(" (range %d->%d)", min, max);
179 }
180}
181
182static void usb_soundcard_list_controls(struct mixer *mixer)
183{
184 struct mixer_ctl *ctl;
185 const char *name, *type;
186 unsigned int num_ctls, num_values;
187 unsigned int i;
188
189 num_ctls = mixer_get_num_ctls(mixer);
190
191 ALOGI("Number of controls: %d\n", num_ctls);
192
193 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
194 for (i = 0; i < num_ctls; i++) {
195 ctl = mixer_get_ctl(mixer, i);
196 if (ctl != NULL) {
197 name = mixer_ctl_get_name(ctl);
198 type = mixer_ctl_get_type_string(ctl);
199 num_values = mixer_ctl_get_num_values(ctl);
200 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
201 if (name != NULL)
202 usb_soundcard_detail_control(mixer, name);
203 }
204 }
205}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700206
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800207static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
208 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700209{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800210 struct mixer_ctl *ctl;
211 unsigned int dev_token;
212 unsigned int pcm_device_number = 0;
213
214 /*
215 * usb_dev_token_id is 32 bit number and is defined as below:
216 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
217 */
218 dev_token = (card << 16 ) |
219 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
220
221 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
222 if (!ctl) {
223 ALOGE("%s: Could not get ctl for mixer cmd - %s",
224 __func__, dev_mixer_ctl_name);
225 return -EINVAL;
226 }
227 mixer_ctl_set_value(ctl, 0, dev_token);
228
229 return 0;
230}
231
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700232static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
233{
234 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
235 endian_mixer_ctl_name);
236 if (!ctl) {
237 ALOGE("%s: Could not get ctl for mixer cmd - %s",
238 __func__, endian_mixer_ctl_name);
239 return -EINVAL;
240 }
241
242 switch (endian) {
243 case 0:
244 case 1:
245 mixer_ctl_set_value(ctl, 0, endian);
246 break;
247 default:
248 ALOGW("%s: endianness(%d) not supported",
249 __func__, endian);
250 break;
251 }
252 return 0;
253}
254
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700255static int usb_get_sample_rates(int type, char *rates_str,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800256 struct usb_device_config *config)
257{
258 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700259 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800260 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700261
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800262 /* Sample rate string can be in any of the folloing two bit_widthes:
263 * Rates: 8000 - 48000 (continuous)
264 * Rates: 8000, 44100, 48000
265 * Support both the bit_widths
266 */
267 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700268 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
269 if (next_sr_string == NULL) {
270 ALOGE("%s: could not find min rates string", __func__);
271 return -EINVAL;
272 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800273 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700274 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700275 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800276 if (next_sr_string == NULL) {
277 ALOGE("%s: could not find max rates string", __func__);
278 return -EINVAL;
279 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700280 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800281
Kuirong Wang591a98a2016-06-27 12:41:41 -0700282 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800283 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700284 supported_sample_rates[i] <= max_sr) {
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800285 // FIXME: we don't support >192KHz in recording path for now
286 if ((supported_sample_rates[i] > SAMPLE_RATE_192000) &&
287 (type == USB_CAPTURE))
288 continue;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800289 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700290 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700291 ALOGI_IF(usb_audio_debug_enable,
292 "%s: continuous sample rate supported_sample_rates[%d] %d",
293 __func__, i, supported_sample_rates[i]);
294 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800295 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700296 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800297 do {
298 sr = (uint32_t)atoi(next_sr_string);
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800299 // FIXME: we don't support >192KHz in recording path for now
300 if ((sr > SAMPLE_RATE_192000) && (type == USB_CAPTURE)) {
301 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
302 continue;
303 }
304
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800305 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
306 if (supported_sample_rates[i] == sr) {
307 ALOGI_IF(usb_audio_debug_enable,
308 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
309 __func__, sr, i, supported_sample_rates[i]);
310 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700311 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800312 }
313 }
314 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
315 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700316 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800317 config->rate_size = sr_size;
318 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700319}
320
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800321static int usb_get_capability(int type,
322 struct usb_card_config *usb_card_info,
323 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700324{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700325 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800326 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800327 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700328 char *str_start = NULL;
329 char *str_end = NULL;
330 char *channel_start = NULL;
331 char *bit_width_start = NULL;
332 char *rates_str_start = NULL;
333 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700334 char *read_buf = NULL;
335 char *rates_str = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700336 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700337 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800338 char *bit_width_str = NULL;
339 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700340 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700341
Kuirong Wange9894162016-08-26 15:16:39 -0700342 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800343 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
344 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
345
Kuirong Wange9894162016-08-26 15:16:39 -0700346 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800347 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700348 if(ret < 0) {
349 ALOGE("%s: failed on snprintf (%d) to path %s\n",
350 __func__, ret, path);
351 goto done;
352 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700353
354 fd = open(path, O_RDONLY);
355 if (fd <0) {
356 ALOGE("%s: error failed to open config file %s error: %d\n",
357 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700358 ret = -EINVAL;
359 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700360 }
361
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800362 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700363
364 if (!read_buf) {
365 ALOGE("Failed to create read_buf");
366 ret = -ENOMEM;
367 goto done;
368 }
369
Kuirong Wange9894162016-08-26 15:16:39 -0700370 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
371 ALOGE("file read error\n");
372 goto done;
373 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800374 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
375 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700376 if (str_start == NULL) {
377 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800378 __func__, ((type == USB_PLAYBACK) ?
379 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700380 ret = -EINVAL;
381 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700382 }
Kuirong Wange9894162016-08-26 15:16:39 -0700383 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
384 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
385 if (str_end > str_start)
386 check = true;
387
388 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700389
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800390 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700391 str_start = strstr(str_start, "Altset");
392 if ((str_start == NULL) || (check && (str_start >= str_end))) {
393 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800394 break;
395 }
Kuirong Wange9894162016-08-26 15:16:39 -0700396 ALOGV("%s: remaining string %s\n", __func__, str_start);
397 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800398 usb_device_info = calloc(1, sizeof(struct usb_device_config));
399 if (usb_device_info == NULL) {
400 ALOGE("%s: error unable to allocate memory",
401 __func__);
402 ret = -ENOMEM;
403 break;
404 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800405 /* Bit bit_width parsing */
406 bit_width_start = strstr(str_start, "Format: ");
407 if (bit_width_start == NULL) {
408 ALOGI("%s: Could not find bit_width string", __func__);
409 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700410 continue;
411 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800412 target = strchr(bit_width_start, '\n');
413 if (target == NULL) {
414 ALOGI("%s:end of line not found", __func__);
415 free(usb_device_info);
416 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700417 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800418 size = target - bit_width_start;
419 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
420 ALOGE("%s: unable to allocate memory to hold bit width strings",
421 __func__);
422 ret = -EINVAL;
423 free(usb_device_info);
424 break;
425 }
426 memcpy(bit_width_str, bit_width_start, size);
427 bit_width_str[size] = '\0';
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700428
429 const char * formats[] = { "S32", "S24_3", "S24", "S16" };
430 const int bit_width[] = { 32, 24, 24, 16};
431 for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
432 const char * s = strstr(bit_width_str, formats[i]);
433 if (s) {
434 usb_device_info->bit_width = bit_width[i];
435 usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
436 break;
437 }
438 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800439
440 if (bit_width_str)
441 free(bit_width_str);
442
443 /* channels parsing */
444 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
445 if (channel_start == NULL) {
446 ALOGI("%s: could not find Channels string", __func__);
447 free(usb_device_info);
448 continue;
449 }
450 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
451 usb_device_info->channels = channels_no;
452
453 /* Sample rates parsing */
454 rates_str_start = strstr(str_start, "Rates: ");
455 if (rates_str_start == NULL) {
456 ALOGI("%s: cant find rates string", __func__);
457 free(usb_device_info);
458 continue;
459 }
460 target = strchr(rates_str_start, '\n');
461 if (target == NULL) {
462 ALOGI("%s: end of line not found", __func__);
463 free(usb_device_info);
464 continue;
465 }
466 size = target - rates_str_start;
467 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
468 ALOGE("%s: unable to allocate memory to hold sample rate strings",
469 __func__);
470 ret = -EINVAL;
471 free(usb_device_info);
472 break;
473 }
474 memcpy(rates_str, rates_str_start, size);
475 rates_str[size] = '\0';
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700476 ret = usb_get_sample_rates(type, rates_str, usb_device_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800477 if (rates_str)
478 free(rates_str);
479 if (ret < 0) {
480 ALOGI("%s: error unable to get sample rate values",
481 __func__);
482 free(usb_device_info);
483 continue;
484 }
485 /* Add to list if every field is valid */
486 list_add_tail(&usb_card_info->usb_device_conf_list,
487 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700488 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700489
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700490done:
491 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700492 if (read_buf) free(read_buf);
493 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700494}
495
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800496static int usb_get_device_pb_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_PLAYBACK, 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_PLAYBACK, card, "USB_AUDIO_RX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700508 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800509exit:
510
511 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700512}
513
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800514static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
515 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700516{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800517 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700518
519 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800520 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
521 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700522 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800523 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700524 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800525 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700526 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700527
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800528exit:
529 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700530}
531
Kuirong Wang1cad7142016-05-24 15:21:56 -0700532static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
533{
534 struct mixer_ctl *ctl;
535 unsigned int index;
536
537 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
538 usb_card_info->usb_sidetone_index[index] = -1;
539
540 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
541 for (index = 0;
542 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
543 index++) {
544 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
545 usb_sidetone_enable_str[index]);
546 if (ctl) {
547 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
548 /* Disable device sidetone by default */
549 mixer_ctl_set_value(ctl, 0, false);
550 break;
551 }
552 }
553 for (index = 0;
554 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
555 index++) {
556 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
557 usb_sidetone_volume_str[index]);
558 if (ctl) {
559 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
560 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
561 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
562 break;
563 }
564 }
565
566 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
567 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
568
569 return;
570}
571
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700572static inline bool usb_output_device(audio_devices_t device) {
573 // ignore accessory for now
574 if (device == AUDIO_DEVICE_OUT_USB_ACCESSORY)
575 return false;
576 return audio_is_usb_out_device(device);
577}
578
579static inline bool usb_input_device(audio_devices_t device) {
580 // ignore accessory for now
581 if (device == AUDIO_DEVICE_IN_USB_ACCESSORY)
582 return false;
583 return audio_is_usb_in_device(device);
584}
585
586static bool usb_valid_device(audio_devices_t device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700587{
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700588 return usb_output_device(device) ||
589 usb_input_device(device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800590}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700591
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800592static void usb_print_active_device(void){
593 struct listnode *node_i, *node_j;
594 struct usb_device_config *dev_info;
595 struct usb_card_config *card_info;
596 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700597
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800598 ALOGI("%s", __func__);
599 list_for_each(node_i, &usbmod->usb_card_conf_list) {
600 card_info = node_to_item(node_i, struct usb_card_config, list);
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700601 ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
602 __func__, card_info->usb_device_type,
603 card_info->usb_card, card_info->endian ? "BE" : "LE");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800604 list_for_each(node_j, &card_info->usb_device_conf_list) {
605 dev_info = node_to_item(node_j, struct usb_device_config, list);
606 ALOGI("%s: bit-width(%d) channel(%d)",
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700607 __func__, dev_info->bit_width, dev_info->channels);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800608 for (i = 0; i < dev_info->rate_size; i++)
609 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
610 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700611 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800612}
613
614static bool usb_get_best_match_for_bit_width(
615 struct listnode *dev_list,
616 unsigned int stream_bit_width,
617 unsigned int *bit_width)
618{
619 struct listnode *node_i;
620 struct usb_device_config *dev_info;
621 unsigned int candidate = 0;
622
623 list_for_each(node_i, dev_list) {
624 dev_info = node_to_item(node_i, struct usb_device_config, list);
625 ALOGI_IF(usb_audio_debug_enable,
626 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
627 __func__, dev_info->bit_width,
628 stream_bit_width, candidate);
629 if (dev_info->bit_width == stream_bit_width) {
630 *bit_width = dev_info->bit_width;
631 ALOGV("%s: Found match bit-width (%d)",
632 __func__, dev_info->bit_width);
633 goto exit;
634 } else if (candidate == 0) {
635 candidate = dev_info->bit_width;
636 }
637 /*
638 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
639 * higher bit width 32 is picked up instead of 16-bit
640 */
641 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
642 ABS_SUB(stream_bit_width, candidate)) {
643 candidate = dev_info->bit_width;
644 }
645 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
646 ABS_SUB(stream_bit_width, candidate)) &&
647 (dev_info->bit_width > candidate)) {
648 candidate = dev_info->bit_width;
649 }
650 }
651 ALOGV("%s: No match found, use the best candidate bw(%d)",
652 __func__, candidate);
653 *bit_width = candidate;
654exit:
655 return true;
656}
657
658static bool usb_get_best_match_for_channels(
659 struct listnode *dev_list,
660 unsigned int bit_width,
661 unsigned int stream_ch,
662 unsigned int *ch)
663{
664 struct listnode *node_i;
665 struct usb_device_config *dev_info;
666 unsigned int candidate = 0;
667
668 list_for_each(node_i, dev_list) {
669 dev_info = node_to_item(node_i, struct usb_device_config, list);
670 ALOGI_IF(usb_audio_debug_enable,
671 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
672 __func__, dev_info->channels, dev_info->bit_width,
673 stream_ch, bit_width, candidate);
674 if (dev_info->bit_width != bit_width)
675 continue;
676 if (dev_info->channels== stream_ch) {
677 *ch = dev_info->channels;
678 ALOGV("%s: Found match channels (%d)",
679 __func__, dev_info->channels);
680 goto exit;
681 } else if (candidate == 0)
682 candidate = dev_info->channels;
683 /*
684 * If stream channel is 4, USB supports both 3 and 5, then
685 * higher channel 5 is picked up instead of 3
686 */
687 else if (ABS_SUB(stream_ch, dev_info->channels) <
688 ABS_SUB(stream_ch, candidate)) {
689 candidate = dev_info->channels;
690 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
691 ABS_SUB(stream_ch, candidate)) &&
692 (dev_info->channels > candidate)) {
693 candidate = dev_info->channels;
694 }
695 }
696 ALOGV("%s: No match found, use the best candidate ch(%d)",
697 __func__, candidate);
698 *ch = candidate;
699exit:
700 return true;
701
702}
703
704static bool usb_sample_rate_multiple(
705 unsigned int stream_sample_rate,
706 unsigned int base)
707{
708 return (((stream_sample_rate / base) * base) == stream_sample_rate);
709}
710
711static bool usb_find_sample_rate_candidate(unsigned int base,
712 unsigned stream_rate,
713 unsigned int usb_rate,
714 unsigned int cur_candidate,
715 unsigned int *update_candidate)
716{
717 /* For sample rate, we should consider fracational sample rate as high priority.
718 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
719 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
720 */
721 if (!usb_sample_rate_multiple(cur_candidate, base) &&
722 usb_sample_rate_multiple(usb_rate, base)) {
723 *update_candidate = usb_rate;
724 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
725 usb_sample_rate_multiple(usb_rate, base)) {
726 if (ABS_SUB(stream_rate, usb_rate) <
727 ABS_SUB(stream_rate, cur_candidate)) {
728 *update_candidate = usb_rate;
729 } else if ((ABS_SUB(stream_rate, usb_rate) ==
730 ABS_SUB(stream_rate, cur_candidate)) &&
731 (usb_rate > cur_candidate)) {
732 *update_candidate = usb_rate;
733 }
734 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
735 !usb_sample_rate_multiple(usb_rate, base)) {
736 if (ABS_SUB(stream_rate, usb_rate) <
737 ABS_SUB(stream_rate, cur_candidate)) {
738 *update_candidate = usb_rate;
739 } else if ((ABS_SUB(stream_rate, usb_rate) ==
740 ABS_SUB(stream_rate, cur_candidate)) &&
741 (usb_rate > cur_candidate)) {
742 *update_candidate = usb_rate;
743 }
744 }
745 return true;
746}
747
748static bool usb_get_best_match_for_sample_rate(
749 struct listnode *dev_list,
750 unsigned int bit_width,
751 unsigned int ch,
752 unsigned int stream_sample_rate,
753 unsigned int *sr)
754{
755 struct listnode *node_i;
756 struct usb_device_config *dev_info;
757 unsigned int candidate = 48000;
758 unsigned int base = SAMPLE_RATE_8000;
759 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
760 unsigned int i;
761
762 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
763 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
764
765 list_for_each(node_i, dev_list) {
766 dev_info = node_to_item(node_i, struct usb_device_config, list);
767 ALOGI_IF(usb_audio_debug_enable,
768 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
769 __func__, dev_info->channels, dev_info->bit_width,
770 ch, bit_width, stream_sample_rate, candidate);
Ashish Jainb26edfb2016-08-25 00:10:11 +0530771 if ((dev_info->bit_width != bit_width) || dev_info->channels != ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800772 continue;
773
774 candidate = 0;
775 for (i = 0; i < dev_info->rate_size; i++) {
776 ALOGI_IF(usb_audio_debug_enable,
777 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
778 __func__, dev_info->channels,
779 dev_info->bit_width, dev_info->rates[i],
780 ch, bit_width, stream_sample_rate, candidate);
781 if (stream_sample_rate == dev_info->rates[i]) {
782 *sr = dev_info->rates[i];
783 ALOGV("%s: Found match sample rate (%d)",
784 __func__, dev_info->rates[i]);
785 goto exit;
786 } else if (candidate == 0) {
787 candidate = dev_info->rates[i];
788 /*
789 * For sample rate, we should consider fracational sample rate as high priority.
790 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
791 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
792 */
793 } else if (multiple_8k) {
794 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
795 stream_sample_rate,
796 dev_info->rates[i],
797 candidate,
798 &candidate);
799 } else {
800 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
801 stream_sample_rate,
802 dev_info->rates[i],
803 candidate,
804 &candidate);
805 }
806 }
807 }
808 ALOGV("%s: No match found, use the best candidate sr(%d)",
809 __func__, candidate);
810 *sr = candidate;
811exit:
812 return true;
813}
814
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800815static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
816 unsigned int *bit_width,
817 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530818 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800819{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800820 bool is_usb_supported = true;
821
822 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530823 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800824 if (list_empty(dev_list)) {
825 *sample_rate = 48000;
826 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530827 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800828 ALOGI("%s: list is empty,fall back to default setting", __func__);
829 goto exit;
830 }
831 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
832 usb_get_best_match_for_channels(dev_list,
833 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530834 *ch,
835 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800836 usb_get_best_match_for_sample_rate(dev_list,
837 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530838 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800839 *sample_rate,
840 sample_rate);
841exit:
842 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530843 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800844 return is_usb_supported;
845}
846
Kuirong Wang1cad7142016-05-24 15:21:56 -0700847static int usb_get_sidetone_gain(struct usb_card_config *card_info)
848{
849 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
850 if (gain > card_info->usb_sidetone_vol_max)
851 gain = card_info->usb_sidetone_vol_max;
852 return gain;
853}
854
855void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
856 char *value, int len)
857{
858 int err;
859
860 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
861 value, len);
862 if (err >= 0) {
863 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
864 ALOGV("%s: sidetone gain(%s) decimal %d",
865 __func__, value, usb_sidetone_gain);
866 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
867 }
868 return;
869}
870
871int audio_extn_usb_enable_sidetone(int device, bool enable)
872{
873 int ret = -ENODEV;
874 struct listnode *node_i;
875 struct usb_card_config *card_info;
876 int i;
877 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
878 __func__, device, enable);
879
880 list_for_each(node_i, &usbmod->usb_card_conf_list) {
881 card_info = node_to_item(node_i, struct usb_card_config, list);
882 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
883 __func__, card_info->usb_device_type, card_info->usb_card);
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700884 if (usb_output_device(card_info->usb_device_type)) {
Kuirong Wang1cad7142016-05-24 15:21:56 -0700885 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
886 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
887 card_info->usb_snd_mixer,
888 usb_sidetone_enable_str[i]);
889 if (ctl)
890 mixer_ctl_set_value(ctl, 0, enable);
891 else
892 break;
893
894 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
895 ctl = mixer_get_ctl_by_name(
896 card_info->usb_snd_mixer,
897 usb_sidetone_volume_str[i]);
898 if (ctl == NULL)
899 ALOGV("%s: sidetone gain mixer command is not found",
900 __func__);
901 else if (enable)
902 mixer_ctl_set_value(ctl, 0,
903 usb_get_sidetone_gain(card_info));
904 }
905 ret = 0;
906 break;
907 }
908 }
909 }
910 return ret;
911}
912
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800913bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
914 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700915 unsigned int *ch,
916 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800917{
918 struct listnode *node_i;
919 struct usb_card_config *card_info;
920 bool is_usb_supported = false;
921
Kuirong Wang27152a12016-11-11 10:20:30 -0800922 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
923 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800924 list_for_each(node_i, &usbmod->usb_card_conf_list) {
925 card_info = node_to_item(node_i, struct usb_card_config, list);
926 ALOGI_IF(usb_audio_debug_enable,
927 "%s: card_dev_type (0x%x), card_no(%d)",
928 __func__, card_info->usb_device_type, card_info->usb_card);
929 /* Currently only apply the first playback sound card configuration */
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700930 if ((is_playback && usb_output_device(card_info->usb_device_type)) ||
931 (!is_playback && usb_input_device(card_info->usb_device_type))){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800932 is_usb_supported = usb_audio_backend_apply_policy(
933 &card_info->usb_device_conf_list,
934 bit_width,
935 sample_rate,
936 ch);
937 break;
938 }
939 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530940 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
941 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800942
943 return is_usb_supported;
944}
945
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700946int audio_extn_usb_get_max_channels(bool is_playback)
947{
948 struct listnode *node_i, *node_j;
949 struct usb_device_config *dev_info;
950 struct usb_card_config *card_info;
951 unsigned int max_ch = 1;
952 list_for_each(node_i, &usbmod->usb_card_conf_list) {
953 card_info = node_to_item(node_i, struct usb_card_config, list);
954 if (usb_output_device(card_info->usb_device_type) && !is_playback)
955 continue;
956 else if (usb_input_device(card_info->usb_device_type) && is_playback)
957 continue;
958
959 list_for_each(node_j, &card_info->usb_device_conf_list) {
960 dev_info = node_to_item(node_j, struct usb_device_config, list);
961 max_ch = _MAX(max_ch, dev_info->channels);
962 }
963 }
964
965 return max_ch;
966}
967
968int audio_extn_usb_get_max_bit_width(bool is_playback)
969{
970 struct listnode *node_i, *node_j;
971 struct usb_device_config *dev_info;
972 struct usb_card_config *card_info;
973 unsigned int max_bw = 16;
974 list_for_each(node_i, &usbmod->usb_card_conf_list) {
975 card_info = node_to_item(node_i, struct usb_card_config, list);
976 if (usb_output_device(card_info->usb_device_type) && !is_playback)
977 continue;
978 else if (usb_input_device(card_info->usb_device_type) && is_playback)
979 continue;
980
981 list_for_each(node_j, &card_info->usb_device_conf_list) {
982 dev_info = node_to_item(node_j, struct usb_device_config, list);
983 max_bw = _MAX(max_bw, dev_info->bit_width);
984 }
985 }
986
987 return max_bw;
988}
989
990int audio_extn_usb_get_sup_sample_rates(bool is_playback,
991 uint32_t *sample_rates,
992 uint32_t sample_rate_size)
993{
994 int type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
995
996 ALOGV("%s supported_sample_rates_mask 0x%x", __func__, supported_sample_rates_mask[type]);
997 uint32_t bm = supported_sample_rates_mask[type];
998 uint32_t tries = _MIN(sample_rate_size, (uint32_t)__builtin_popcount(bm));
999
1000 int i = 0;
1001 while (tries--) {
1002 int idx = __builtin_ffs(bm) - 1;
1003 sample_rates[i++] = supported_sample_rates[idx];
1004 bm &= ~(1<<idx);
1005 }
1006
1007 return i;
1008}
1009
Ashish Jain3e37a702016-11-25 12:27:15 +05301010bool audio_extn_usb_is_capture_supported()
1011{
1012 if (usbmod == NULL) {
1013 ALOGE("%s: USB device object is NULL", __func__);
1014 return false;
1015 }
1016 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
1017 return usbmod->is_capture_supported;
1018}
1019
Zhou Song6f862822017-11-06 17:27:57 +08001020bool audio_extn_usb_is_tunnel_supported()
1021{
1022 return true;
1023}
1024
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001025void audio_extn_usb_add_device(audio_devices_t device, int card)
1026{
1027 struct usb_card_config *usb_card_info;
1028 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -08001029 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001030
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07001031 property_get("vendor.audio.usb.enable.debug", check_debug_enable, NULL);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001032 if (atoi(check_debug_enable)) {
1033 usb_audio_debug_enable = true;
1034 }
1035
1036 ALOGI_IF(usb_audio_debug_enable,
1037 "%s: parameters device(0x%x), card(%d)",
1038 __func__, device, card);
1039 if (usbmod == NULL) {
1040 ALOGE("%s: USB device object is NULL", __func__);
1041 goto exit;
1042 }
1043
1044 if (!(usb_valid_device(device)) || (card < 0)) {
1045 ALOGE("%s:device(0x%x), card(%d)",
1046 __func__, device, card);
1047 goto exit;
1048 }
1049
Kuirong Wang27152a12016-11-11 10:20:30 -08001050 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1051 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
1052 ALOGI_IF(usb_audio_debug_enable,
1053 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
1054 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
1055 /* If we have cached the capability */
1056 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
1057 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
1058 __func__, device, card);
1059 goto exit;
1060 }
1061 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001062 usb_card_info = calloc(1, sizeof(struct usb_card_config));
1063 if (usb_card_info == NULL) {
1064 ALOGE("%s: error unable to allocate memory",
1065 __func__);
1066 goto exit;
1067 }
1068 list_init(&usb_card_info->usb_device_conf_list);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001069 if (usb_output_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001070 if (!usb_get_device_pb_config(usb_card_info, card)){
1071 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001072 usb_card_info->usb_device_type = device;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001073 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001074 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1075 goto exit;
1076 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001077 } else if (usb_input_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001078 if (!usb_get_device_cap_config(usb_card_info, card)) {
1079 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001080 usb_card_info->usb_device_type = device;
Ashish Jain3e37a702016-11-25 12:27:15 +05301081 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001082 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1083 goto exit;
1084 }
1085 }
1086 /* free memory in error case */
1087 if (usb_card_info != NULL)
1088 free(usb_card_info);
1089exit:
1090 if (usb_audio_debug_enable)
1091 usb_print_active_device();
1092 return;
1093}
1094
1095void audio_extn_usb_remove_device(audio_devices_t device, int card)
1096{
1097 struct listnode *node_i, *temp_i;
1098 struct listnode *node_j, *temp_j;
1099 struct usb_device_config *dev_info;
1100 struct usb_card_config *card_info;
1101 unsigned int i;
1102
1103 ALOGV("%s: device(0x%x), card(%d)",
1104 __func__, device, card);
1105
1106 if (usbmod == NULL) {
1107 ALOGE("%s: USB device object is NULL", __func__);
1108 goto exit;
1109 }
1110
1111 if (!(usb_valid_device(device)) || (card < 0)) {
1112 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1113 __func__, device, card);
1114 goto exit;
1115 }
1116 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1117 card_info = node_to_item(node_i, struct usb_card_config, list);
1118 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1119 __func__, card_info->usb_device_type, card_info->usb_card);
1120 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1121 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1122 dev_info = node_to_item(node_j, struct usb_device_config, list);
1123 ALOGV("%s: bit-width(%d) channel(%d)",
1124 __func__, dev_info->bit_width, dev_info->channels);
1125 for (i = 0; i < dev_info->rate_size; i++)
1126 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1127
1128 list_remove(node_j);
1129 free(node_to_item(node_j, struct usb_device_config, list));
1130 }
1131 list_remove(node_i);
1132 free(node_to_item(node_i, struct usb_card_config, list));
1133 }
1134 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001135 if (audio_is_usb_in_device(device)) { // XXX not sure if we need to check for card
1136 usbmod->is_capture_supported = false;
1137 supported_sample_rates_mask[USB_CAPTURE] = 0;
1138 } else
1139 supported_sample_rates_mask[USB_PLAYBACK] = 0;
1140
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001141exit:
1142 if (usb_audio_debug_enable)
1143 usb_print_active_device();
1144
1145 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001146}
1147
Kevin Rocardfce19002017-08-07 19:21:36 -07001148bool audio_extn_usb_alive(int card) {
1149 char path[PATH_MAX] = {0};
1150 // snprintf should never fail
1151 (void) snprintf(path, sizeof(path), "/proc/asound/card%u/stream0", card);
1152 return access(path, F_OK) == 0;
1153}
1154
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001155void audio_extn_usb_init(void *adev)
1156{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001157 if (usbmod == NULL) {
1158 usbmod = calloc(1, sizeof(struct usb_module));
1159 if (usbmod == NULL) {
1160 ALOGE("%s: error unable to allocate memory", __func__);
1161 goto exit;
1162 }
1163 }
1164 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001165 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001166 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301167 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001168exit:
1169 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001170}
1171
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001172void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001173{
1174 if (NULL != usbmod){
1175 free(usbmod);
1176 usbmod = NULL;
1177 }
1178}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001179#endif /*USB_HEADSET_ENABLED end*/