blob: af8cc898b764e33ffa8703477e3f1b5af1183e96 [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[] =
Haynes Mathew George484e8d22017-07-31 18:55:17 -070056 {384000, 352800, 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 22050, 16000, 11025, 8000};
57static uint32_t supported_sample_rates_mask[2];
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080058
59#define MAX_SAMPLE_RATE_SIZE sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
60
Haynes Mathew George484e8d22017-07-31 18:55:17 -070061#define _MAX(x, y) (((x) >= (y)) ? (x) : (y))
62#define _MIN(x, y) (((x) <= (y)) ? (x) : (y))
63
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080064enum usb_usecase_type{
65 USB_PLAYBACK = 0,
66 USB_CAPTURE,
67};
68
Kuirong Wang1cad7142016-05-24 15:21:56 -070069enum {
70 USB_SIDETONE_ENABLE_INDEX = 0,
71 USB_SIDETONE_VOLUME_INDEX,
72 USB_SIDETONE_MAX_INDEX,
73};
74
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080075struct usb_device_config {
76 struct listnode list;
77 unsigned int bit_width;
78 unsigned int channels;
79 unsigned int rate_size;
80 unsigned int rates[MAX_SAMPLE_RATE_SIZE];
81};
82
83struct usb_card_config {
84 struct listnode list;
85 audio_devices_t usb_device_type;
86 int usb_card;
87 struct listnode usb_device_conf_list;
Kuirong Wang1cad7142016-05-24 15:21:56 -070088 struct mixer *usb_snd_mixer;
89 int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
90 int usb_sidetone_vol_min;
91 int usb_sidetone_vol_max;
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -070092 int endian;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080093};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070094
95struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080096 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070097 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -070098 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +053099 bool is_capture_supported;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700100};
101
102static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800103static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700104static int usb_sidetone_gain = 0;
105
106static const char * const usb_sidetone_enable_str[] = {
107 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -0700108 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -0700109};
110
111static const char * const usb_sidetone_volume_str[] = {
112 "Sidetone Playback Volume",
113 "Mic Playback Volume",
114};
115
116static void usb_mixer_print_enum(struct mixer_ctl *ctl)
117{
118 unsigned int num_enums;
119 unsigned int i;
120 const char *string;
121
122 num_enums = mixer_ctl_get_num_enums(ctl);
123
124 for (i = 0; i < num_enums; i++) {
125 string = mixer_ctl_get_enum_string(ctl, i);
126 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
127 }
128}
129
130static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
131{
132 struct mixer_ctl *ctl;
133 enum mixer_ctl_type type;
134 unsigned int num_values;
135 unsigned int i;
136 int min, max;
137
138 if (isdigit(control[0]))
139 ctl = mixer_get_ctl(mixer, atoi(control));
140 else
141 ctl = mixer_get_ctl_by_name(mixer, control);
142
143 if (!ctl) {
144 fprintf(stderr, "Invalid mixer control\n");
145 return;
146 }
147
148 type = mixer_ctl_get_type(ctl);
149 num_values = mixer_ctl_get_num_values(ctl);
150
151 ALOGI("%s:", mixer_ctl_get_name(ctl));
152
153 for (i = 0; i < num_values; i++) {
154 switch (type) {
155 case MIXER_CTL_TYPE_INT:
156 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
157 break;
158 case MIXER_CTL_TYPE_BOOL:
159 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
160 break;
161 case MIXER_CTL_TYPE_ENUM:
162 usb_mixer_print_enum(ctl);
163 break;
164 case MIXER_CTL_TYPE_BYTE:
165 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
166 break;
167 default:
168 ALOGI(" unknown");
169 break;
170 }
171 }
172
173 if (type == MIXER_CTL_TYPE_INT) {
174 min = mixer_ctl_get_range_min(ctl);
175 max = mixer_ctl_get_range_max(ctl);
176 ALOGI(" (range %d->%d)", min, max);
177 }
178}
179
180static void usb_soundcard_list_controls(struct mixer *mixer)
181{
182 struct mixer_ctl *ctl;
183 const char *name, *type;
184 unsigned int num_ctls, num_values;
185 unsigned int i;
186
187 num_ctls = mixer_get_num_ctls(mixer);
188
189 ALOGI("Number of controls: %d\n", num_ctls);
190
191 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
192 for (i = 0; i < num_ctls; i++) {
193 ctl = mixer_get_ctl(mixer, i);
194 if (ctl != NULL) {
195 name = mixer_ctl_get_name(ctl);
196 type = mixer_ctl_get_type_string(ctl);
197 num_values = mixer_ctl_get_num_values(ctl);
198 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
199 if (name != NULL)
200 usb_soundcard_detail_control(mixer, name);
201 }
202 }
203}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700204
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800205static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
206 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700207{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800208 struct mixer_ctl *ctl;
209 unsigned int dev_token;
210 unsigned int pcm_device_number = 0;
211
212 /*
213 * usb_dev_token_id is 32 bit number and is defined as below:
214 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
215 */
216 dev_token = (card << 16 ) |
217 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
218
219 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
220 if (!ctl) {
221 ALOGE("%s: Could not get ctl for mixer cmd - %s",
222 __func__, dev_mixer_ctl_name);
223 return -EINVAL;
224 }
225 mixer_ctl_set_value(ctl, 0, dev_token);
226
227 return 0;
228}
229
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700230static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
231{
232 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
233 endian_mixer_ctl_name);
234 if (!ctl) {
235 ALOGE("%s: Could not get ctl for mixer cmd - %s",
236 __func__, endian_mixer_ctl_name);
237 return -EINVAL;
238 }
239
240 switch (endian) {
241 case 0:
242 case 1:
243 mixer_ctl_set_value(ctl, 0, endian);
244 break;
245 default:
246 ALOGW("%s: endianness(%d) not supported",
247 __func__, endian);
248 break;
249 }
250 return 0;
251}
252
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700253static int usb_get_sample_rates(int type, char *rates_str,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800254 struct usb_device_config *config)
255{
256 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700257 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800258 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700259
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800260 /* Sample rate string can be in any of the folloing two bit_widthes:
261 * Rates: 8000 - 48000 (continuous)
262 * Rates: 8000, 44100, 48000
263 * Support both the bit_widths
264 */
265 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700266 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
267 if (next_sr_string == NULL) {
268 ALOGE("%s: could not find min rates string", __func__);
269 return -EINVAL;
270 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800271 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700272 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700273 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800274 if (next_sr_string == NULL) {
275 ALOGE("%s: could not find max rates string", __func__);
276 return -EINVAL;
277 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700278 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800279
Kuirong Wang591a98a2016-06-27 12:41:41 -0700280 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800281 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700282 supported_sample_rates[i] <= max_sr) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800283 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700284 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700285 ALOGI_IF(usb_audio_debug_enable,
286 "%s: continuous sample rate supported_sample_rates[%d] %d",
287 __func__, i, supported_sample_rates[i]);
288 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800289 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700290 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800291 do {
292 sr = (uint32_t)atoi(next_sr_string);
293 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
294 if (supported_sample_rates[i] == sr) {
295 ALOGI_IF(usb_audio_debug_enable,
296 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
297 __func__, sr, i, supported_sample_rates[i]);
298 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700299 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800300 }
301 }
302 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
303 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700304 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800305 config->rate_size = sr_size;
306 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700307}
308
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800309static int usb_get_capability(int type,
310 struct usb_card_config *usb_card_info,
311 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700312{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700313 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800314 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800315 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700316 char *str_start = NULL;
317 char *str_end = NULL;
318 char *channel_start = NULL;
319 char *bit_width_start = NULL;
320 char *rates_str_start = NULL;
321 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700322 char *read_buf = NULL;
323 char *rates_str = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700324 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700325 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800326 char *bit_width_str = NULL;
327 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700328 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700329
Kuirong Wange9894162016-08-26 15:16:39 -0700330 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800331 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
332 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
333
Kuirong Wange9894162016-08-26 15:16:39 -0700334 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800335 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700336 if(ret < 0) {
337 ALOGE("%s: failed on snprintf (%d) to path %s\n",
338 __func__, ret, path);
339 goto done;
340 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700341
342 fd = open(path, O_RDONLY);
343 if (fd <0) {
344 ALOGE("%s: error failed to open config file %s error: %d\n",
345 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700346 ret = -EINVAL;
347 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700348 }
349
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800350 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700351
352 if (!read_buf) {
353 ALOGE("Failed to create read_buf");
354 ret = -ENOMEM;
355 goto done;
356 }
357
Kuirong Wange9894162016-08-26 15:16:39 -0700358 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
359 ALOGE("file read error\n");
360 goto done;
361 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800362 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
363 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700364 if (str_start == NULL) {
365 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800366 __func__, ((type == USB_PLAYBACK) ?
367 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700368 ret = -EINVAL;
369 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700370 }
Kuirong Wange9894162016-08-26 15:16:39 -0700371 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
372 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
373 if (str_end > str_start)
374 check = true;
375
376 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700377
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800378 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700379 str_start = strstr(str_start, "Altset");
380 if ((str_start == NULL) || (check && (str_start >= str_end))) {
381 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800382 break;
383 }
Kuirong Wange9894162016-08-26 15:16:39 -0700384 ALOGV("%s: remaining string %s\n", __func__, str_start);
385 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800386 usb_device_info = calloc(1, sizeof(struct usb_device_config));
387 if (usb_device_info == NULL) {
388 ALOGE("%s: error unable to allocate memory",
389 __func__);
390 ret = -ENOMEM;
391 break;
392 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800393 /* Bit bit_width parsing */
394 bit_width_start = strstr(str_start, "Format: ");
395 if (bit_width_start == NULL) {
396 ALOGI("%s: Could not find bit_width string", __func__);
397 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700398 continue;
399 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800400 target = strchr(bit_width_start, '\n');
401 if (target == NULL) {
402 ALOGI("%s:end of line not found", __func__);
403 free(usb_device_info);
404 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700405 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800406 size = target - bit_width_start;
407 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
408 ALOGE("%s: unable to allocate memory to hold bit width strings",
409 __func__);
410 ret = -EINVAL;
411 free(usb_device_info);
412 break;
413 }
414 memcpy(bit_width_str, bit_width_start, size);
415 bit_width_str[size] = '\0';
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700416
417 const char * formats[] = { "S32", "S24_3", "S24", "S16" };
418 const int bit_width[] = { 32, 24, 24, 16};
419 for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
420 const char * s = strstr(bit_width_str, formats[i]);
421 if (s) {
422 usb_device_info->bit_width = bit_width[i];
423 usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
424 break;
425 }
426 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800427
428 if (bit_width_str)
429 free(bit_width_str);
430
431 /* channels parsing */
432 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
433 if (channel_start == NULL) {
434 ALOGI("%s: could not find Channels string", __func__);
435 free(usb_device_info);
436 continue;
437 }
438 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
439 usb_device_info->channels = channels_no;
440
441 /* Sample rates parsing */
442 rates_str_start = strstr(str_start, "Rates: ");
443 if (rates_str_start == NULL) {
444 ALOGI("%s: cant find rates string", __func__);
445 free(usb_device_info);
446 continue;
447 }
448 target = strchr(rates_str_start, '\n');
449 if (target == NULL) {
450 ALOGI("%s: end of line not found", __func__);
451 free(usb_device_info);
452 continue;
453 }
454 size = target - rates_str_start;
455 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
456 ALOGE("%s: unable to allocate memory to hold sample rate strings",
457 __func__);
458 ret = -EINVAL;
459 free(usb_device_info);
460 break;
461 }
462 memcpy(rates_str, rates_str_start, size);
463 rates_str[size] = '\0';
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464 ret = usb_get_sample_rates(type, rates_str, usb_device_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800465 if (rates_str)
466 free(rates_str);
467 if (ret < 0) {
468 ALOGI("%s: error unable to get sample rate values",
469 __func__);
470 free(usb_device_info);
471 continue;
472 }
473 /* Add to list if every field is valid */
474 list_add_tail(&usb_card_info->usb_device_conf_list,
475 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700476 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700477
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700478done:
479 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700480 if (read_buf) free(read_buf);
481 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700482}
483
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800484static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
485 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700486{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800487 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700488
489 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800490 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
491 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700492 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800493 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700494 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800495 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700496 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800497exit:
498
499 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700500}
501
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800502static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
503 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700504{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800505 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700506
507 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800508 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
509 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700510 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800511 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700512 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800513 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700514 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700515
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800516exit:
517 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700518}
519
Kuirong Wang1cad7142016-05-24 15:21:56 -0700520static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
521{
522 struct mixer_ctl *ctl;
523 unsigned int index;
524
525 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
526 usb_card_info->usb_sidetone_index[index] = -1;
527
528 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
529 for (index = 0;
530 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
531 index++) {
532 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
533 usb_sidetone_enable_str[index]);
534 if (ctl) {
535 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
536 /* Disable device sidetone by default */
537 mixer_ctl_set_value(ctl, 0, false);
538 break;
539 }
540 }
541 for (index = 0;
542 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
543 index++) {
544 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
545 usb_sidetone_volume_str[index]);
546 if (ctl) {
547 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
548 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
549 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
550 break;
551 }
552 }
553
554 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
555 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
556
557 return;
558}
559
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700560static inline bool usb_output_device(audio_devices_t device) {
561 // ignore accessory for now
562 if (device == AUDIO_DEVICE_OUT_USB_ACCESSORY)
563 return false;
564 return audio_is_usb_out_device(device);
565}
566
567static inline bool usb_input_device(audio_devices_t device) {
568 // ignore accessory for now
569 if (device == AUDIO_DEVICE_IN_USB_ACCESSORY)
570 return false;
571 return audio_is_usb_in_device(device);
572}
573
574static bool usb_valid_device(audio_devices_t device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700575{
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700576 return usb_output_device(device) ||
577 usb_input_device(device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800578}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700579
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800580static void usb_print_active_device(void){
581 struct listnode *node_i, *node_j;
582 struct usb_device_config *dev_info;
583 struct usb_card_config *card_info;
584 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700585
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800586 ALOGI("%s", __func__);
587 list_for_each(node_i, &usbmod->usb_card_conf_list) {
588 card_info = node_to_item(node_i, struct usb_card_config, list);
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700589 ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
590 __func__, card_info->usb_device_type,
591 card_info->usb_card, card_info->endian ? "BE" : "LE");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800592 list_for_each(node_j, &card_info->usb_device_conf_list) {
593 dev_info = node_to_item(node_j, struct usb_device_config, list);
594 ALOGI("%s: bit-width(%d) channel(%d)",
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700595 __func__, dev_info->bit_width, dev_info->channels);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800596 for (i = 0; i < dev_info->rate_size; i++)
597 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
598 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700599 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800600}
601
602static bool usb_get_best_match_for_bit_width(
603 struct listnode *dev_list,
604 unsigned int stream_bit_width,
605 unsigned int *bit_width)
606{
607 struct listnode *node_i;
608 struct usb_device_config *dev_info;
609 unsigned int candidate = 0;
610
611 list_for_each(node_i, dev_list) {
612 dev_info = node_to_item(node_i, struct usb_device_config, list);
613 ALOGI_IF(usb_audio_debug_enable,
614 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
615 __func__, dev_info->bit_width,
616 stream_bit_width, candidate);
617 if (dev_info->bit_width == stream_bit_width) {
618 *bit_width = dev_info->bit_width;
619 ALOGV("%s: Found match bit-width (%d)",
620 __func__, dev_info->bit_width);
621 goto exit;
622 } else if (candidate == 0) {
623 candidate = dev_info->bit_width;
624 }
625 /*
626 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
627 * higher bit width 32 is picked up instead of 16-bit
628 */
629 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
630 ABS_SUB(stream_bit_width, candidate)) {
631 candidate = dev_info->bit_width;
632 }
633 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
634 ABS_SUB(stream_bit_width, candidate)) &&
635 (dev_info->bit_width > candidate)) {
636 candidate = dev_info->bit_width;
637 }
638 }
639 ALOGV("%s: No match found, use the best candidate bw(%d)",
640 __func__, candidate);
641 *bit_width = candidate;
642exit:
643 return true;
644}
645
646static bool usb_get_best_match_for_channels(
647 struct listnode *dev_list,
648 unsigned int bit_width,
649 unsigned int stream_ch,
650 unsigned int *ch)
651{
652 struct listnode *node_i;
653 struct usb_device_config *dev_info;
654 unsigned int candidate = 0;
655
656 list_for_each(node_i, dev_list) {
657 dev_info = node_to_item(node_i, struct usb_device_config, list);
658 ALOGI_IF(usb_audio_debug_enable,
659 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
660 __func__, dev_info->channels, dev_info->bit_width,
661 stream_ch, bit_width, candidate);
662 if (dev_info->bit_width != bit_width)
663 continue;
664 if (dev_info->channels== stream_ch) {
665 *ch = dev_info->channels;
666 ALOGV("%s: Found match channels (%d)",
667 __func__, dev_info->channels);
668 goto exit;
669 } else if (candidate == 0)
670 candidate = dev_info->channels;
671 /*
672 * If stream channel is 4, USB supports both 3 and 5, then
673 * higher channel 5 is picked up instead of 3
674 */
675 else if (ABS_SUB(stream_ch, dev_info->channels) <
676 ABS_SUB(stream_ch, candidate)) {
677 candidate = dev_info->channels;
678 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
679 ABS_SUB(stream_ch, candidate)) &&
680 (dev_info->channels > candidate)) {
681 candidate = dev_info->channels;
682 }
683 }
684 ALOGV("%s: No match found, use the best candidate ch(%d)",
685 __func__, candidate);
686 *ch = candidate;
687exit:
688 return true;
689
690}
691
692static bool usb_sample_rate_multiple(
693 unsigned int stream_sample_rate,
694 unsigned int base)
695{
696 return (((stream_sample_rate / base) * base) == stream_sample_rate);
697}
698
699static bool usb_find_sample_rate_candidate(unsigned int base,
700 unsigned stream_rate,
701 unsigned int usb_rate,
702 unsigned int cur_candidate,
703 unsigned int *update_candidate)
704{
705 /* For sample rate, we should consider fracational sample rate as high priority.
706 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
707 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
708 */
709 if (!usb_sample_rate_multiple(cur_candidate, base) &&
710 usb_sample_rate_multiple(usb_rate, base)) {
711 *update_candidate = usb_rate;
712 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
713 usb_sample_rate_multiple(usb_rate, base)) {
714 if (ABS_SUB(stream_rate, usb_rate) <
715 ABS_SUB(stream_rate, cur_candidate)) {
716 *update_candidate = usb_rate;
717 } else if ((ABS_SUB(stream_rate, usb_rate) ==
718 ABS_SUB(stream_rate, cur_candidate)) &&
719 (usb_rate > cur_candidate)) {
720 *update_candidate = usb_rate;
721 }
722 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
723 !usb_sample_rate_multiple(usb_rate, base)) {
724 if (ABS_SUB(stream_rate, usb_rate) <
725 ABS_SUB(stream_rate, cur_candidate)) {
726 *update_candidate = usb_rate;
727 } else if ((ABS_SUB(stream_rate, usb_rate) ==
728 ABS_SUB(stream_rate, cur_candidate)) &&
729 (usb_rate > cur_candidate)) {
730 *update_candidate = usb_rate;
731 }
732 }
733 return true;
734}
735
736static bool usb_get_best_match_for_sample_rate(
737 struct listnode *dev_list,
738 unsigned int bit_width,
739 unsigned int ch,
740 unsigned int stream_sample_rate,
741 unsigned int *sr)
742{
743 struct listnode *node_i;
744 struct usb_device_config *dev_info;
745 unsigned int candidate = 48000;
746 unsigned int base = SAMPLE_RATE_8000;
747 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
748 unsigned int i;
749
750 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
751 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
752
753 list_for_each(node_i, dev_list) {
754 dev_info = node_to_item(node_i, struct usb_device_config, list);
755 ALOGI_IF(usb_audio_debug_enable,
756 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
757 __func__, dev_info->channels, dev_info->bit_width,
758 ch, bit_width, stream_sample_rate, candidate);
Ashish Jainb26edfb2016-08-25 00:10:11 +0530759 if ((dev_info->bit_width != bit_width) || dev_info->channels != ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800760 continue;
761
762 candidate = 0;
763 for (i = 0; i < dev_info->rate_size; i++) {
764 ALOGI_IF(usb_audio_debug_enable,
765 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
766 __func__, dev_info->channels,
767 dev_info->bit_width, dev_info->rates[i],
768 ch, bit_width, stream_sample_rate, candidate);
769 if (stream_sample_rate == dev_info->rates[i]) {
770 *sr = dev_info->rates[i];
771 ALOGV("%s: Found match sample rate (%d)",
772 __func__, dev_info->rates[i]);
773 goto exit;
774 } else if (candidate == 0) {
775 candidate = dev_info->rates[i];
776 /*
777 * For sample rate, we should consider fracational sample rate as high priority.
778 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
779 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
780 */
781 } else if (multiple_8k) {
782 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
783 stream_sample_rate,
784 dev_info->rates[i],
785 candidate,
786 &candidate);
787 } else {
788 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
789 stream_sample_rate,
790 dev_info->rates[i],
791 candidate,
792 &candidate);
793 }
794 }
795 }
796 ALOGV("%s: No match found, use the best candidate sr(%d)",
797 __func__, candidate);
798 *sr = candidate;
799exit:
800 return true;
801}
802
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800803static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
804 unsigned int *bit_width,
805 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530806 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800807{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800808 bool is_usb_supported = true;
809
810 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530811 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800812 if (list_empty(dev_list)) {
813 *sample_rate = 48000;
814 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530815 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800816 ALOGI("%s: list is empty,fall back to default setting", __func__);
817 goto exit;
818 }
819 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
820 usb_get_best_match_for_channels(dev_list,
821 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530822 *ch,
823 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800824 usb_get_best_match_for_sample_rate(dev_list,
825 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530826 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800827 *sample_rate,
828 sample_rate);
829exit:
830 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530831 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800832 return is_usb_supported;
833}
834
Kuirong Wang1cad7142016-05-24 15:21:56 -0700835static int usb_get_sidetone_gain(struct usb_card_config *card_info)
836{
837 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
838 if (gain > card_info->usb_sidetone_vol_max)
839 gain = card_info->usb_sidetone_vol_max;
840 return gain;
841}
842
843void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
844 char *value, int len)
845{
846 int err;
847
848 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
849 value, len);
850 if (err >= 0) {
851 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
852 ALOGV("%s: sidetone gain(%s) decimal %d",
853 __func__, value, usb_sidetone_gain);
854 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
855 }
856 return;
857}
858
859int audio_extn_usb_enable_sidetone(int device, bool enable)
860{
861 int ret = -ENODEV;
862 struct listnode *node_i;
863 struct usb_card_config *card_info;
864 int i;
865 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
866 __func__, device, enable);
867
868 list_for_each(node_i, &usbmod->usb_card_conf_list) {
869 card_info = node_to_item(node_i, struct usb_card_config, list);
870 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
871 __func__, card_info->usb_device_type, card_info->usb_card);
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700872 if (usb_output_device(card_info->usb_device_type)) {
Kuirong Wang1cad7142016-05-24 15:21:56 -0700873 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
874 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
875 card_info->usb_snd_mixer,
876 usb_sidetone_enable_str[i]);
877 if (ctl)
878 mixer_ctl_set_value(ctl, 0, enable);
879 else
880 break;
881
882 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
883 ctl = mixer_get_ctl_by_name(
884 card_info->usb_snd_mixer,
885 usb_sidetone_volume_str[i]);
886 if (ctl == NULL)
887 ALOGV("%s: sidetone gain mixer command is not found",
888 __func__);
889 else if (enable)
890 mixer_ctl_set_value(ctl, 0,
891 usb_get_sidetone_gain(card_info));
892 }
893 ret = 0;
894 break;
895 }
896 }
897 }
898 return ret;
899}
900
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800901bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
902 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700903 unsigned int *ch,
904 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800905{
906 struct listnode *node_i;
907 struct usb_card_config *card_info;
908 bool is_usb_supported = false;
909
Kuirong Wang27152a12016-11-11 10:20:30 -0800910 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
911 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800912 list_for_each(node_i, &usbmod->usb_card_conf_list) {
913 card_info = node_to_item(node_i, struct usb_card_config, list);
914 ALOGI_IF(usb_audio_debug_enable,
915 "%s: card_dev_type (0x%x), card_no(%d)",
916 __func__, card_info->usb_device_type, card_info->usb_card);
917 /* Currently only apply the first playback sound card configuration */
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700918 if ((is_playback && usb_output_device(card_info->usb_device_type)) ||
919 (!is_playback && usb_input_device(card_info->usb_device_type))){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800920 is_usb_supported = usb_audio_backend_apply_policy(
921 &card_info->usb_device_conf_list,
922 bit_width,
923 sample_rate,
924 ch);
925 break;
926 }
927 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530928 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
929 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800930
931 return is_usb_supported;
932}
933
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700934int audio_extn_usb_get_max_channels(bool is_playback)
935{
936 struct listnode *node_i, *node_j;
937 struct usb_device_config *dev_info;
938 struct usb_card_config *card_info;
939 unsigned int max_ch = 1;
940 list_for_each(node_i, &usbmod->usb_card_conf_list) {
941 card_info = node_to_item(node_i, struct usb_card_config, list);
942 if (usb_output_device(card_info->usb_device_type) && !is_playback)
943 continue;
944 else if (usb_input_device(card_info->usb_device_type) && is_playback)
945 continue;
946
947 list_for_each(node_j, &card_info->usb_device_conf_list) {
948 dev_info = node_to_item(node_j, struct usb_device_config, list);
949 max_ch = _MAX(max_ch, dev_info->channels);
950 }
951 }
952
953 return max_ch;
954}
955
956int audio_extn_usb_get_max_bit_width(bool is_playback)
957{
958 struct listnode *node_i, *node_j;
959 struct usb_device_config *dev_info;
960 struct usb_card_config *card_info;
961 unsigned int max_bw = 16;
962 list_for_each(node_i, &usbmod->usb_card_conf_list) {
963 card_info = node_to_item(node_i, struct usb_card_config, list);
964 if (usb_output_device(card_info->usb_device_type) && !is_playback)
965 continue;
966 else if (usb_input_device(card_info->usb_device_type) && is_playback)
967 continue;
968
969 list_for_each(node_j, &card_info->usb_device_conf_list) {
970 dev_info = node_to_item(node_j, struct usb_device_config, list);
971 max_bw = _MAX(max_bw, dev_info->bit_width);
972 }
973 }
974
975 return max_bw;
976}
977
978int audio_extn_usb_get_sup_sample_rates(bool is_playback,
979 uint32_t *sample_rates,
980 uint32_t sample_rate_size)
981{
982 int type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
983
984 ALOGV("%s supported_sample_rates_mask 0x%x", __func__, supported_sample_rates_mask[type]);
985 uint32_t bm = supported_sample_rates_mask[type];
986 uint32_t tries = _MIN(sample_rate_size, (uint32_t)__builtin_popcount(bm));
987
988 int i = 0;
989 while (tries--) {
990 int idx = __builtin_ffs(bm) - 1;
991 sample_rates[i++] = supported_sample_rates[idx];
992 bm &= ~(1<<idx);
993 }
994
995 return i;
996}
997
Ashish Jain3e37a702016-11-25 12:27:15 +0530998bool audio_extn_usb_is_capture_supported()
999{
1000 if (usbmod == NULL) {
1001 ALOGE("%s: USB device object is NULL", __func__);
1002 return false;
1003 }
1004 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
1005 return usbmod->is_capture_supported;
1006}
1007
Zhou Song6f862822017-11-06 17:27:57 +08001008bool audio_extn_usb_is_tunnel_supported()
1009{
1010 return true;
1011}
1012
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001013void audio_extn_usb_add_device(audio_devices_t device, int card)
1014{
1015 struct usb_card_config *usb_card_info;
1016 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -08001017 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001018
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07001019 property_get("vendor.audio.usb.enable.debug", check_debug_enable, NULL);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001020 if (atoi(check_debug_enable)) {
1021 usb_audio_debug_enable = true;
1022 }
1023
1024 ALOGI_IF(usb_audio_debug_enable,
1025 "%s: parameters device(0x%x), card(%d)",
1026 __func__, device, card);
1027 if (usbmod == NULL) {
1028 ALOGE("%s: USB device object is NULL", __func__);
1029 goto exit;
1030 }
1031
1032 if (!(usb_valid_device(device)) || (card < 0)) {
1033 ALOGE("%s:device(0x%x), card(%d)",
1034 __func__, device, card);
1035 goto exit;
1036 }
1037
Kuirong Wang27152a12016-11-11 10:20:30 -08001038 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1039 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
1040 ALOGI_IF(usb_audio_debug_enable,
1041 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
1042 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
1043 /* If we have cached the capability */
1044 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
1045 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
1046 __func__, device, card);
1047 goto exit;
1048 }
1049 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001050 usb_card_info = calloc(1, sizeof(struct usb_card_config));
1051 if (usb_card_info == NULL) {
1052 ALOGE("%s: error unable to allocate memory",
1053 __func__);
1054 goto exit;
1055 }
1056 list_init(&usb_card_info->usb_device_conf_list);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001057 if (usb_output_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001058 if (!usb_get_device_pb_config(usb_card_info, card)){
1059 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001060 usb_card_info->usb_device_type = device;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001061 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001062 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1063 goto exit;
1064 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001065 } else if (usb_input_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001066 if (!usb_get_device_cap_config(usb_card_info, card)) {
1067 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001068 usb_card_info->usb_device_type = device;
Ashish Jain3e37a702016-11-25 12:27:15 +05301069 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001070 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1071 goto exit;
1072 }
1073 }
1074 /* free memory in error case */
1075 if (usb_card_info != NULL)
1076 free(usb_card_info);
1077exit:
1078 if (usb_audio_debug_enable)
1079 usb_print_active_device();
1080 return;
1081}
1082
1083void audio_extn_usb_remove_device(audio_devices_t device, int card)
1084{
1085 struct listnode *node_i, *temp_i;
1086 struct listnode *node_j, *temp_j;
1087 struct usb_device_config *dev_info;
1088 struct usb_card_config *card_info;
1089 unsigned int i;
1090
1091 ALOGV("%s: device(0x%x), card(%d)",
1092 __func__, device, card);
1093
1094 if (usbmod == NULL) {
1095 ALOGE("%s: USB device object is NULL", __func__);
1096 goto exit;
1097 }
1098
1099 if (!(usb_valid_device(device)) || (card < 0)) {
1100 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1101 __func__, device, card);
1102 goto exit;
1103 }
1104 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1105 card_info = node_to_item(node_i, struct usb_card_config, list);
1106 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1107 __func__, card_info->usb_device_type, card_info->usb_card);
1108 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1109 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1110 dev_info = node_to_item(node_j, struct usb_device_config, list);
1111 ALOGV("%s: bit-width(%d) channel(%d)",
1112 __func__, dev_info->bit_width, dev_info->channels);
1113 for (i = 0; i < dev_info->rate_size; i++)
1114 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1115
1116 list_remove(node_j);
1117 free(node_to_item(node_j, struct usb_device_config, list));
1118 }
1119 list_remove(node_i);
1120 free(node_to_item(node_i, struct usb_card_config, list));
1121 }
1122 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001123 if (audio_is_usb_in_device(device)) { // XXX not sure if we need to check for card
1124 usbmod->is_capture_supported = false;
1125 supported_sample_rates_mask[USB_CAPTURE] = 0;
1126 } else
1127 supported_sample_rates_mask[USB_PLAYBACK] = 0;
1128
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001129exit:
1130 if (usb_audio_debug_enable)
1131 usb_print_active_device();
1132
1133 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001134}
1135
Kevin Rocardfce19002017-08-07 19:21:36 -07001136bool audio_extn_usb_alive(int card) {
1137 char path[PATH_MAX] = {0};
1138 // snprintf should never fail
1139 (void) snprintf(path, sizeof(path), "/proc/asound/card%u/stream0", card);
1140 return access(path, F_OK) == 0;
1141}
1142
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001143void audio_extn_usb_init(void *adev)
1144{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001145 if (usbmod == NULL) {
1146 usbmod = calloc(1, sizeof(struct usb_module));
1147 if (usbmod == NULL) {
1148 ALOGE("%s: error unable to allocate memory", __func__);
1149 goto exit;
1150 }
1151 }
1152 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001153 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001154 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301155 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001156exit:
1157 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001158}
1159
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001160void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001161{
1162 if (NULL != usbmod){
1163 free(usbmod);
1164 usbmod = NULL;
1165 }
1166}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001167#endif /*USB_HEADSET_ENABLED end*/