blob: 8766c0e841ce85cc6c75a6bb0624aec690391608 [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>
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
Weiyin Jiangcba6f962018-03-18 11:52:05 +080054#define SAMPLE_RATE_192000 192000
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080055// Supported sample rates for USB
56static uint32_t supported_sample_rates[] =
Haynes Mathew George484e8d22017-07-31 18:55:17 -070057 {384000, 352800, 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 22050, 16000, 11025, 8000};
58static uint32_t supported_sample_rates_mask[2];
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080059
60#define MAX_SAMPLE_RATE_SIZE sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
61
Haynes Mathew George484e8d22017-07-31 18:55:17 -070062#define _MAX(x, y) (((x) >= (y)) ? (x) : (y))
63#define _MIN(x, y) (((x) <= (y)) ? (x) : (y))
64
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080065enum usb_usecase_type{
66 USB_PLAYBACK = 0,
67 USB_CAPTURE,
68};
69
Kuirong Wang1cad7142016-05-24 15:21:56 -070070enum {
71 USB_SIDETONE_ENABLE_INDEX = 0,
72 USB_SIDETONE_VOLUME_INDEX,
73 USB_SIDETONE_MAX_INDEX,
74};
75
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080076struct usb_device_config {
77 struct listnode list;
78 unsigned int bit_width;
79 unsigned int channels;
80 unsigned int rate_size;
81 unsigned int rates[MAX_SAMPLE_RATE_SIZE];
82};
83
84struct usb_card_config {
85 struct listnode list;
86 audio_devices_t usb_device_type;
87 int usb_card;
88 struct listnode usb_device_conf_list;
Kuirong Wang1cad7142016-05-24 15:21:56 -070089 struct mixer *usb_snd_mixer;
90 int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
91 int usb_sidetone_vol_min;
92 int usb_sidetone_vol_max;
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -070093 int endian;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080094};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070095
96struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080097 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070098 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -070099 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +0530100 bool is_capture_supported;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700101};
102
103static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800104static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700105static int usb_sidetone_gain = 0;
106
107static const char * const usb_sidetone_enable_str[] = {
108 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -0700109 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -0700110};
111
112static const char * const usb_sidetone_volume_str[] = {
113 "Sidetone Playback Volume",
114 "Mic Playback Volume",
115};
116
117static void usb_mixer_print_enum(struct mixer_ctl *ctl)
118{
119 unsigned int num_enums;
120 unsigned int i;
121 const char *string;
122
123 num_enums = mixer_ctl_get_num_enums(ctl);
124
125 for (i = 0; i < num_enums; i++) {
126 string = mixer_ctl_get_enum_string(ctl, i);
127 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
128 }
129}
130
131static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
132{
133 struct mixer_ctl *ctl;
134 enum mixer_ctl_type type;
135 unsigned int num_values;
136 unsigned int i;
137 int min, max;
138
139 if (isdigit(control[0]))
140 ctl = mixer_get_ctl(mixer, atoi(control));
141 else
142 ctl = mixer_get_ctl_by_name(mixer, control);
143
144 if (!ctl) {
145 fprintf(stderr, "Invalid mixer control\n");
146 return;
147 }
148
149 type = mixer_ctl_get_type(ctl);
150 num_values = mixer_ctl_get_num_values(ctl);
151
152 ALOGI("%s:", mixer_ctl_get_name(ctl));
153
154 for (i = 0; i < num_values; i++) {
155 switch (type) {
156 case MIXER_CTL_TYPE_INT:
157 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
158 break;
159 case MIXER_CTL_TYPE_BOOL:
160 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
161 break;
162 case MIXER_CTL_TYPE_ENUM:
163 usb_mixer_print_enum(ctl);
164 break;
165 case MIXER_CTL_TYPE_BYTE:
166 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
167 break;
168 default:
169 ALOGI(" unknown");
170 break;
171 }
172 }
173
174 if (type == MIXER_CTL_TYPE_INT) {
175 min = mixer_ctl_get_range_min(ctl);
176 max = mixer_ctl_get_range_max(ctl);
177 ALOGI(" (range %d->%d)", min, max);
178 }
179}
180
181static void usb_soundcard_list_controls(struct mixer *mixer)
182{
183 struct mixer_ctl *ctl;
184 const char *name, *type;
185 unsigned int num_ctls, num_values;
186 unsigned int i;
187
188 num_ctls = mixer_get_num_ctls(mixer);
189
190 ALOGI("Number of controls: %d\n", num_ctls);
191
192 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
193 for (i = 0; i < num_ctls; i++) {
194 ctl = mixer_get_ctl(mixer, i);
195 if (ctl != NULL) {
196 name = mixer_ctl_get_name(ctl);
197 type = mixer_ctl_get_type_string(ctl);
198 num_values = mixer_ctl_get_num_values(ctl);
199 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
200 if (name != NULL)
201 usb_soundcard_detail_control(mixer, name);
202 }
203 }
204}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700205
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800206static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
207 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700208{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800209 struct mixer_ctl *ctl;
210 unsigned int dev_token;
211 unsigned int pcm_device_number = 0;
212
213 /*
214 * usb_dev_token_id is 32 bit number and is defined as below:
215 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
216 */
217 dev_token = (card << 16 ) |
218 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
219
220 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
221 if (!ctl) {
222 ALOGE("%s: Could not get ctl for mixer cmd - %s",
223 __func__, dev_mixer_ctl_name);
224 return -EINVAL;
225 }
226 mixer_ctl_set_value(ctl, 0, dev_token);
227
228 return 0;
229}
230
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700231static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
232{
233 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
234 endian_mixer_ctl_name);
235 if (!ctl) {
236 ALOGE("%s: Could not get ctl for mixer cmd - %s",
237 __func__, endian_mixer_ctl_name);
238 return -EINVAL;
239 }
240
241 switch (endian) {
242 case 0:
243 case 1:
244 mixer_ctl_set_value(ctl, 0, endian);
245 break;
246 default:
247 ALOGW("%s: endianness(%d) not supported",
248 __func__, endian);
249 break;
250 }
251 return 0;
252}
253
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700254static int usb_get_sample_rates(int type, char *rates_str,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800255 struct usb_device_config *config)
256{
257 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700258 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800259 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700260
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800261 /* Sample rate string can be in any of the folloing two bit_widthes:
262 * Rates: 8000 - 48000 (continuous)
263 * Rates: 8000, 44100, 48000
264 * Support both the bit_widths
265 */
266 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700267 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
268 if (next_sr_string == NULL) {
269 ALOGE("%s: could not find min rates string", __func__);
270 return -EINVAL;
271 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800272 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700273 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700274 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800275 if (next_sr_string == NULL) {
276 ALOGE("%s: could not find max rates string", __func__);
277 return -EINVAL;
278 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700279 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800280
Kuirong Wang591a98a2016-06-27 12:41:41 -0700281 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800282 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700283 supported_sample_rates[i] <= max_sr) {
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800284 // FIXME: we don't support >192KHz in recording path for now
285 if ((supported_sample_rates[i] > SAMPLE_RATE_192000) &&
286 (type == USB_CAPTURE))
287 continue;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800288 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700289 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700290 ALOGI_IF(usb_audio_debug_enable,
291 "%s: continuous sample rate supported_sample_rates[%d] %d",
292 __func__, i, supported_sample_rates[i]);
293 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800294 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700295 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800296 do {
297 sr = (uint32_t)atoi(next_sr_string);
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800298 // FIXME: we don't support >192KHz in recording path for now
299 if ((sr > SAMPLE_RATE_192000) && (type == USB_CAPTURE)) {
300 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
301 continue;
302 }
303
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800304 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
305 if (supported_sample_rates[i] == sr) {
306 ALOGI_IF(usb_audio_debug_enable,
307 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
308 __func__, sr, i, supported_sample_rates[i]);
309 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700310 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800311 }
312 }
313 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
314 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700315 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800316 config->rate_size = sr_size;
317 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700318}
319
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800320static int usb_get_capability(int type,
321 struct usb_card_config *usb_card_info,
322 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700323{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700324 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800325 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800326 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700327 char *str_start = NULL;
328 char *str_end = NULL;
329 char *channel_start = NULL;
330 char *bit_width_start = NULL;
331 char *rates_str_start = NULL;
332 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700333 char *read_buf = NULL;
334 char *rates_str = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700335 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700336 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800337 char *bit_width_str = NULL;
338 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700339 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700340
Kuirong Wange9894162016-08-26 15:16:39 -0700341 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800342 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
343 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
344
Kuirong Wange9894162016-08-26 15:16:39 -0700345 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800346 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700347 if(ret < 0) {
348 ALOGE("%s: failed on snprintf (%d) to path %s\n",
349 __func__, ret, path);
350 goto done;
351 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700352
353 fd = open(path, O_RDONLY);
354 if (fd <0) {
355 ALOGE("%s: error failed to open config file %s error: %d\n",
356 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700357 ret = -EINVAL;
358 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700359 }
360
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800361 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700362
363 if (!read_buf) {
364 ALOGE("Failed to create read_buf");
365 ret = -ENOMEM;
366 goto done;
367 }
368
Kuirong Wange9894162016-08-26 15:16:39 -0700369 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
370 ALOGE("file read error\n");
371 goto done;
372 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800373 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
374 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700375 if (str_start == NULL) {
376 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800377 __func__, ((type == USB_PLAYBACK) ?
378 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700379 ret = -EINVAL;
380 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700381 }
Kuirong Wange9894162016-08-26 15:16:39 -0700382 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
383 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
384 if (str_end > str_start)
385 check = true;
386
387 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700388
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800389 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700390 str_start = strstr(str_start, "Altset");
391 if ((str_start == NULL) || (check && (str_start >= str_end))) {
392 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800393 break;
394 }
Kuirong Wange9894162016-08-26 15:16:39 -0700395 ALOGV("%s: remaining string %s\n", __func__, str_start);
396 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800397 usb_device_info = calloc(1, sizeof(struct usb_device_config));
398 if (usb_device_info == NULL) {
399 ALOGE("%s: error unable to allocate memory",
400 __func__);
401 ret = -ENOMEM;
402 break;
403 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800404 /* Bit bit_width parsing */
405 bit_width_start = strstr(str_start, "Format: ");
406 if (bit_width_start == NULL) {
407 ALOGI("%s: Could not find bit_width string", __func__);
408 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700409 continue;
410 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800411 target = strchr(bit_width_start, '\n');
412 if (target == NULL) {
413 ALOGI("%s:end of line not found", __func__);
414 free(usb_device_info);
415 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700416 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800417 size = target - bit_width_start;
418 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
419 ALOGE("%s: unable to allocate memory to hold bit width strings",
420 __func__);
421 ret = -EINVAL;
422 free(usb_device_info);
423 break;
424 }
425 memcpy(bit_width_str, bit_width_start, size);
426 bit_width_str[size] = '\0';
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700427
428 const char * formats[] = { "S32", "S24_3", "S24", "S16" };
429 const int bit_width[] = { 32, 24, 24, 16};
430 for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
431 const char * s = strstr(bit_width_str, formats[i]);
432 if (s) {
433 usb_device_info->bit_width = bit_width[i];
434 usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
435 break;
436 }
437 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800438
439 if (bit_width_str)
440 free(bit_width_str);
441
442 /* channels parsing */
443 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
444 if (channel_start == NULL) {
445 ALOGI("%s: could not find Channels string", __func__);
446 free(usb_device_info);
447 continue;
448 }
449 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
450 usb_device_info->channels = channels_no;
451
452 /* Sample rates parsing */
453 rates_str_start = strstr(str_start, "Rates: ");
454 if (rates_str_start == NULL) {
455 ALOGI("%s: cant find rates string", __func__);
456 free(usb_device_info);
457 continue;
458 }
459 target = strchr(rates_str_start, '\n');
460 if (target == NULL) {
461 ALOGI("%s: end of line not found", __func__);
462 free(usb_device_info);
463 continue;
464 }
465 size = target - rates_str_start;
466 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
467 ALOGE("%s: unable to allocate memory to hold sample rate strings",
468 __func__);
469 ret = -EINVAL;
470 free(usb_device_info);
471 break;
472 }
473 memcpy(rates_str, rates_str_start, size);
474 rates_str[size] = '\0';
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700475 ret = usb_get_sample_rates(type, rates_str, usb_device_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800476 if (rates_str)
477 free(rates_str);
478 if (ret < 0) {
479 ALOGI("%s: error unable to get sample rate values",
480 __func__);
481 free(usb_device_info);
482 continue;
483 }
484 /* Add to list if every field is valid */
485 list_add_tail(&usb_card_info->usb_device_conf_list,
486 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700487 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700488
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700489done:
490 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700491 if (read_buf) free(read_buf);
492 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700493}
494
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800495static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
496 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700497{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800498 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700499
500 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800501 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
502 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700503 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800504 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700505 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800506 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700507 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800508exit:
509
510 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511}
512
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800513static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
514 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700515{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800516 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700517
518 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800519 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
520 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700521 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800522 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700523 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800524 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700525 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700526
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800527exit:
528 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700529}
530
Kuirong Wang1cad7142016-05-24 15:21:56 -0700531static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
532{
533 struct mixer_ctl *ctl;
534 unsigned int index;
535
536 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
537 usb_card_info->usb_sidetone_index[index] = -1;
538
539 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
540 for (index = 0;
541 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
542 index++) {
543 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
544 usb_sidetone_enable_str[index]);
545 if (ctl) {
546 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
547 /* Disable device sidetone by default */
548 mixer_ctl_set_value(ctl, 0, false);
549 break;
550 }
551 }
552 for (index = 0;
553 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
554 index++) {
555 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
556 usb_sidetone_volume_str[index]);
557 if (ctl) {
558 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
559 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
560 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
561 break;
562 }
563 }
564
565 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
566 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
567
568 return;
569}
570
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700571static inline bool usb_output_device(audio_devices_t device) {
572 // ignore accessory for now
573 if (device == AUDIO_DEVICE_OUT_USB_ACCESSORY)
574 return false;
575 return audio_is_usb_out_device(device);
576}
577
578static inline bool usb_input_device(audio_devices_t device) {
579 // ignore accessory for now
580 if (device == AUDIO_DEVICE_IN_USB_ACCESSORY)
581 return false;
582 return audio_is_usb_in_device(device);
583}
584
585static bool usb_valid_device(audio_devices_t device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700586{
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700587 return usb_output_device(device) ||
588 usb_input_device(device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800589}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700590
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800591static void usb_print_active_device(void){
592 struct listnode *node_i, *node_j;
593 struct usb_device_config *dev_info;
594 struct usb_card_config *card_info;
595 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700596
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800597 ALOGI("%s", __func__);
598 list_for_each(node_i, &usbmod->usb_card_conf_list) {
599 card_info = node_to_item(node_i, struct usb_card_config, list);
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700600 ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
601 __func__, card_info->usb_device_type,
602 card_info->usb_card, card_info->endian ? "BE" : "LE");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800603 list_for_each(node_j, &card_info->usb_device_conf_list) {
604 dev_info = node_to_item(node_j, struct usb_device_config, list);
605 ALOGI("%s: bit-width(%d) channel(%d)",
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700606 __func__, dev_info->bit_width, dev_info->channels);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800607 for (i = 0; i < dev_info->rate_size; i++)
608 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
609 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700610 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800611}
612
613static bool usb_get_best_match_for_bit_width(
614 struct listnode *dev_list,
615 unsigned int stream_bit_width,
616 unsigned int *bit_width)
617{
618 struct listnode *node_i;
619 struct usb_device_config *dev_info;
620 unsigned int candidate = 0;
621
622 list_for_each(node_i, dev_list) {
623 dev_info = node_to_item(node_i, struct usb_device_config, list);
624 ALOGI_IF(usb_audio_debug_enable,
625 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
626 __func__, dev_info->bit_width,
627 stream_bit_width, candidate);
628 if (dev_info->bit_width == stream_bit_width) {
629 *bit_width = dev_info->bit_width;
630 ALOGV("%s: Found match bit-width (%d)",
631 __func__, dev_info->bit_width);
632 goto exit;
633 } else if (candidate == 0) {
634 candidate = dev_info->bit_width;
635 }
636 /*
637 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
638 * higher bit width 32 is picked up instead of 16-bit
639 */
640 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
641 ABS_SUB(stream_bit_width, candidate)) {
642 candidate = dev_info->bit_width;
643 }
644 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
645 ABS_SUB(stream_bit_width, candidate)) &&
646 (dev_info->bit_width > candidate)) {
647 candidate = dev_info->bit_width;
648 }
649 }
650 ALOGV("%s: No match found, use the best candidate bw(%d)",
651 __func__, candidate);
652 *bit_width = candidate;
653exit:
654 return true;
655}
656
657static bool usb_get_best_match_for_channels(
658 struct listnode *dev_list,
659 unsigned int bit_width,
660 unsigned int stream_ch,
661 unsigned int *ch)
662{
663 struct listnode *node_i;
664 struct usb_device_config *dev_info;
665 unsigned int candidate = 0;
666
667 list_for_each(node_i, dev_list) {
668 dev_info = node_to_item(node_i, struct usb_device_config, list);
669 ALOGI_IF(usb_audio_debug_enable,
670 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
671 __func__, dev_info->channels, dev_info->bit_width,
672 stream_ch, bit_width, candidate);
673 if (dev_info->bit_width != bit_width)
674 continue;
675 if (dev_info->channels== stream_ch) {
676 *ch = dev_info->channels;
677 ALOGV("%s: Found match channels (%d)",
678 __func__, dev_info->channels);
679 goto exit;
680 } else if (candidate == 0)
681 candidate = dev_info->channels;
682 /*
683 * If stream channel is 4, USB supports both 3 and 5, then
684 * higher channel 5 is picked up instead of 3
685 */
686 else if (ABS_SUB(stream_ch, dev_info->channels) <
687 ABS_SUB(stream_ch, candidate)) {
688 candidate = dev_info->channels;
689 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
690 ABS_SUB(stream_ch, candidate)) &&
691 (dev_info->channels > candidate)) {
692 candidate = dev_info->channels;
693 }
694 }
695 ALOGV("%s: No match found, use the best candidate ch(%d)",
696 __func__, candidate);
697 *ch = candidate;
698exit:
699 return true;
700
701}
702
703static bool usb_sample_rate_multiple(
704 unsigned int stream_sample_rate,
705 unsigned int base)
706{
707 return (((stream_sample_rate / base) * base) == stream_sample_rate);
708}
709
710static bool usb_find_sample_rate_candidate(unsigned int base,
711 unsigned stream_rate,
712 unsigned int usb_rate,
713 unsigned int cur_candidate,
714 unsigned int *update_candidate)
715{
716 /* For sample rate, we should consider fracational sample rate as high priority.
717 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
718 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
719 */
720 if (!usb_sample_rate_multiple(cur_candidate, base) &&
721 usb_sample_rate_multiple(usb_rate, base)) {
722 *update_candidate = usb_rate;
723 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
724 usb_sample_rate_multiple(usb_rate, base)) {
725 if (ABS_SUB(stream_rate, usb_rate) <
726 ABS_SUB(stream_rate, cur_candidate)) {
727 *update_candidate = usb_rate;
728 } else if ((ABS_SUB(stream_rate, usb_rate) ==
729 ABS_SUB(stream_rate, cur_candidate)) &&
730 (usb_rate > cur_candidate)) {
731 *update_candidate = usb_rate;
732 }
733 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
734 !usb_sample_rate_multiple(usb_rate, base)) {
735 if (ABS_SUB(stream_rate, usb_rate) <
736 ABS_SUB(stream_rate, cur_candidate)) {
737 *update_candidate = usb_rate;
738 } else if ((ABS_SUB(stream_rate, usb_rate) ==
739 ABS_SUB(stream_rate, cur_candidate)) &&
740 (usb_rate > cur_candidate)) {
741 *update_candidate = usb_rate;
742 }
743 }
744 return true;
745}
746
747static bool usb_get_best_match_for_sample_rate(
748 struct listnode *dev_list,
749 unsigned int bit_width,
750 unsigned int ch,
751 unsigned int stream_sample_rate,
752 unsigned int *sr)
753{
754 struct listnode *node_i;
755 struct usb_device_config *dev_info;
756 unsigned int candidate = 48000;
757 unsigned int base = SAMPLE_RATE_8000;
758 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
759 unsigned int i;
760
761 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
762 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
763
764 list_for_each(node_i, dev_list) {
765 dev_info = node_to_item(node_i, struct usb_device_config, list);
766 ALOGI_IF(usb_audio_debug_enable,
767 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
768 __func__, dev_info->channels, dev_info->bit_width,
769 ch, bit_width, stream_sample_rate, candidate);
Ashish Jainb26edfb2016-08-25 00:10:11 +0530770 if ((dev_info->bit_width != bit_width) || dev_info->channels != ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800771 continue;
772
773 candidate = 0;
774 for (i = 0; i < dev_info->rate_size; i++) {
775 ALOGI_IF(usb_audio_debug_enable,
776 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
777 __func__, dev_info->channels,
778 dev_info->bit_width, dev_info->rates[i],
779 ch, bit_width, stream_sample_rate, candidate);
780 if (stream_sample_rate == dev_info->rates[i]) {
781 *sr = dev_info->rates[i];
782 ALOGV("%s: Found match sample rate (%d)",
783 __func__, dev_info->rates[i]);
784 goto exit;
785 } else if (candidate == 0) {
786 candidate = dev_info->rates[i];
787 /*
788 * For sample rate, we should consider fracational sample rate as high priority.
789 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
790 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
791 */
792 } else if (multiple_8k) {
793 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
794 stream_sample_rate,
795 dev_info->rates[i],
796 candidate,
797 &candidate);
798 } else {
799 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
800 stream_sample_rate,
801 dev_info->rates[i],
802 candidate,
803 &candidate);
804 }
805 }
806 }
807 ALOGV("%s: No match found, use the best candidate sr(%d)",
808 __func__, candidate);
809 *sr = candidate;
810exit:
811 return true;
812}
813
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800814static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
815 unsigned int *bit_width,
816 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530817 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800818{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800819 bool is_usb_supported = true;
820
821 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530822 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800823 if (list_empty(dev_list)) {
824 *sample_rate = 48000;
825 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530826 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800827 ALOGI("%s: list is empty,fall back to default setting", __func__);
828 goto exit;
829 }
830 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
831 usb_get_best_match_for_channels(dev_list,
832 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530833 *ch,
834 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800835 usb_get_best_match_for_sample_rate(dev_list,
836 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530837 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800838 *sample_rate,
839 sample_rate);
840exit:
841 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530842 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800843 return is_usb_supported;
844}
845
Kuirong Wang1cad7142016-05-24 15:21:56 -0700846static int usb_get_sidetone_gain(struct usb_card_config *card_info)
847{
848 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
849 if (gain > card_info->usb_sidetone_vol_max)
850 gain = card_info->usb_sidetone_vol_max;
851 return gain;
852}
853
854void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
855 char *value, int len)
856{
857 int err;
858
859 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
860 value, len);
861 if (err >= 0) {
862 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
863 ALOGV("%s: sidetone gain(%s) decimal %d",
864 __func__, value, usb_sidetone_gain);
865 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
866 }
867 return;
868}
869
870int audio_extn_usb_enable_sidetone(int device, bool enable)
871{
872 int ret = -ENODEV;
873 struct listnode *node_i;
874 struct usb_card_config *card_info;
875 int i;
876 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
877 __func__, device, enable);
878
879 list_for_each(node_i, &usbmod->usb_card_conf_list) {
880 card_info = node_to_item(node_i, struct usb_card_config, list);
881 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
882 __func__, card_info->usb_device_type, card_info->usb_card);
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700883 if (usb_output_device(card_info->usb_device_type)) {
Kuirong Wang1cad7142016-05-24 15:21:56 -0700884 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
885 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
886 card_info->usb_snd_mixer,
887 usb_sidetone_enable_str[i]);
888 if (ctl)
889 mixer_ctl_set_value(ctl, 0, enable);
890 else
891 break;
892
893 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
894 ctl = mixer_get_ctl_by_name(
895 card_info->usb_snd_mixer,
896 usb_sidetone_volume_str[i]);
897 if (ctl == NULL)
898 ALOGV("%s: sidetone gain mixer command is not found",
899 __func__);
900 else if (enable)
901 mixer_ctl_set_value(ctl, 0,
902 usb_get_sidetone_gain(card_info));
903 }
904 ret = 0;
905 break;
906 }
907 }
908 }
909 return ret;
910}
911
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800912bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
913 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700914 unsigned int *ch,
915 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800916{
917 struct listnode *node_i;
918 struct usb_card_config *card_info;
919 bool is_usb_supported = false;
920
Kuirong Wang27152a12016-11-11 10:20:30 -0800921 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
922 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800923 list_for_each(node_i, &usbmod->usb_card_conf_list) {
924 card_info = node_to_item(node_i, struct usb_card_config, list);
925 ALOGI_IF(usb_audio_debug_enable,
926 "%s: card_dev_type (0x%x), card_no(%d)",
927 __func__, card_info->usb_device_type, card_info->usb_card);
928 /* Currently only apply the first playback sound card configuration */
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700929 if ((is_playback && usb_output_device(card_info->usb_device_type)) ||
930 (!is_playback && usb_input_device(card_info->usb_device_type))){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800931 is_usb_supported = usb_audio_backend_apply_policy(
932 &card_info->usb_device_conf_list,
933 bit_width,
934 sample_rate,
935 ch);
936 break;
937 }
938 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530939 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
940 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800941
942 return is_usb_supported;
943}
944
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700945int audio_extn_usb_get_max_channels(bool is_playback)
946{
947 struct listnode *node_i, *node_j;
948 struct usb_device_config *dev_info;
949 struct usb_card_config *card_info;
950 unsigned int max_ch = 1;
951 list_for_each(node_i, &usbmod->usb_card_conf_list) {
952 card_info = node_to_item(node_i, struct usb_card_config, list);
953 if (usb_output_device(card_info->usb_device_type) && !is_playback)
954 continue;
955 else if (usb_input_device(card_info->usb_device_type) && is_playback)
956 continue;
957
958 list_for_each(node_j, &card_info->usb_device_conf_list) {
959 dev_info = node_to_item(node_j, struct usb_device_config, list);
960 max_ch = _MAX(max_ch, dev_info->channels);
961 }
962 }
963
964 return max_ch;
965}
966
967int audio_extn_usb_get_max_bit_width(bool is_playback)
968{
969 struct listnode *node_i, *node_j;
970 struct usb_device_config *dev_info;
971 struct usb_card_config *card_info;
972 unsigned int max_bw = 16;
973 list_for_each(node_i, &usbmod->usb_card_conf_list) {
974 card_info = node_to_item(node_i, struct usb_card_config, list);
975 if (usb_output_device(card_info->usb_device_type) && !is_playback)
976 continue;
977 else if (usb_input_device(card_info->usb_device_type) && is_playback)
978 continue;
979
980 list_for_each(node_j, &card_info->usb_device_conf_list) {
981 dev_info = node_to_item(node_j, struct usb_device_config, list);
982 max_bw = _MAX(max_bw, dev_info->bit_width);
983 }
984 }
985
986 return max_bw;
987}
988
989int audio_extn_usb_get_sup_sample_rates(bool is_playback,
990 uint32_t *sample_rates,
991 uint32_t sample_rate_size)
992{
993 int type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
994
995 ALOGV("%s supported_sample_rates_mask 0x%x", __func__, supported_sample_rates_mask[type]);
996 uint32_t bm = supported_sample_rates_mask[type];
997 uint32_t tries = _MIN(sample_rate_size, (uint32_t)__builtin_popcount(bm));
998
999 int i = 0;
1000 while (tries--) {
1001 int idx = __builtin_ffs(bm) - 1;
1002 sample_rates[i++] = supported_sample_rates[idx];
1003 bm &= ~(1<<idx);
1004 }
1005
1006 return i;
1007}
1008
Ashish Jain3e37a702016-11-25 12:27:15 +05301009bool audio_extn_usb_is_capture_supported()
1010{
1011 if (usbmod == NULL) {
1012 ALOGE("%s: USB device object is NULL", __func__);
1013 return false;
1014 }
1015 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
1016 return usbmod->is_capture_supported;
1017}
1018
Zhou Song6f862822017-11-06 17:27:57 +08001019bool audio_extn_usb_is_tunnel_supported()
1020{
1021 return true;
1022}
1023
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001024void audio_extn_usb_add_device(audio_devices_t device, int card)
1025{
1026 struct usb_card_config *usb_card_info;
1027 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -08001028 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001029
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07001030 property_get("vendor.audio.usb.enable.debug", check_debug_enable, NULL);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001031 if (atoi(check_debug_enable)) {
1032 usb_audio_debug_enable = true;
1033 }
1034
1035 ALOGI_IF(usb_audio_debug_enable,
1036 "%s: parameters device(0x%x), card(%d)",
1037 __func__, device, card);
1038 if (usbmod == NULL) {
1039 ALOGE("%s: USB device object is NULL", __func__);
1040 goto exit;
1041 }
1042
1043 if (!(usb_valid_device(device)) || (card < 0)) {
1044 ALOGE("%s:device(0x%x), card(%d)",
1045 __func__, device, card);
1046 goto exit;
1047 }
1048
Kuirong Wang27152a12016-11-11 10:20:30 -08001049 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1050 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
1051 ALOGI_IF(usb_audio_debug_enable,
1052 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
1053 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
1054 /* If we have cached the capability */
1055 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
1056 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
1057 __func__, device, card);
1058 goto exit;
1059 }
1060 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001061 usb_card_info = calloc(1, sizeof(struct usb_card_config));
1062 if (usb_card_info == NULL) {
1063 ALOGE("%s: error unable to allocate memory",
1064 __func__);
1065 goto exit;
1066 }
1067 list_init(&usb_card_info->usb_device_conf_list);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001068 if (usb_output_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001069 if (!usb_get_device_pb_config(usb_card_info, card)){
1070 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001071 usb_card_info->usb_device_type = device;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001072 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001073 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1074 goto exit;
1075 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001076 } else if (usb_input_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001077 if (!usb_get_device_cap_config(usb_card_info, card)) {
1078 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001079 usb_card_info->usb_device_type = device;
Ashish Jain3e37a702016-11-25 12:27:15 +05301080 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001081 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1082 goto exit;
1083 }
1084 }
1085 /* free memory in error case */
1086 if (usb_card_info != NULL)
1087 free(usb_card_info);
1088exit:
1089 if (usb_audio_debug_enable)
1090 usb_print_active_device();
1091 return;
1092}
1093
1094void audio_extn_usb_remove_device(audio_devices_t device, int card)
1095{
1096 struct listnode *node_i, *temp_i;
1097 struct listnode *node_j, *temp_j;
1098 struct usb_device_config *dev_info;
1099 struct usb_card_config *card_info;
1100 unsigned int i;
1101
1102 ALOGV("%s: device(0x%x), card(%d)",
1103 __func__, device, card);
1104
1105 if (usbmod == NULL) {
1106 ALOGE("%s: USB device object is NULL", __func__);
1107 goto exit;
1108 }
1109
1110 if (!(usb_valid_device(device)) || (card < 0)) {
1111 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1112 __func__, device, card);
1113 goto exit;
1114 }
1115 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1116 card_info = node_to_item(node_i, struct usb_card_config, list);
1117 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1118 __func__, card_info->usb_device_type, card_info->usb_card);
1119 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1120 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1121 dev_info = node_to_item(node_j, struct usb_device_config, list);
1122 ALOGV("%s: bit-width(%d) channel(%d)",
1123 __func__, dev_info->bit_width, dev_info->channels);
1124 for (i = 0; i < dev_info->rate_size; i++)
1125 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1126
1127 list_remove(node_j);
1128 free(node_to_item(node_j, struct usb_device_config, list));
1129 }
1130 list_remove(node_i);
1131 free(node_to_item(node_i, struct usb_card_config, list));
1132 }
1133 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001134 if (audio_is_usb_in_device(device)) { // XXX not sure if we need to check for card
1135 usbmod->is_capture_supported = false;
1136 supported_sample_rates_mask[USB_CAPTURE] = 0;
1137 } else
1138 supported_sample_rates_mask[USB_PLAYBACK] = 0;
1139
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001140exit:
1141 if (usb_audio_debug_enable)
1142 usb_print_active_device();
1143
1144 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001145}
1146
Kevin Rocardfce19002017-08-07 19:21:36 -07001147bool audio_extn_usb_alive(int card) {
1148 char path[PATH_MAX] = {0};
1149 // snprintf should never fail
1150 (void) snprintf(path, sizeof(path), "/proc/asound/card%u/stream0", card);
1151 return access(path, F_OK) == 0;
1152}
1153
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001154void audio_extn_usb_init(void *adev)
1155{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001156 if (usbmod == NULL) {
1157 usbmod = calloc(1, sizeof(struct usb_module));
1158 if (usbmod == NULL) {
1159 ALOGE("%s: error unable to allocate memory", __func__);
1160 goto exit;
1161 }
1162 }
1163 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001164 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001165 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301166 usbmod->is_capture_supported = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001167exit:
1168 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001169}
1170
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001171void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001172{
1173 if (NULL != usbmod){
1174 free(usbmod);
1175 usbmod = NULL;
1176 }
1177}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001178#endif /*USB_HEADSET_ENABLED end*/