blob: 531c4b29a8574b099a17659bcf4bc639ab7108fb [file] [log] [blame]
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001/*
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002 * Copyright (c) 2013, 2016-2020, 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>
Aalique Grahame22e49102018-12-18 14:23:57 -080027#include <log/log.h>
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070028#include <cutils/str_parms.h>
29#include <sys/ioctl.h>
30#include <fcntl.h>
31#include <sys/stat.h>
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070032#include <system/audio.h>
33#include <tinyalsa/asoundlib.h>
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080034#include <audio_hw.h>
35#include <cutils/properties.h>
Kuirong Wang1cad7142016-05-24 15:21:56 -070036#include <ctype.h>
37#include <math.h>
Vinay Vermaaddfa4a2018-04-29 14:03:38 +053038#include <unistd.h>
Aalique Grahame22e49102018-12-18 14:23:57 -080039#include "audio_extn.h"
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -070040
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053041#ifdef DYNAMIC_LOG_ENABLED
42#include <log_xml_parser.h>
43#define LOG_MASK HAL_MOD_FILE_USB
44#include <log_utils.h>
45#endif
46
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080047#define USB_BUFF_SIZE 2048
48#define CHANNEL_NUMBER_STR "Channels: "
49#define PLAYBACK_PROFILE_STR "Playback:"
50#define CAPTURE_PROFILE_STR "Capture:"
Garmond Leung5fd0b552018-04-17 11:56:12 -070051#define DATA_PACKET_INTERVAL_STR "Data packet interval:"
Kuirong Wang1cad7142016-05-24 15:21:56 -070052#define USB_SIDETONE_GAIN_STR "usb_sidetone_gain"
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080053#define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A)))
54#define SAMPLE_RATE_8000 8000
55#define SAMPLE_RATE_11025 11025
Weiyin Jiangcba6f962018-03-18 11:52:05 +080056#define SAMPLE_RATE_192000 192000
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080057// Supported sample rates for USB
Carter Hsu32a62362018-10-15 15:01:42 -070058#define USBID_SIZE 16
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080059static uint32_t supported_sample_rates[] =
Haynes Mathew George484e8d22017-07-31 18:55:17 -070060 {384000, 352800, 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 22050, 16000, 11025, 8000};
61static uint32_t supported_sample_rates_mask[2];
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080062
63#define MAX_SAMPLE_RATE_SIZE sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
64
Garmond Leung5fd0b552018-04-17 11:56:12 -070065#define DEFAULT_SERVICE_INTERVAL_US 0
66
Haynes Mathew George484e8d22017-07-31 18:55:17 -070067#define _MAX(x, y) (((x) >= (y)) ? (x) : (y))
68#define _MIN(x, y) (((x) <= (y)) ? (x) : (y))
69
Garmond Leung5fd0b552018-04-17 11:56:12 -070070typedef enum usb_usecase_type{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080071 USB_PLAYBACK = 0,
72 USB_CAPTURE,
Garmond Leung5fd0b552018-04-17 11:56:12 -070073} usb_usecase_type_t;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080074
Kuirong Wang1cad7142016-05-24 15:21:56 -070075enum {
76 USB_SIDETONE_ENABLE_INDEX = 0,
77 USB_SIDETONE_VOLUME_INDEX,
78 USB_SIDETONE_MAX_INDEX,
79};
80
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080081struct usb_device_config {
82 struct listnode list;
83 unsigned int bit_width;
84 unsigned int channels;
85 unsigned int rate_size;
86 unsigned int rates[MAX_SAMPLE_RATE_SIZE];
Garmond Leung5fd0b552018-04-17 11:56:12 -070087 unsigned long service_interval_us;
88 usb_usecase_type_t type;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080089};
90
91struct usb_card_config {
92 struct listnode list;
93 audio_devices_t usb_device_type;
94 int usb_card;
95 struct listnode usb_device_conf_list;
Kuirong Wang1cad7142016-05-24 15:21:56 -070096 struct mixer *usb_snd_mixer;
97 int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
98 int usb_sidetone_vol_min;
99 int usb_sidetone_vol_max;
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700100 int endian;
Carter Hsu32a62362018-10-15 15:01:42 -0700101 char usbid[USBID_SIZE];
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800102};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700103
104struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800105 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700106 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700107 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +0530108 bool is_capture_supported;
Garmond Leung5fd0b552018-04-17 11:56:12 -0700109 bool usb_reconfig;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700110};
111
112static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800113static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700114static int usb_sidetone_gain = 0;
115
116static const char * const usb_sidetone_enable_str[] = {
117 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -0700118 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -0700119};
120
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800121static const char * const usb_sidetone_volume_str[] = {
122 "Sidetone Playback Volume",
123 "Mic Playback Volume",
124};
125
126static int usb_get_sidetone_gain(struct usb_card_config *card_info)
127{
128 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
129 if (gain > card_info->usb_sidetone_vol_max)
130 gain = card_info->usb_sidetone_vol_max;
131 return gain;
132}
133
134static void usb_get_sidetone_volume(struct usb_card_config *usb_card_info)
135{
136 struct mixer_ctl *ctl;
137 unsigned int index;
138
139 if (!audio_extn_usb_is_sidetone_volume_enabled())
140 return;
141
142 for (index = 0;
143 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
144 index++) {
145 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
146 usb_sidetone_volume_str[index]);
147 if (ctl) {
148 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
149 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
150 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
151 break;
152 }
153 }
154}
155
156static void usb_set_sidetone_volume(struct usb_card_config *usb_card_info,
157 bool enable, int index)
158{
159 struct mixer_ctl *ctl;
160
161 if (!audio_extn_usb_is_sidetone_volume_enabled())
162 return;
163
164 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
165 usb_sidetone_volume_str[index]);
166
167 if (ctl == NULL)
168 ALOGV("%s: sidetone gain mixer command is not found",
169 __func__);
170 else if (enable)
171 mixer_ctl_set_value(ctl, 0,
172 usb_get_sidetone_gain(usb_card_info));
173}
174
175
176
Kuirong Wang1cad7142016-05-24 15:21:56 -0700177static void usb_mixer_print_enum(struct mixer_ctl *ctl)
178{
179 unsigned int num_enums;
180 unsigned int i;
181 const char *string;
182
183 num_enums = mixer_ctl_get_num_enums(ctl);
184
185 for (i = 0; i < num_enums; i++) {
186 string = mixer_ctl_get_enum_string(ctl, i);
187 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
188 }
189}
190
191static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
192{
193 struct mixer_ctl *ctl;
194 enum mixer_ctl_type type;
195 unsigned int num_values;
196 unsigned int i;
197 int min, max;
198
199 if (isdigit(control[0]))
200 ctl = mixer_get_ctl(mixer, atoi(control));
201 else
202 ctl = mixer_get_ctl_by_name(mixer, control);
203
204 if (!ctl) {
205 fprintf(stderr, "Invalid mixer control\n");
206 return;
207 }
208
209 type = mixer_ctl_get_type(ctl);
210 num_values = mixer_ctl_get_num_values(ctl);
211
212 ALOGI("%s:", mixer_ctl_get_name(ctl));
213
214 for (i = 0; i < num_values; i++) {
215 switch (type) {
216 case MIXER_CTL_TYPE_INT:
217 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
218 break;
219 case MIXER_CTL_TYPE_BOOL:
220 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
221 break;
222 case MIXER_CTL_TYPE_ENUM:
223 usb_mixer_print_enum(ctl);
224 break;
225 case MIXER_CTL_TYPE_BYTE:
226 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
227 break;
228 default:
229 ALOGI(" unknown");
230 break;
231 }
232 }
233
234 if (type == MIXER_CTL_TYPE_INT) {
235 min = mixer_ctl_get_range_min(ctl);
236 max = mixer_ctl_get_range_max(ctl);
237 ALOGI(" (range %d->%d)", min, max);
238 }
239}
240
241static void usb_soundcard_list_controls(struct mixer *mixer)
242{
243 struct mixer_ctl *ctl;
244 const char *name, *type;
245 unsigned int num_ctls, num_values;
246 unsigned int i;
247
248 num_ctls = mixer_get_num_ctls(mixer);
249
250 ALOGI("Number of controls: %d\n", num_ctls);
251
252 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
253 for (i = 0; i < num_ctls; i++) {
254 ctl = mixer_get_ctl(mixer, i);
255 if (ctl != NULL) {
256 name = mixer_ctl_get_name(ctl);
257 type = mixer_ctl_get_type_string(ctl);
258 num_values = mixer_ctl_get_num_values(ctl);
259 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
260 if (name != NULL)
261 usb_soundcard_detail_control(mixer, name);
262 }
263 }
264}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700265
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800266static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
267 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700268{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800269 struct mixer_ctl *ctl;
270 unsigned int dev_token;
271 unsigned int pcm_device_number = 0;
272
273 /*
274 * usb_dev_token_id is 32 bit number and is defined as below:
275 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
276 */
277 dev_token = (card << 16 ) |
278 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
279
280 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
281 if (!ctl) {
282 ALOGE("%s: Could not get ctl for mixer cmd - %s",
283 __func__, dev_mixer_ctl_name);
284 return -EINVAL;
285 }
286 mixer_ctl_set_value(ctl, 0, dev_token);
287
288 return 0;
289}
290
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700291static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
292{
293 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
294 endian_mixer_ctl_name);
295 if (!ctl) {
296 ALOGE("%s: Could not get ctl for mixer cmd - %s",
297 __func__, endian_mixer_ctl_name);
298 return -EINVAL;
299 }
300
301 switch (endian) {
302 case 0:
303 case 1:
304 mixer_ctl_set_value(ctl, 0, endian);
305 break;
306 default:
307 ALOGW("%s: endianness(%d) not supported",
308 __func__, endian);
309 break;
310 }
311 return 0;
312}
313
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700314static int usb_get_sample_rates(int type, char *rates_str,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800315 struct usb_device_config *config)
316{
317 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700318 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800319 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700320
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800321 /* Sample rate string can be in any of the folloing two bit_widthes:
322 * Rates: 8000 - 48000 (continuous)
323 * Rates: 8000, 44100, 48000
324 * Support both the bit_widths
325 */
326 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700327 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
328 if (next_sr_string == NULL) {
329 ALOGE("%s: could not find min rates string", __func__);
330 return -EINVAL;
331 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800332 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700333 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700334 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800335 if (next_sr_string == NULL) {
336 ALOGE("%s: could not find max rates string", __func__);
337 return -EINVAL;
338 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700339 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800340
Kuirong Wang591a98a2016-06-27 12:41:41 -0700341 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800342 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700343 supported_sample_rates[i] <= max_sr) {
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800344 // FIXME: we don't support >192KHz in recording path for now
345 if ((supported_sample_rates[i] > SAMPLE_RATE_192000) &&
346 (type == USB_CAPTURE))
347 continue;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800348 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700349 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700350 ALOGI_IF(usb_audio_debug_enable,
351 "%s: continuous sample rate supported_sample_rates[%d] %d",
352 __func__, i, supported_sample_rates[i]);
353 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800354 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700355 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800356 do {
357 sr = (uint32_t)atoi(next_sr_string);
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800358 // FIXME: we don't support >192KHz in recording path for now
359 if ((sr > SAMPLE_RATE_192000) && (type == USB_CAPTURE)) {
360 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
361 continue;
362 }
363
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800364 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
365 if (supported_sample_rates[i] == sr) {
366 ALOGI_IF(usb_audio_debug_enable,
367 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
368 __func__, sr, i, supported_sample_rates[i]);
369 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700370 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800371 }
372 }
373 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
374 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700375 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800376 config->rate_size = sr_size;
377 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700378}
379
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800380static int get_usb_service_interval(const char *interval_str_start,
Garmond Leung5fd0b552018-04-17 11:56:12 -0700381 struct usb_device_config *usb_device_info)
382{
383 unsigned long interval = 0;
384 char time_unit[8] = {0};
385 int multiplier = 0;
386
387 char *eol = strchr(interval_str_start, '\n');
388 if (!eol) {
389 ALOGE("%s: No EOL found", __func__);
390 return -1;
391 }
392 char *tmp = (char *)calloc(1, eol-interval_str_start+1);
393 if (!tmp) {
394 ALOGE("%s: failed to allocate tmp", __func__);
395 return -1;
396 }
397 memcpy(tmp, interval_str_start, eol-interval_str_start);
Zhou Song8c05a3c2019-06-18 22:57:11 +0800398 tmp[eol-interval_str_start] = '\0';
Garmond Leung5fd0b552018-04-17 11:56:12 -0700399 sscanf(tmp, "%lu %2s", &interval, &time_unit[0]);
400 if (!strcmp(time_unit, "us")) {
401 multiplier = 1;
402 } else if (!strcmp(time_unit, "ms")) {
403 multiplier = 1000;
404 } else if (!strcmp(time_unit, "s")) {
405 multiplier = 1000000;
406 } else {
407 ALOGE("%s: unknown time_unit %s, assume default", __func__, time_unit);
408 interval = DEFAULT_SERVICE_INTERVAL_US;
409 multiplier = 1;
410 }
411 interval *= multiplier;
412 ALOGD("%s: set service_interval_us %lu", __func__, interval);
413 usb_device_info->service_interval_us = interval;
414 free(tmp);
415 return 0;
416}
417
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800418static int usb_get_capability(int type,
419 struct usb_card_config *usb_card_info,
420 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700421{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700422 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800423 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800424 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700425 char *str_start = NULL;
426 char *str_end = NULL;
427 char *channel_start = NULL;
428 char *bit_width_start = NULL;
429 char *rates_str_start = NULL;
430 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700431 char *read_buf = NULL;
432 char *rates_str = NULL;
Garmond Leung5fd0b552018-04-17 11:56:12 -0700433 char *interval_str_start = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700434 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700435 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800436 char *bit_width_str = NULL;
437 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700438 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700439
Kuirong Wange9894162016-08-26 15:16:39 -0700440 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800441 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
442 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
443
Kuirong Wange9894162016-08-26 15:16:39 -0700444 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800445 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700446 if(ret < 0) {
447 ALOGE("%s: failed on snprintf (%d) to path %s\n",
448 __func__, ret, path);
449 goto done;
450 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700451
452 fd = open(path, O_RDONLY);
453 if (fd <0) {
454 ALOGE("%s: error failed to open config file %s error: %d\n",
455 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700456 ret = -EINVAL;
457 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700458 }
459
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800460 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700461
462 if (!read_buf) {
463 ALOGE("Failed to create read_buf");
464 ret = -ENOMEM;
465 goto done;
466 }
467
Kuirong Wange9894162016-08-26 15:16:39 -0700468 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
469 ALOGE("file read error\n");
470 goto done;
471 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800472 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
473 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700474 if (str_start == NULL) {
475 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800476 __func__, ((type == USB_PLAYBACK) ?
477 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700478 ret = -EINVAL;
479 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 }
Kuirong Wange9894162016-08-26 15:16:39 -0700481 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
482 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
483 if (str_end > str_start)
484 check = true;
485
486 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700487
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800488 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700489 str_start = strstr(str_start, "Altset");
490 if ((str_start == NULL) || (check && (str_start >= str_end))) {
491 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800492 break;
493 }
Kuirong Wange9894162016-08-26 15:16:39 -0700494 ALOGV("%s: remaining string %s\n", __func__, str_start);
495 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800496 usb_device_info = calloc(1, sizeof(struct usb_device_config));
497 if (usb_device_info == NULL) {
498 ALOGE("%s: error unable to allocate memory",
499 __func__);
500 ret = -ENOMEM;
501 break;
502 }
Garmond Leung5fd0b552018-04-17 11:56:12 -0700503 usb_device_info->type = type;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800504 /* Bit bit_width parsing */
505 bit_width_start = strstr(str_start, "Format: ");
506 if (bit_width_start == NULL) {
507 ALOGI("%s: Could not find bit_width string", __func__);
508 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700509 continue;
510 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800511 target = strchr(bit_width_start, '\n');
512 if (target == NULL) {
513 ALOGI("%s:end of line not found", __func__);
514 free(usb_device_info);
515 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700516 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800517 size = target - bit_width_start;
518 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
519 ALOGE("%s: unable to allocate memory to hold bit width strings",
520 __func__);
521 ret = -EINVAL;
522 free(usb_device_info);
523 break;
524 }
525 memcpy(bit_width_str, bit_width_start, size);
526 bit_width_str[size] = '\0';
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700527
528 const char * formats[] = { "S32", "S24_3", "S24", "S16" };
529 const int bit_width[] = { 32, 24, 24, 16};
530 for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
531 const char * s = strstr(bit_width_str, formats[i]);
532 if (s) {
533 usb_device_info->bit_width = bit_width[i];
534 usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
535 break;
536 }
537 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800538
539 if (bit_width_str)
540 free(bit_width_str);
541
542 /* channels parsing */
543 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
544 if (channel_start == NULL) {
545 ALOGI("%s: could not find Channels string", __func__);
546 free(usb_device_info);
547 continue;
548 }
549 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
550 usb_device_info->channels = channels_no;
551
552 /* Sample rates parsing */
553 rates_str_start = strstr(str_start, "Rates: ");
554 if (rates_str_start == NULL) {
555 ALOGI("%s: cant find rates string", __func__);
556 free(usb_device_info);
557 continue;
558 }
559 target = strchr(rates_str_start, '\n');
560 if (target == NULL) {
561 ALOGI("%s: end of line not found", __func__);
562 free(usb_device_info);
563 continue;
564 }
565 size = target - rates_str_start;
566 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
567 ALOGE("%s: unable to allocate memory to hold sample rate strings",
568 __func__);
569 ret = -EINVAL;
570 free(usb_device_info);
571 break;
572 }
573 memcpy(rates_str, rates_str_start, size);
574 rates_str[size] = '\0';
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700575 ret = usb_get_sample_rates(type, rates_str, usb_device_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800576 if (rates_str)
577 free(rates_str);
578 if (ret < 0) {
579 ALOGI("%s: error unable to get sample rate values",
580 __func__);
581 free(usb_device_info);
582 continue;
583 }
Garmond Leung5fd0b552018-04-17 11:56:12 -0700584 // Data packet interval is an optional field.
585 // Assume 0ms interval if this cannot be read
586 // LPASS USB and HLOS USB will figure out the default to use
587 usb_device_info->service_interval_us = DEFAULT_SERVICE_INTERVAL_US;
588 interval_str_start = strstr(str_start, DATA_PACKET_INTERVAL_STR);
589 if (interval_str_start != NULL) {
590 interval_str_start += strlen(DATA_PACKET_INTERVAL_STR);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800591 ret = get_usb_service_interval(interval_str_start, usb_device_info);
Garmond Leung5fd0b552018-04-17 11:56:12 -0700592 if (ret < 0) {
593 ALOGE("%s: error unable to get service interval, assume default",
594 __func__);
595 }
596 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800597 /* Add to list if every field is valid */
598 list_add_tail(&usb_card_info->usb_device_conf_list,
599 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700600 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700601
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700602done:
603 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700604 if (read_buf) free(read_buf);
605 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700606}
607
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800608static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
609 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700610{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800611 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700612
613 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800614 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
615 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700616 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800617 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700618 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800619 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700620 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800621exit:
622
623 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700624}
625
Carter Hsu32a62362018-10-15 15:01:42 -0700626static int usb_get_usbid(struct usb_card_config *usb_card_info,
627 int card)
628{
629 int32_t fd=-1;
630 char path[128];
631 int ret = 0;
Weiyin Jiang0d985872019-06-13 15:47:21 +0800632 char *saveptr = NULL;
Carter Hsu32a62362018-10-15 15:01:42 -0700633
634 memset(usb_card_info->usbid, 0, sizeof(usb_card_info->usbid));
635
636 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/usbid",
637 card);
638
639 if (ret < 0) {
640 ALOGE("%s: failed on snprintf (%d) to path %s\n",
641 __func__, ret, path);
642 goto done;
643 }
644
645 fd = open(path, O_RDONLY);
646 if (fd < 0) {
647 ALOGE("%s: error failed to open file %s error: %d\n",
648 __func__, path, errno);
649 ret = -EINVAL;
650 goto done;
651 }
652
653 if (read(fd, usb_card_info->usbid, USBID_SIZE - 1) < 0) {
654 ALOGE("file read error\n");
655 ret = -EINVAL;
656 usb_card_info->usbid[0] = '\0';
657 goto done;
658 }
659
Weiyin Jiang0d985872019-06-13 15:47:21 +0800660 strtok_r(usb_card_info->usbid, "\n", &saveptr);
Carter Hsu32a62362018-10-15 15:01:42 -0700661
662done:
663 if (fd >= 0)
664 close(fd);
665
666 return ret;
667}
668
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800669static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
670 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700671{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800672 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700673
674 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800675 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
676 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700677 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800678 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700679 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800680 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700681 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700682
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800683exit:
684 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700685}
686
Kuirong Wang1cad7142016-05-24 15:21:56 -0700687static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
688{
689 struct mixer_ctl *ctl;
690 unsigned int index;
691
692 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
693 usb_card_info->usb_sidetone_index[index] = -1;
694
695 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
696 for (index = 0;
697 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
698 index++) {
699 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
700 usb_sidetone_enable_str[index]);
701 if (ctl) {
702 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
703 /* Disable device sidetone by default */
704 mixer_ctl_set_value(ctl, 0, false);
Aalique Grahame22e49102018-12-18 14:23:57 -0800705 ALOGV("%s: sidetone mixer Control found(%s) ... disabling by default",
706 __func__, usb_sidetone_enable_str[index]);
Kuirong Wang1cad7142016-05-24 15:21:56 -0700707 break;
708 }
709 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800710
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800711 usb_get_sidetone_volume(usb_card_info);
Kuirong Wang1cad7142016-05-24 15:21:56 -0700712
713 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
714 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
715
716 return;
717}
718
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700719static inline bool usb_output_device(audio_devices_t device) {
720 // ignore accessory for now
721 if (device == AUDIO_DEVICE_OUT_USB_ACCESSORY)
722 return false;
723 return audio_is_usb_out_device(device);
724}
725
726static inline bool usb_input_device(audio_devices_t device) {
727 // ignore accessory for now
728 if (device == AUDIO_DEVICE_IN_USB_ACCESSORY)
729 return false;
730 return audio_is_usb_in_device(device);
731}
732
733static bool usb_valid_device(audio_devices_t device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700734{
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700735 return usb_output_device(device) ||
736 usb_input_device(device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800737}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700738
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800739static void usb_print_active_device(void){
740 struct listnode *node_i, *node_j;
741 struct usb_device_config *dev_info;
742 struct usb_card_config *card_info;
743 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700744
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800745 ALOGI("%s", __func__);
746 list_for_each(node_i, &usbmod->usb_card_conf_list) {
747 card_info = node_to_item(node_i, struct usb_card_config, list);
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700748 ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
749 __func__, card_info->usb_device_type,
750 card_info->usb_card, card_info->endian ? "BE" : "LE");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800751 list_for_each(node_j, &card_info->usb_device_conf_list) {
752 dev_info = node_to_item(node_j, struct usb_device_config, list);
753 ALOGI("%s: bit-width(%d) channel(%d)",
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700754 __func__, dev_info->bit_width, dev_info->channels);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800755 for (i = 0; i < dev_info->rate_size; i++)
756 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
757 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700758 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800759}
760
761static bool usb_get_best_match_for_bit_width(
762 struct listnode *dev_list,
763 unsigned int stream_bit_width,
764 unsigned int *bit_width)
765{
766 struct listnode *node_i;
767 struct usb_device_config *dev_info;
768 unsigned int candidate = 0;
769
770 list_for_each(node_i, dev_list) {
771 dev_info = node_to_item(node_i, struct usb_device_config, list);
772 ALOGI_IF(usb_audio_debug_enable,
773 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
774 __func__, dev_info->bit_width,
775 stream_bit_width, candidate);
776 if (dev_info->bit_width == stream_bit_width) {
777 *bit_width = dev_info->bit_width;
778 ALOGV("%s: Found match bit-width (%d)",
779 __func__, dev_info->bit_width);
780 goto exit;
781 } else if (candidate == 0) {
782 candidate = dev_info->bit_width;
783 }
784 /*
785 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
786 * higher bit width 32 is picked up instead of 16-bit
787 */
788 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
789 ABS_SUB(stream_bit_width, candidate)) {
790 candidate = dev_info->bit_width;
791 }
792 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
793 ABS_SUB(stream_bit_width, candidate)) &&
794 (dev_info->bit_width > candidate)) {
795 candidate = dev_info->bit_width;
796 }
797 }
798 ALOGV("%s: No match found, use the best candidate bw(%d)",
799 __func__, candidate);
800 *bit_width = candidate;
801exit:
802 return true;
803}
804
805static bool usb_get_best_match_for_channels(
806 struct listnode *dev_list,
807 unsigned int bit_width,
808 unsigned int stream_ch,
809 unsigned int *ch)
810{
811 struct listnode *node_i;
812 struct usb_device_config *dev_info;
813 unsigned int candidate = 0;
814
815 list_for_each(node_i, dev_list) {
816 dev_info = node_to_item(node_i, struct usb_device_config, list);
817 ALOGI_IF(usb_audio_debug_enable,
818 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
819 __func__, dev_info->channels, dev_info->bit_width,
820 stream_ch, bit_width, candidate);
821 if (dev_info->bit_width != bit_width)
822 continue;
823 if (dev_info->channels== stream_ch) {
824 *ch = dev_info->channels;
825 ALOGV("%s: Found match channels (%d)",
826 __func__, dev_info->channels);
827 goto exit;
828 } else if (candidate == 0)
829 candidate = dev_info->channels;
830 /*
831 * If stream channel is 4, USB supports both 3 and 5, then
832 * higher channel 5 is picked up instead of 3
833 */
834 else if (ABS_SUB(stream_ch, dev_info->channels) <
835 ABS_SUB(stream_ch, candidate)) {
836 candidate = dev_info->channels;
837 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
838 ABS_SUB(stream_ch, candidate)) &&
839 (dev_info->channels > candidate)) {
840 candidate = dev_info->channels;
841 }
842 }
843 ALOGV("%s: No match found, use the best candidate ch(%d)",
844 __func__, candidate);
845 *ch = candidate;
846exit:
847 return true;
848
849}
850
851static bool usb_sample_rate_multiple(
852 unsigned int stream_sample_rate,
853 unsigned int base)
854{
855 return (((stream_sample_rate / base) * base) == stream_sample_rate);
856}
857
858static bool usb_find_sample_rate_candidate(unsigned int base,
859 unsigned stream_rate,
860 unsigned int usb_rate,
861 unsigned int cur_candidate,
862 unsigned int *update_candidate)
863{
864 /* For sample rate, we should consider fracational sample rate as high priority.
865 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
866 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
867 */
868 if (!usb_sample_rate_multiple(cur_candidate, base) &&
869 usb_sample_rate_multiple(usb_rate, base)) {
870 *update_candidate = usb_rate;
871 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
872 usb_sample_rate_multiple(usb_rate, base)) {
873 if (ABS_SUB(stream_rate, usb_rate) <
874 ABS_SUB(stream_rate, cur_candidate)) {
875 *update_candidate = usb_rate;
876 } else if ((ABS_SUB(stream_rate, usb_rate) ==
877 ABS_SUB(stream_rate, cur_candidate)) &&
878 (usb_rate > cur_candidate)) {
879 *update_candidate = usb_rate;
880 }
881 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
882 !usb_sample_rate_multiple(usb_rate, base)) {
883 if (ABS_SUB(stream_rate, usb_rate) <
884 ABS_SUB(stream_rate, cur_candidate)) {
885 *update_candidate = usb_rate;
886 } else if ((ABS_SUB(stream_rate, usb_rate) ==
887 ABS_SUB(stream_rate, cur_candidate)) &&
888 (usb_rate > cur_candidate)) {
889 *update_candidate = usb_rate;
890 }
891 }
892 return true;
893}
894
895static bool usb_get_best_match_for_sample_rate(
896 struct listnode *dev_list,
897 unsigned int bit_width,
898 unsigned int ch,
899 unsigned int stream_sample_rate,
Garmond Leung5fd0b552018-04-17 11:56:12 -0700900 unsigned int *sr,
901 unsigned int service_interval,
902 bool do_service_interval_check)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800903{
904 struct listnode *node_i;
905 struct usb_device_config *dev_info;
906 unsigned int candidate = 48000;
907 unsigned int base = SAMPLE_RATE_8000;
908 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
909 unsigned int i;
910
911 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
912 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
913
914 list_for_each(node_i, dev_list) {
915 dev_info = node_to_item(node_i, struct usb_device_config, list);
916 ALOGI_IF(usb_audio_debug_enable,
917 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
918 __func__, dev_info->channels, dev_info->bit_width,
919 ch, bit_width, stream_sample_rate, candidate);
Garmond Leung5fd0b552018-04-17 11:56:12 -0700920
921 if ((dev_info->bit_width != bit_width) ||
922 (dev_info->channels != ch) ||
923 (do_service_interval_check && (dev_info->service_interval_us !=
924 service_interval)))
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800925 continue;
926
927 candidate = 0;
928 for (i = 0; i < dev_info->rate_size; i++) {
929 ALOGI_IF(usb_audio_debug_enable,
930 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
931 __func__, dev_info->channels,
932 dev_info->bit_width, dev_info->rates[i],
933 ch, bit_width, stream_sample_rate, candidate);
934 if (stream_sample_rate == dev_info->rates[i]) {
935 *sr = dev_info->rates[i];
936 ALOGV("%s: Found match sample rate (%d)",
937 __func__, dev_info->rates[i]);
938 goto exit;
939 } else if (candidate == 0) {
940 candidate = dev_info->rates[i];
941 /*
942 * For sample rate, we should consider fracational sample rate as high priority.
943 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
944 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
945 */
946 } else if (multiple_8k) {
947 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
948 stream_sample_rate,
949 dev_info->rates[i],
950 candidate,
951 &candidate);
952 } else {
953 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
954 stream_sample_rate,
955 dev_info->rates[i],
956 candidate,
957 &candidate);
958 }
959 }
960 }
961 ALOGV("%s: No match found, use the best candidate sr(%d)",
962 __func__, candidate);
963 *sr = candidate;
964exit:
965 return true;
966}
967
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800968static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
969 unsigned int *bit_width,
970 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530971 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800972{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800973 bool is_usb_supported = true;
974
975 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530976 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800977 if (list_empty(dev_list)) {
978 *sample_rate = 48000;
979 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530980 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800981 ALOGI("%s: list is empty,fall back to default setting", __func__);
982 goto exit;
983 }
984 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
985 usb_get_best_match_for_channels(dev_list,
986 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530987 *ch,
988 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800989 usb_get_best_match_for_sample_rate(dev_list,
990 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530991 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800992 *sample_rate,
Garmond Leung5fd0b552018-04-17 11:56:12 -0700993 sample_rate,
994 0 /*service int*/,
995 false /*do service int check*/);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800996exit:
997 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530998 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800999 return is_usb_supported;
1000}
1001
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001002void usb_set_sidetone_gain(struct str_parms *parms,
Kuirong Wang1cad7142016-05-24 15:21:56 -07001003 char *value, int len)
1004{
1005 int err;
1006
1007 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
1008 value, len);
1009 if (err >= 0) {
1010 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
1011 ALOGV("%s: sidetone gain(%s) decimal %d",
1012 __func__, value, usb_sidetone_gain);
1013 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
1014 }
1015 return;
1016}
1017
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001018int usb_enable_sidetone(int device, bool enable)
Kuirong Wang1cad7142016-05-24 15:21:56 -07001019{
1020 int ret = -ENODEV;
1021 struct listnode *node_i;
1022 struct usb_card_config *card_info;
1023 int i;
1024 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
1025 __func__, device, enable);
1026
1027 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1028 card_info = node_to_item(node_i, struct usb_card_config, list);
1029 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1030 __func__, card_info->usb_device_type, card_info->usb_card);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001031 if (usb_output_device(card_info->usb_device_type)) {
Kuirong Wang1cad7142016-05-24 15:21:56 -07001032 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
1033 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
1034 card_info->usb_snd_mixer,
1035 usb_sidetone_enable_str[i]);
1036 if (ctl)
1037 mixer_ctl_set_value(ctl, 0, enable);
1038 else
1039 break;
1040
1041 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001042 usb_set_sidetone_volume(card_info, enable, i);
Kuirong Wang1cad7142016-05-24 15:21:56 -07001043 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001044
Kuirong Wang1cad7142016-05-24 15:21:56 -07001045 ret = 0;
1046 break;
1047 }
1048 }
1049 }
1050 return ret;
1051}
1052
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001053bool usb_is_config_supported(unsigned int *bit_width,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001054 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -07001055 unsigned int *ch,
1056 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001057{
1058 struct listnode *node_i;
1059 struct usb_card_config *card_info;
1060 bool is_usb_supported = false;
1061
Kuirong Wang27152a12016-11-11 10:20:30 -08001062 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
1063 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001064 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1065 card_info = node_to_item(node_i, struct usb_card_config, list);
1066 ALOGI_IF(usb_audio_debug_enable,
1067 "%s: card_dev_type (0x%x), card_no(%d)",
1068 __func__, card_info->usb_device_type, card_info->usb_card);
1069 /* Currently only apply the first playback sound card configuration */
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001070 if ((is_playback && usb_output_device(card_info->usb_device_type)) ||
1071 (!is_playback && usb_input_device(card_info->usb_device_type))){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001072 is_usb_supported = usb_audio_backend_apply_policy(
1073 &card_info->usb_device_conf_list,
1074 bit_width,
1075 sample_rate,
1076 ch);
1077 break;
1078 }
1079 }
Ashish Jainb26edfb2016-08-25 00:10:11 +05301080 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
1081 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001082
1083 return is_usb_supported;
1084}
1085
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001086int usb_get_max_channels(bool is_playback)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001087{
1088 struct listnode *node_i, *node_j;
1089 struct usb_device_config *dev_info;
1090 struct usb_card_config *card_info;
1091 unsigned int max_ch = 1;
1092 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1093 card_info = node_to_item(node_i, struct usb_card_config, list);
1094 if (usb_output_device(card_info->usb_device_type) && !is_playback)
1095 continue;
1096 else if (usb_input_device(card_info->usb_device_type) && is_playback)
1097 continue;
1098
1099 list_for_each(node_j, &card_info->usb_device_conf_list) {
1100 dev_info = node_to_item(node_j, struct usb_device_config, list);
1101 max_ch = _MAX(max_ch, dev_info->channels);
1102 }
1103 }
1104
1105 return max_ch;
1106}
1107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001108int usb_get_max_bit_width(bool is_playback)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001109{
1110 struct listnode *node_i, *node_j;
1111 struct usb_device_config *dev_info;
1112 struct usb_card_config *card_info;
1113 unsigned int max_bw = 16;
1114 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1115 card_info = node_to_item(node_i, struct usb_card_config, list);
1116 if (usb_output_device(card_info->usb_device_type) && !is_playback)
1117 continue;
1118 else if (usb_input_device(card_info->usb_device_type) && is_playback)
1119 continue;
1120
1121 list_for_each(node_j, &card_info->usb_device_conf_list) {
1122 dev_info = node_to_item(node_j, struct usb_device_config, list);
1123 max_bw = _MAX(max_bw, dev_info->bit_width);
1124 }
1125 }
1126
1127 return max_bw;
1128}
1129
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001130int usb_get_sup_sample_rates(bool is_playback,
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001131 uint32_t *sample_rates,
1132 uint32_t sample_rate_size)
1133{
1134 int type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
1135
1136 ALOGV("%s supported_sample_rates_mask 0x%x", __func__, supported_sample_rates_mask[type]);
1137 uint32_t bm = supported_sample_rates_mask[type];
1138 uint32_t tries = _MIN(sample_rate_size, (uint32_t)__builtin_popcount(bm));
1139
1140 int i = 0;
Vikram Panduranga5c51bff2019-09-13 16:43:44 -07001141 while (tries) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001142 int idx = __builtin_ffs(bm) - 1;
1143 sample_rates[i++] = supported_sample_rates[idx];
1144 bm &= ~(1<<idx);
Vikram Panduranga5c51bff2019-09-13 16:43:44 -07001145 tries--;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001146 }
1147
1148 return i;
1149}
1150
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001151bool usb_is_capture_supported()
Ashish Jain3e37a702016-11-25 12:27:15 +05301152{
1153 if (usbmod == NULL) {
1154 ALOGE("%s: USB device object is NULL", __func__);
1155 return false;
1156 }
1157 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
1158 return usbmod->is_capture_supported;
1159}
1160
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001161bool usb_is_tunnel_supported()
Zhou Song6f862822017-11-06 17:27:57 +08001162{
1163 return true;
1164}
1165
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001166void usb_add_device(audio_devices_t device, int card)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001167{
1168 struct usb_card_config *usb_card_info;
1169 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -08001170 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001171
Aalique Grahame22e49102018-12-18 14:23:57 -08001172 if ((property_get("vendor.audio.usb.enable.debug",
1173 check_debug_enable, NULL) > 0) ||
1174 (property_get("audio.usb.enable.debug",
1175 check_debug_enable, NULL) > 0)) {
1176 if (atoi(check_debug_enable))
1177 usb_audio_debug_enable = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001178 }
1179
1180 ALOGI_IF(usb_audio_debug_enable,
1181 "%s: parameters device(0x%x), card(%d)",
1182 __func__, device, card);
1183 if (usbmod == NULL) {
1184 ALOGE("%s: USB device object is NULL", __func__);
1185 goto exit;
1186 }
1187
1188 if (!(usb_valid_device(device)) || (card < 0)) {
1189 ALOGE("%s:device(0x%x), card(%d)",
1190 __func__, device, card);
1191 goto exit;
1192 }
1193
Kuirong Wang27152a12016-11-11 10:20:30 -08001194 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1195 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
1196 ALOGI_IF(usb_audio_debug_enable,
1197 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
1198 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
1199 /* If we have cached the capability */
1200 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
1201 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
1202 __func__, device, card);
1203 goto exit;
1204 }
1205 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001206 usb_card_info = calloc(1, sizeof(struct usb_card_config));
1207 if (usb_card_info == NULL) {
1208 ALOGE("%s: error unable to allocate memory",
1209 __func__);
1210 goto exit;
1211 }
1212 list_init(&usb_card_info->usb_device_conf_list);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001213 if (usb_output_device(device)) {
Carter Hsu32a62362018-10-15 15:01:42 -07001214 if (usb_get_usbid(usb_card_info, card) < 0) {
1215 ALOGE("parse card %d usbid fail", card);
1216 }
1217
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001218 if (!usb_get_device_pb_config(usb_card_info, card)){
1219 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001220 usb_card_info->usb_device_type = device;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001221 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001222 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1223 goto exit;
1224 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001225 } else if (usb_input_device(device)) {
Carter Hsu32a62362018-10-15 15:01:42 -07001226 if (usb_get_usbid(usb_card_info, card) < 0) {
1227 ALOGE("parse card %d usbid fail", card);
1228 }
1229
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001230 if (!usb_get_device_cap_config(usb_card_info, card)) {
1231 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001232 usb_card_info->usb_device_type = device;
Ashish Jain3e37a702016-11-25 12:27:15 +05301233 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001234 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1235 goto exit;
1236 }
1237 }
1238 /* free memory in error case */
1239 if (usb_card_info != NULL)
1240 free(usb_card_info);
1241exit:
1242 if (usb_audio_debug_enable)
1243 usb_print_active_device();
1244 return;
1245}
1246
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001247void usb_remove_device(audio_devices_t device, int card)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001248{
1249 struct listnode *node_i, *temp_i;
1250 struct listnode *node_j, *temp_j;
1251 struct usb_device_config *dev_info;
1252 struct usb_card_config *card_info;
1253 unsigned int i;
1254
1255 ALOGV("%s: device(0x%x), card(%d)",
1256 __func__, device, card);
1257
1258 if (usbmod == NULL) {
1259 ALOGE("%s: USB device object is NULL", __func__);
1260 goto exit;
1261 }
1262
1263 if (!(usb_valid_device(device)) || (card < 0)) {
1264 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1265 __func__, device, card);
1266 goto exit;
1267 }
1268 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1269 card_info = node_to_item(node_i, struct usb_card_config, list);
1270 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1271 __func__, card_info->usb_device_type, card_info->usb_card);
1272 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1273 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1274 dev_info = node_to_item(node_j, struct usb_device_config, list);
1275 ALOGV("%s: bit-width(%d) channel(%d)",
1276 __func__, dev_info->bit_width, dev_info->channels);
1277 for (i = 0; i < dev_info->rate_size; i++)
1278 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1279
1280 list_remove(node_j);
1281 free(node_to_item(node_j, struct usb_device_config, list));
1282 }
1283 list_remove(node_i);
1284 free(node_to_item(node_i, struct usb_card_config, list));
1285 }
1286 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001287 if (audio_is_usb_in_device(device)) { // XXX not sure if we need to check for card
1288 usbmod->is_capture_supported = false;
1289 supported_sample_rates_mask[USB_CAPTURE] = 0;
1290 } else
1291 supported_sample_rates_mask[USB_PLAYBACK] = 0;
1292
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001293exit:
1294 if (usb_audio_debug_enable)
1295 usb_print_active_device();
1296
1297 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001298}
1299
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001300bool usb_alive(int card) {
Kevin Rocardfce19002017-08-07 19:21:36 -07001301 char path[PATH_MAX] = {0};
1302 // snprintf should never fail
1303 (void) snprintf(path, sizeof(path), "/proc/asound/card%u/stream0", card);
1304 return access(path, F_OK) == 0;
1305}
1306
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001307unsigned long usb_find_service_interval(bool min,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001308 bool playback) {
1309 struct usb_card_config *card_info = NULL;
1310 struct usb_device_config *dev_info = NULL;
1311 struct listnode *node_i = NULL;
1312 struct listnode *node_j = NULL;
Aalique Grahame22e49102018-12-18 14:23:57 -08001313 unsigned long interval_us = min ? ULONG_MAX : 0;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001314 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1315 card_info = node_to_item(node_i, struct usb_card_config, list);
1316 list_for_each(node_j, &card_info->usb_device_conf_list) {
1317 dev_info = node_to_item(node_j, struct usb_device_config, list);
1318 bool match = (playback && (dev_info->type == USB_PLAYBACK)) ||
1319 (!playback && (dev_info->type == USB_CAPTURE));
1320 if (match) {
1321 interval_us = min ?
1322 _MIN(interval_us, dev_info->service_interval_us) :
1323 _MAX(interval_us, dev_info->service_interval_us);
1324 }
1325 }
1326 break;
1327 }
1328 return interval_us;
1329}
1330
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001331int usb_altset_for_service_interval(bool playback,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001332 unsigned long service_interval,
1333 uint32_t *bit_width,
1334 uint32_t *sample_rate,
1335 uint32_t *channels)
1336{
1337 struct usb_card_config *card_info = NULL;
Aalique Grahame22e49102018-12-18 14:23:57 -08001338 struct usb_device_config *dev_info = NULL;
1339 struct listnode *node_i = NULL;
1340 struct listnode *node_j = NULL;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001341 uint32_t bw = 0;
1342 uint32_t ch = 0;
1343 uint32_t sr = 0;
1344
1345 if (service_interval == 0)
1346 return 0;
1347 /* not a valid service interval to search for */
1348
1349#define FIND_BEST_MATCH(local_var, field, cond) \
1350 list_for_each(node_i, &usbmod->usb_card_conf_list) { \
1351 /* Currently only apply the first playback sound card configuration */ \
1352 card_info = node_to_item(node_i, struct usb_card_config, list); \
1353 list_for_each(node_j, &card_info->usb_device_conf_list) { \
1354 dev_info = node_to_item(node_j, struct usb_device_config, list); \
1355 bool match = (playback && (dev_info->type == USB_PLAYBACK)) || \
1356 (!playback && (dev_info->type == USB_CAPTURE)); \
1357 if (match && (cond)) { \
Garmond Leung003d9ea2018-08-14 17:05:08 -07001358 if (dev_info->field == *field) { \
1359 local_var = dev_info->field; \
1360 break; \
1361 } \
Garmond Leung5fd0b552018-04-17 11:56:12 -07001362 local_var = _MAX(local_var, dev_info->field); \
1363 } \
1364 } \
1365 break; \
1366 }
1367
1368 FIND_BEST_MATCH(bw, bit_width, dev_info->service_interval_us == service_interval);
1369 FIND_BEST_MATCH(ch, channels, \
1370 dev_info->service_interval_us == service_interval && \
1371 dev_info->bit_width == bw);
Garmond Leung003d9ea2018-08-14 17:05:08 -07001372 sr = *sample_rate;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001373 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1374 /* Currently only apply the first playback sound card configuration */
1375 card_info = node_to_item(node_i, struct usb_card_config, list);
1376 if ((playback && usb_output_device(card_info->usb_device_type)) ||
1377 (!playback && usb_input_device(card_info->usb_device_type))) {
1378 usb_get_best_match_for_sample_rate(&card_info->usb_device_conf_list,
1379 bw, ch, sr, &sr,
1380 service_interval,
1381 true);
1382 }
1383 break;
1384 }
1385
1386#define SET_OR_RETURN_ON_ERROR(arg, local_var, cond) \
1387 if (local_var != (cond)) arg = local_var; else return -1;
1388
1389 SET_OR_RETURN_ON_ERROR(*bit_width, bw, 0);
1390 SET_OR_RETURN_ON_ERROR(*sample_rate, sr, 0);
1391 SET_OR_RETURN_ON_ERROR(*channels, ch, 0);
1392 return 0;
1393#undef FIND_BEST_MATCH
1394#undef SET_OR_RETURN_ON_ERROR
1395}
1396
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001397int usb_get_service_interval(bool playback,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001398 unsigned long *service_interval)
1399{
1400 const char *ctl_name = "USB_AUDIO_RX service_interval";
1401 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
1402 ctl_name);
1403
1404 if (!playback) {
1405 ALOGE("%s not valid for capture", __func__);
1406 return -1;
1407 }
1408
1409 if (!ctl) {
1410 ALOGV("%s: could not get mixer %s", __func__, ctl_name);
1411 return -1;
1412 }
1413
1414 *service_interval = mixer_ctl_get_value(ctl, 0);
1415 return 0;
1416}
1417
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001418int usb_set_service_interval(bool playback,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001419 unsigned long service_interval,
1420 bool *reconfig)
1421{
1422 *reconfig = false;
1423 unsigned long current_service_interval = 0;
1424 const char *ctl_name = "USB_AUDIO_RX service_interval";
1425 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
1426 ctl_name);
1427
1428 if (!playback) {
1429 ALOGE("%s not valid for capture", __func__);
1430 return -1;
1431 }
1432
1433 if (!ctl) {
1434 ALOGV("%s: could not get mixer %s", __func__, ctl_name);
1435 return -1;
1436 }
1437
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001438 if (usb_get_service_interval(playback,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001439 &current_service_interval) != 0) {
1440 ALOGE("%s Unable to get current service interval", __func__);
1441 return -1;
1442 }
1443
1444 if (current_service_interval != service_interval) {
1445 mixer_ctl_set_value(ctl, 0, service_interval);
1446 *reconfig = usbmod->usb_reconfig = true;
1447 }
1448 else
1449 *reconfig = usbmod->usb_reconfig = false;
1450 return 0;
1451}
1452
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001453int usb_check_and_set_svc_int(struct audio_usecase *uc_info,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001454 bool starting_output_stream)
1455{
1456 struct listnode *node = NULL;
1457 struct audio_usecase *usecase = uc_info;
1458 bool reconfig = false;
1459 bool burst_mode = true;
1460 unsigned long service_interval = 0;
1461 struct audio_device *adev = usbmod->adev;
1462
1463 ALOGV("%s: enter:", __func__);
1464
1465 if ((starting_output_stream == true &&
1466 ((uc_info->id == USECASE_AUDIO_PLAYBACK_MMAP) ||
1467 (uc_info->id == USECASE_AUDIO_PLAYBACK_ULL))) ||
1468 (voice_is_call_state_active(usbmod->adev))) {
1469 burst_mode = false;
1470 } else {
1471 /* set if the valid usecase do not already exist */
1472 list_for_each(node, &adev->usecase_list) {
1473 usecase = node_to_item(node, struct audio_usecase, list);
1474 if (usecase->type == PCM_PLAYBACK &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001475 is_usb_out_device_type(&usecase->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07001476 switch (usecase->id) {
1477 case USECASE_AUDIO_PLAYBACK_MMAP:
1478 case USECASE_AUDIO_PLAYBACK_ULL:
1479 {
1480 if (uc_info != usecase) {
1481 //another ULL stream exists
1482 ALOGV("%s: another ULL Stream in active use-case list burst mode = false.", __func__);
1483 burst_mode = false;
1484 } else {
1485 ALOGV("%s:current ULL uc is the same as incoming uc_info \
1486 which means we are stopping the output stream, \
1487 we don't want to set burst mode to false", __func__);
1488 }
1489 break;
1490 }
1491 default:
1492 break;
1493 }
1494 }
1495 }
1496 }
1497
1498 ALOGV("%s: burst mode(%d).", __func__,burst_mode);
1499
1500 service_interval =
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001501 usb_find_service_interval(!burst_mode, true /*playback*/);
Garmond Leung5fd0b552018-04-17 11:56:12 -07001502
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001503 usb_set_service_interval(true /*playback*/,
Yunfei Zhang7728dce2018-10-31 10:20:52 +08001504 service_interval,
1505 &reconfig);
Garmond Leung5fd0b552018-04-17 11:56:12 -07001506
1507 /* no change or not supported or no active usecases */
1508 if (reconfig)
1509 return -1;
1510 return 0;
1511}
1512
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001513bool usb_is_reconfig_req()
Garmond Leung5fd0b552018-04-17 11:56:12 -07001514{
1515 return usbmod->usb_reconfig;
1516}
1517
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001518void usb_set_reconfig(bool is_required)
Garmond Leung5fd0b552018-04-17 11:56:12 -07001519{
1520 usbmod->usb_reconfig = is_required;
1521}
1522
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001523bool usb_connected(struct str_parms *parms) {
Sharad Sangled0a50b22018-04-05 23:28:32 +05301524 int card = -1;
1525 struct listnode *node_i = NULL;
1526 struct usb_card_config *usb_card_info = NULL;
1527 bool usb_connected = false;
1528
Weiyin Jiang63831272018-06-28 11:41:01 +08001529 if ((parms != NULL) && str_parms_get_int(parms, "card", &card) >= 0) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001530 usb_connected = usb_alive(card);
Sharad Sangled0a50b22018-04-05 23:28:32 +05301531 } else {
1532 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1533 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001534 if (usb_alive(usb_card_info->usb_card)) {
Sharad Sangled0a50b22018-04-05 23:28:32 +05301535 usb_connected = true;
1536 break;
1537 }
1538 }
1539 }
1540 return usb_connected;
1541}
1542
Carter Hsu32a62362018-10-15 15:01:42 -07001543char *usb_usbid()
1544{
1545 struct usb_card_config *card_info;
1546
1547 if (usbmod == NULL)
1548 return NULL;
1549
1550 if (list_empty(&usbmod->usb_card_conf_list))
1551 return NULL;
1552
1553 card_info = node_to_item(list_head(&usbmod->usb_card_conf_list),\
1554 struct usb_card_config, list);
1555
1556 return strdup(card_info->usbid);
1557}
1558
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001559void usb_init(void *adev)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001560{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001561 if (usbmod == NULL) {
1562 usbmod = calloc(1, sizeof(struct usb_module));
1563 if (usbmod == NULL) {
1564 ALOGE("%s: error unable to allocate memory", __func__);
1565 goto exit;
1566 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001567 } else {
1568 memset(usbmod, 0, sizeof(*usbmod));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001569 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001570
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001571 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001572 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001573 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301574 usbmod->is_capture_supported = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001575 usbmod->usb_reconfig = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001576exit:
1577 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001578}
1579
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001580void usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001581{
1582 if (NULL != usbmod){
1583 free(usbmod);
1584 usbmod = NULL;
1585 }
1586}