blob: 9981ef01e55e0c4392e4fcff4aed3888ee3ecf40 [file] [log] [blame]
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013, 2016-2019 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
58static uint32_t supported_sample_rates[] =
Haynes Mathew George484e8d22017-07-31 18:55:17 -070059 {384000, 352800, 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 22050, 16000, 11025, 8000};
60static uint32_t supported_sample_rates_mask[2];
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080061
62#define MAX_SAMPLE_RATE_SIZE sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
63
Garmond Leung5fd0b552018-04-17 11:56:12 -070064#define DEFAULT_SERVICE_INTERVAL_US 0
65
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#define _MAX(x, y) (((x) >= (y)) ? (x) : (y))
67#define _MIN(x, y) (((x) <= (y)) ? (x) : (y))
68
Garmond Leung5fd0b552018-04-17 11:56:12 -070069typedef enum usb_usecase_type{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080070 USB_PLAYBACK = 0,
71 USB_CAPTURE,
Garmond Leung5fd0b552018-04-17 11:56:12 -070072} usb_usecase_type_t;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080073
Kuirong Wang1cad7142016-05-24 15:21:56 -070074enum {
75 USB_SIDETONE_ENABLE_INDEX = 0,
76 USB_SIDETONE_VOLUME_INDEX,
77 USB_SIDETONE_MAX_INDEX,
78};
79
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080080struct usb_device_config {
81 struct listnode list;
82 unsigned int bit_width;
83 unsigned int channels;
84 unsigned int rate_size;
85 unsigned int rates[MAX_SAMPLE_RATE_SIZE];
Garmond Leung5fd0b552018-04-17 11:56:12 -070086 unsigned long service_interval_us;
87 usb_usecase_type_t type;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080088};
89
90struct usb_card_config {
91 struct listnode list;
92 audio_devices_t usb_device_type;
93 int usb_card;
94 struct listnode usb_device_conf_list;
Kuirong Wang1cad7142016-05-24 15:21:56 -070095 struct mixer *usb_snd_mixer;
96 int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
97 int usb_sidetone_vol_min;
98 int usb_sidetone_vol_max;
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -070099 int endian;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800100};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700101
102struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800103 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700104 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700105 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +0530106 bool is_capture_supported;
Garmond Leung5fd0b552018-04-17 11:56:12 -0700107 bool usb_reconfig;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700108};
109
110static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800111static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700112static int usb_sidetone_gain = 0;
113
114static const char * const usb_sidetone_enable_str[] = {
115 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -0700116 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -0700117};
118
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800119static const char * const usb_sidetone_volume_str[] = {
120 "Sidetone Playback Volume",
121 "Mic Playback Volume",
122};
123
124static int usb_get_sidetone_gain(struct usb_card_config *card_info)
125{
126 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
127 if (gain > card_info->usb_sidetone_vol_max)
128 gain = card_info->usb_sidetone_vol_max;
129 return gain;
130}
131
132static void usb_get_sidetone_volume(struct usb_card_config *usb_card_info)
133{
134 struct mixer_ctl *ctl;
135 unsigned int index;
136
137 if (!audio_extn_usb_is_sidetone_volume_enabled())
138 return;
139
140 for (index = 0;
141 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
142 index++) {
143 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
144 usb_sidetone_volume_str[index]);
145 if (ctl) {
146 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
147 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
148 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
149 break;
150 }
151 }
152}
153
154static void usb_set_sidetone_volume(struct usb_card_config *usb_card_info,
155 bool enable, int index)
156{
157 struct mixer_ctl *ctl;
158
159 if (!audio_extn_usb_is_sidetone_volume_enabled())
160 return;
161
162 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
163 usb_sidetone_volume_str[index]);
164
165 if (ctl == NULL)
166 ALOGV("%s: sidetone gain mixer command is not found",
167 __func__);
168 else if (enable)
169 mixer_ctl_set_value(ctl, 0,
170 usb_get_sidetone_gain(usb_card_info));
171}
172
173
174
Kuirong Wang1cad7142016-05-24 15:21:56 -0700175static void usb_mixer_print_enum(struct mixer_ctl *ctl)
176{
177 unsigned int num_enums;
178 unsigned int i;
179 const char *string;
180
181 num_enums = mixer_ctl_get_num_enums(ctl);
182
183 for (i = 0; i < num_enums; i++) {
184 string = mixer_ctl_get_enum_string(ctl, i);
185 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
186 }
187}
188
189static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
190{
191 struct mixer_ctl *ctl;
192 enum mixer_ctl_type type;
193 unsigned int num_values;
194 unsigned int i;
195 int min, max;
196
197 if (isdigit(control[0]))
198 ctl = mixer_get_ctl(mixer, atoi(control));
199 else
200 ctl = mixer_get_ctl_by_name(mixer, control);
201
202 if (!ctl) {
203 fprintf(stderr, "Invalid mixer control\n");
204 return;
205 }
206
207 type = mixer_ctl_get_type(ctl);
208 num_values = mixer_ctl_get_num_values(ctl);
209
210 ALOGI("%s:", mixer_ctl_get_name(ctl));
211
212 for (i = 0; i < num_values; i++) {
213 switch (type) {
214 case MIXER_CTL_TYPE_INT:
215 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
216 break;
217 case MIXER_CTL_TYPE_BOOL:
218 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
219 break;
220 case MIXER_CTL_TYPE_ENUM:
221 usb_mixer_print_enum(ctl);
222 break;
223 case MIXER_CTL_TYPE_BYTE:
224 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
225 break;
226 default:
227 ALOGI(" unknown");
228 break;
229 }
230 }
231
232 if (type == MIXER_CTL_TYPE_INT) {
233 min = mixer_ctl_get_range_min(ctl);
234 max = mixer_ctl_get_range_max(ctl);
235 ALOGI(" (range %d->%d)", min, max);
236 }
237}
238
239static void usb_soundcard_list_controls(struct mixer *mixer)
240{
241 struct mixer_ctl *ctl;
242 const char *name, *type;
243 unsigned int num_ctls, num_values;
244 unsigned int i;
245
246 num_ctls = mixer_get_num_ctls(mixer);
247
248 ALOGI("Number of controls: %d\n", num_ctls);
249
250 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
251 for (i = 0; i < num_ctls; i++) {
252 ctl = mixer_get_ctl(mixer, i);
253 if (ctl != NULL) {
254 name = mixer_ctl_get_name(ctl);
255 type = mixer_ctl_get_type_string(ctl);
256 num_values = mixer_ctl_get_num_values(ctl);
257 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
258 if (name != NULL)
259 usb_soundcard_detail_control(mixer, name);
260 }
261 }
262}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700263
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800264static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
265 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700266{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800267 struct mixer_ctl *ctl;
268 unsigned int dev_token;
269 unsigned int pcm_device_number = 0;
270
271 /*
272 * usb_dev_token_id is 32 bit number and is defined as below:
273 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
274 */
275 dev_token = (card << 16 ) |
276 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
277
278 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
279 if (!ctl) {
280 ALOGE("%s: Could not get ctl for mixer cmd - %s",
281 __func__, dev_mixer_ctl_name);
282 return -EINVAL;
283 }
284 mixer_ctl_set_value(ctl, 0, dev_token);
285
286 return 0;
287}
288
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700289static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
290{
291 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
292 endian_mixer_ctl_name);
293 if (!ctl) {
294 ALOGE("%s: Could not get ctl for mixer cmd - %s",
295 __func__, endian_mixer_ctl_name);
296 return -EINVAL;
297 }
298
299 switch (endian) {
300 case 0:
301 case 1:
302 mixer_ctl_set_value(ctl, 0, endian);
303 break;
304 default:
305 ALOGW("%s: endianness(%d) not supported",
306 __func__, endian);
307 break;
308 }
309 return 0;
310}
311
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700312static int usb_get_sample_rates(int type, char *rates_str,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800313 struct usb_device_config *config)
314{
315 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700316 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800317 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700318
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800319 /* Sample rate string can be in any of the folloing two bit_widthes:
320 * Rates: 8000 - 48000 (continuous)
321 * Rates: 8000, 44100, 48000
322 * Support both the bit_widths
323 */
324 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700325 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
326 if (next_sr_string == NULL) {
327 ALOGE("%s: could not find min rates string", __func__);
328 return -EINVAL;
329 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800330 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700331 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700332 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800333 if (next_sr_string == NULL) {
334 ALOGE("%s: could not find max rates string", __func__);
335 return -EINVAL;
336 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700337 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800338
Kuirong Wang591a98a2016-06-27 12:41:41 -0700339 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800340 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700341 supported_sample_rates[i] <= max_sr) {
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800342 // FIXME: we don't support >192KHz in recording path for now
343 if ((supported_sample_rates[i] > SAMPLE_RATE_192000) &&
344 (type == USB_CAPTURE))
345 continue;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800346 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700347 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700348 ALOGI_IF(usb_audio_debug_enable,
349 "%s: continuous sample rate supported_sample_rates[%d] %d",
350 __func__, i, supported_sample_rates[i]);
351 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800352 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700353 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800354 do {
355 sr = (uint32_t)atoi(next_sr_string);
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800356 // FIXME: we don't support >192KHz in recording path for now
357 if ((sr > SAMPLE_RATE_192000) && (type == USB_CAPTURE)) {
358 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
359 continue;
360 }
361
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800362 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
363 if (supported_sample_rates[i] == sr) {
364 ALOGI_IF(usb_audio_debug_enable,
365 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
366 __func__, sr, i, supported_sample_rates[i]);
367 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700368 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800369 }
370 }
371 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
372 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700373 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800374 config->rate_size = sr_size;
375 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700376}
377
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800378static int get_usb_service_interval(const char *interval_str_start,
Garmond Leung5fd0b552018-04-17 11:56:12 -0700379 struct usb_device_config *usb_device_info)
380{
381 unsigned long interval = 0;
382 char time_unit[8] = {0};
383 int multiplier = 0;
384
385 char *eol = strchr(interval_str_start, '\n');
386 if (!eol) {
387 ALOGE("%s: No EOL found", __func__);
388 return -1;
389 }
390 char *tmp = (char *)calloc(1, eol-interval_str_start+1);
391 if (!tmp) {
392 ALOGE("%s: failed to allocate tmp", __func__);
393 return -1;
394 }
395 memcpy(tmp, interval_str_start, eol-interval_str_start);
396 sscanf(tmp, "%lu %2s", &interval, &time_unit[0]);
397 if (!strcmp(time_unit, "us")) {
398 multiplier = 1;
399 } else if (!strcmp(time_unit, "ms")) {
400 multiplier = 1000;
401 } else if (!strcmp(time_unit, "s")) {
402 multiplier = 1000000;
403 } else {
404 ALOGE("%s: unknown time_unit %s, assume default", __func__, time_unit);
405 interval = DEFAULT_SERVICE_INTERVAL_US;
406 multiplier = 1;
407 }
408 interval *= multiplier;
409 ALOGD("%s: set service_interval_us %lu", __func__, interval);
410 usb_device_info->service_interval_us = interval;
411 free(tmp);
412 return 0;
413}
414
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800415static int usb_get_capability(int type,
416 struct usb_card_config *usb_card_info,
417 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700418{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700419 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800420 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800421 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700422 char *str_start = NULL;
423 char *str_end = NULL;
424 char *channel_start = NULL;
425 char *bit_width_start = NULL;
426 char *rates_str_start = NULL;
427 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700428 char *read_buf = NULL;
429 char *rates_str = NULL;
Garmond Leung5fd0b552018-04-17 11:56:12 -0700430 char *interval_str_start = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700431 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700432 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800433 char *bit_width_str = NULL;
434 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700435 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700436
Kuirong Wange9894162016-08-26 15:16:39 -0700437 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800438 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
439 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
440
Kuirong Wange9894162016-08-26 15:16:39 -0700441 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800442 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700443 if(ret < 0) {
444 ALOGE("%s: failed on snprintf (%d) to path %s\n",
445 __func__, ret, path);
446 goto done;
447 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700448
449 fd = open(path, O_RDONLY);
450 if (fd <0) {
451 ALOGE("%s: error failed to open config file %s error: %d\n",
452 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700453 ret = -EINVAL;
454 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700455 }
456
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800457 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700458
459 if (!read_buf) {
460 ALOGE("Failed to create read_buf");
461 ret = -ENOMEM;
462 goto done;
463 }
464
Kuirong Wange9894162016-08-26 15:16:39 -0700465 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
466 ALOGE("file read error\n");
467 goto done;
468 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800469 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
470 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700471 if (str_start == NULL) {
472 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800473 __func__, ((type == USB_PLAYBACK) ?
474 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700475 ret = -EINVAL;
476 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700477 }
Kuirong Wange9894162016-08-26 15:16:39 -0700478 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
479 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
480 if (str_end > str_start)
481 check = true;
482
483 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700484
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800485 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700486 str_start = strstr(str_start, "Altset");
487 if ((str_start == NULL) || (check && (str_start >= str_end))) {
488 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800489 break;
490 }
Kuirong Wange9894162016-08-26 15:16:39 -0700491 ALOGV("%s: remaining string %s\n", __func__, str_start);
492 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800493 usb_device_info = calloc(1, sizeof(struct usb_device_config));
494 if (usb_device_info == NULL) {
495 ALOGE("%s: error unable to allocate memory",
496 __func__);
497 ret = -ENOMEM;
498 break;
499 }
Garmond Leung5fd0b552018-04-17 11:56:12 -0700500 usb_device_info->type = type;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800501 /* Bit bit_width parsing */
502 bit_width_start = strstr(str_start, "Format: ");
503 if (bit_width_start == NULL) {
504 ALOGI("%s: Could not find bit_width string", __func__);
505 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700506 continue;
507 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800508 target = strchr(bit_width_start, '\n');
509 if (target == NULL) {
510 ALOGI("%s:end of line not found", __func__);
511 free(usb_device_info);
512 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700513 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800514 size = target - bit_width_start;
515 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
516 ALOGE("%s: unable to allocate memory to hold bit width strings",
517 __func__);
518 ret = -EINVAL;
519 free(usb_device_info);
520 break;
521 }
522 memcpy(bit_width_str, bit_width_start, size);
523 bit_width_str[size] = '\0';
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700524
525 const char * formats[] = { "S32", "S24_3", "S24", "S16" };
526 const int bit_width[] = { 32, 24, 24, 16};
527 for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
528 const char * s = strstr(bit_width_str, formats[i]);
529 if (s) {
530 usb_device_info->bit_width = bit_width[i];
531 usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
532 break;
533 }
534 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800535
536 if (bit_width_str)
537 free(bit_width_str);
538
539 /* channels parsing */
540 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
541 if (channel_start == NULL) {
542 ALOGI("%s: could not find Channels string", __func__);
543 free(usb_device_info);
544 continue;
545 }
546 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
547 usb_device_info->channels = channels_no;
548
549 /* Sample rates parsing */
550 rates_str_start = strstr(str_start, "Rates: ");
551 if (rates_str_start == NULL) {
552 ALOGI("%s: cant find rates string", __func__);
553 free(usb_device_info);
554 continue;
555 }
556 target = strchr(rates_str_start, '\n');
557 if (target == NULL) {
558 ALOGI("%s: end of line not found", __func__);
559 free(usb_device_info);
560 continue;
561 }
562 size = target - rates_str_start;
563 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
564 ALOGE("%s: unable to allocate memory to hold sample rate strings",
565 __func__);
566 ret = -EINVAL;
567 free(usb_device_info);
568 break;
569 }
570 memcpy(rates_str, rates_str_start, size);
571 rates_str[size] = '\0';
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700572 ret = usb_get_sample_rates(type, rates_str, usb_device_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800573 if (rates_str)
574 free(rates_str);
575 if (ret < 0) {
576 ALOGI("%s: error unable to get sample rate values",
577 __func__);
578 free(usb_device_info);
579 continue;
580 }
Garmond Leung5fd0b552018-04-17 11:56:12 -0700581 // Data packet interval is an optional field.
582 // Assume 0ms interval if this cannot be read
583 // LPASS USB and HLOS USB will figure out the default to use
584 usb_device_info->service_interval_us = DEFAULT_SERVICE_INTERVAL_US;
585 interval_str_start = strstr(str_start, DATA_PACKET_INTERVAL_STR);
586 if (interval_str_start != NULL) {
587 interval_str_start += strlen(DATA_PACKET_INTERVAL_STR);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800588 ret = get_usb_service_interval(interval_str_start, usb_device_info);
Garmond Leung5fd0b552018-04-17 11:56:12 -0700589 if (ret < 0) {
590 ALOGE("%s: error unable to get service interval, assume default",
591 __func__);
592 }
593 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800594 /* Add to list if every field is valid */
595 list_add_tail(&usb_card_info->usb_device_conf_list,
596 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700597 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700598
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700599done:
600 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700601 if (read_buf) free(read_buf);
602 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700603}
604
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800605static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
606 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700607{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800608 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700609
610 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800611 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
612 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700613 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800614 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700615 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800616 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700617 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800618exit:
619
620 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700621}
622
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800623static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
624 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700625{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800626 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700627
628 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800629 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
630 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700631 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800632 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700633 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800634 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700635 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700636
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800637exit:
638 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700639}
640
Kuirong Wang1cad7142016-05-24 15:21:56 -0700641static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
642{
643 struct mixer_ctl *ctl;
644 unsigned int index;
645
646 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
647 usb_card_info->usb_sidetone_index[index] = -1;
648
649 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
650 for (index = 0;
651 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
652 index++) {
653 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
654 usb_sidetone_enable_str[index]);
655 if (ctl) {
656 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
657 /* Disable device sidetone by default */
658 mixer_ctl_set_value(ctl, 0, false);
Aalique Grahame22e49102018-12-18 14:23:57 -0800659 ALOGV("%s: sidetone mixer Control found(%s) ... disabling by default",
660 __func__, usb_sidetone_enable_str[index]);
Kuirong Wang1cad7142016-05-24 15:21:56 -0700661 break;
662 }
663 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800664
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800665 usb_get_sidetone_volume(usb_card_info);
Kuirong Wang1cad7142016-05-24 15:21:56 -0700666
667 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
668 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
669
670 return;
671}
672
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700673static inline bool usb_output_device(audio_devices_t device) {
674 // ignore accessory for now
675 if (device == AUDIO_DEVICE_OUT_USB_ACCESSORY)
676 return false;
677 return audio_is_usb_out_device(device);
678}
679
680static inline bool usb_input_device(audio_devices_t device) {
681 // ignore accessory for now
682 if (device == AUDIO_DEVICE_IN_USB_ACCESSORY)
683 return false;
684 return audio_is_usb_in_device(device);
685}
686
687static bool usb_valid_device(audio_devices_t device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700688{
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700689 return usb_output_device(device) ||
690 usb_input_device(device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800691}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700692
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800693static void usb_print_active_device(void){
694 struct listnode *node_i, *node_j;
695 struct usb_device_config *dev_info;
696 struct usb_card_config *card_info;
697 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700698
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800699 ALOGI("%s", __func__);
700 list_for_each(node_i, &usbmod->usb_card_conf_list) {
701 card_info = node_to_item(node_i, struct usb_card_config, list);
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700702 ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
703 __func__, card_info->usb_device_type,
704 card_info->usb_card, card_info->endian ? "BE" : "LE");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800705 list_for_each(node_j, &card_info->usb_device_conf_list) {
706 dev_info = node_to_item(node_j, struct usb_device_config, list);
707 ALOGI("%s: bit-width(%d) channel(%d)",
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700708 __func__, dev_info->bit_width, dev_info->channels);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800709 for (i = 0; i < dev_info->rate_size; i++)
710 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
711 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700712 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800713}
714
715static bool usb_get_best_match_for_bit_width(
716 struct listnode *dev_list,
717 unsigned int stream_bit_width,
718 unsigned int *bit_width)
719{
720 struct listnode *node_i;
721 struct usb_device_config *dev_info;
722 unsigned int candidate = 0;
723
724 list_for_each(node_i, dev_list) {
725 dev_info = node_to_item(node_i, struct usb_device_config, list);
726 ALOGI_IF(usb_audio_debug_enable,
727 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
728 __func__, dev_info->bit_width,
729 stream_bit_width, candidate);
730 if (dev_info->bit_width == stream_bit_width) {
731 *bit_width = dev_info->bit_width;
732 ALOGV("%s: Found match bit-width (%d)",
733 __func__, dev_info->bit_width);
734 goto exit;
735 } else if (candidate == 0) {
736 candidate = dev_info->bit_width;
737 }
738 /*
739 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
740 * higher bit width 32 is picked up instead of 16-bit
741 */
742 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
743 ABS_SUB(stream_bit_width, candidate)) {
744 candidate = dev_info->bit_width;
745 }
746 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
747 ABS_SUB(stream_bit_width, candidate)) &&
748 (dev_info->bit_width > candidate)) {
749 candidate = dev_info->bit_width;
750 }
751 }
752 ALOGV("%s: No match found, use the best candidate bw(%d)",
753 __func__, candidate);
754 *bit_width = candidate;
755exit:
756 return true;
757}
758
759static bool usb_get_best_match_for_channels(
760 struct listnode *dev_list,
761 unsigned int bit_width,
762 unsigned int stream_ch,
763 unsigned int *ch)
764{
765 struct listnode *node_i;
766 struct usb_device_config *dev_info;
767 unsigned int candidate = 0;
768
769 list_for_each(node_i, dev_list) {
770 dev_info = node_to_item(node_i, struct usb_device_config, list);
771 ALOGI_IF(usb_audio_debug_enable,
772 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
773 __func__, dev_info->channels, dev_info->bit_width,
774 stream_ch, bit_width, candidate);
775 if (dev_info->bit_width != bit_width)
776 continue;
777 if (dev_info->channels== stream_ch) {
778 *ch = dev_info->channels;
779 ALOGV("%s: Found match channels (%d)",
780 __func__, dev_info->channels);
781 goto exit;
782 } else if (candidate == 0)
783 candidate = dev_info->channels;
784 /*
785 * If stream channel is 4, USB supports both 3 and 5, then
786 * higher channel 5 is picked up instead of 3
787 */
788 else if (ABS_SUB(stream_ch, dev_info->channels) <
789 ABS_SUB(stream_ch, candidate)) {
790 candidate = dev_info->channels;
791 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
792 ABS_SUB(stream_ch, candidate)) &&
793 (dev_info->channels > candidate)) {
794 candidate = dev_info->channels;
795 }
796 }
797 ALOGV("%s: No match found, use the best candidate ch(%d)",
798 __func__, candidate);
799 *ch = candidate;
800exit:
801 return true;
802
803}
804
805static bool usb_sample_rate_multiple(
806 unsigned int stream_sample_rate,
807 unsigned int base)
808{
809 return (((stream_sample_rate / base) * base) == stream_sample_rate);
810}
811
812static bool usb_find_sample_rate_candidate(unsigned int base,
813 unsigned stream_rate,
814 unsigned int usb_rate,
815 unsigned int cur_candidate,
816 unsigned int *update_candidate)
817{
818 /* For sample rate, we should consider fracational sample rate as high priority.
819 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
820 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
821 */
822 if (!usb_sample_rate_multiple(cur_candidate, base) &&
823 usb_sample_rate_multiple(usb_rate, base)) {
824 *update_candidate = usb_rate;
825 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
826 usb_sample_rate_multiple(usb_rate, base)) {
827 if (ABS_SUB(stream_rate, usb_rate) <
828 ABS_SUB(stream_rate, cur_candidate)) {
829 *update_candidate = usb_rate;
830 } else if ((ABS_SUB(stream_rate, usb_rate) ==
831 ABS_SUB(stream_rate, cur_candidate)) &&
832 (usb_rate > cur_candidate)) {
833 *update_candidate = usb_rate;
834 }
835 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
836 !usb_sample_rate_multiple(usb_rate, base)) {
837 if (ABS_SUB(stream_rate, usb_rate) <
838 ABS_SUB(stream_rate, cur_candidate)) {
839 *update_candidate = usb_rate;
840 } else if ((ABS_SUB(stream_rate, usb_rate) ==
841 ABS_SUB(stream_rate, cur_candidate)) &&
842 (usb_rate > cur_candidate)) {
843 *update_candidate = usb_rate;
844 }
845 }
846 return true;
847}
848
849static bool usb_get_best_match_for_sample_rate(
850 struct listnode *dev_list,
851 unsigned int bit_width,
852 unsigned int ch,
853 unsigned int stream_sample_rate,
Garmond Leung5fd0b552018-04-17 11:56:12 -0700854 unsigned int *sr,
855 unsigned int service_interval,
856 bool do_service_interval_check)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800857{
858 struct listnode *node_i;
859 struct usb_device_config *dev_info;
860 unsigned int candidate = 48000;
861 unsigned int base = SAMPLE_RATE_8000;
862 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
863 unsigned int i;
864
865 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
866 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
867
868 list_for_each(node_i, dev_list) {
869 dev_info = node_to_item(node_i, struct usb_device_config, list);
870 ALOGI_IF(usb_audio_debug_enable,
871 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
872 __func__, dev_info->channels, dev_info->bit_width,
873 ch, bit_width, stream_sample_rate, candidate);
Garmond Leung5fd0b552018-04-17 11:56:12 -0700874
875 if ((dev_info->bit_width != bit_width) ||
876 (dev_info->channels != ch) ||
877 (do_service_interval_check && (dev_info->service_interval_us !=
878 service_interval)))
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800879 continue;
880
881 candidate = 0;
882 for (i = 0; i < dev_info->rate_size; i++) {
883 ALOGI_IF(usb_audio_debug_enable,
884 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
885 __func__, dev_info->channels,
886 dev_info->bit_width, dev_info->rates[i],
887 ch, bit_width, stream_sample_rate, candidate);
888 if (stream_sample_rate == dev_info->rates[i]) {
889 *sr = dev_info->rates[i];
890 ALOGV("%s: Found match sample rate (%d)",
891 __func__, dev_info->rates[i]);
892 goto exit;
893 } else if (candidate == 0) {
894 candidate = dev_info->rates[i];
895 /*
896 * For sample rate, we should consider fracational sample rate as high priority.
897 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
898 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
899 */
900 } else if (multiple_8k) {
901 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
902 stream_sample_rate,
903 dev_info->rates[i],
904 candidate,
905 &candidate);
906 } else {
907 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
908 stream_sample_rate,
909 dev_info->rates[i],
910 candidate,
911 &candidate);
912 }
913 }
914 }
915 ALOGV("%s: No match found, use the best candidate sr(%d)",
916 __func__, candidate);
917 *sr = candidate;
918exit:
919 return true;
920}
921
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800922static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
923 unsigned int *bit_width,
924 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530925 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800926{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800927 bool is_usb_supported = true;
928
929 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530930 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800931 if (list_empty(dev_list)) {
932 *sample_rate = 48000;
933 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530934 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800935 ALOGI("%s: list is empty,fall back to default setting", __func__);
936 goto exit;
937 }
938 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
939 usb_get_best_match_for_channels(dev_list,
940 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530941 *ch,
942 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800943 usb_get_best_match_for_sample_rate(dev_list,
944 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530945 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800946 *sample_rate,
Garmond Leung5fd0b552018-04-17 11:56:12 -0700947 sample_rate,
948 0 /*service int*/,
949 false /*do service int check*/);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800950exit:
951 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530952 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800953 return is_usb_supported;
954}
955
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800956void usb_set_sidetone_gain(struct str_parms *parms,
Kuirong Wang1cad7142016-05-24 15:21:56 -0700957 char *value, int len)
958{
959 int err;
960
961 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
962 value, len);
963 if (err >= 0) {
964 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
965 ALOGV("%s: sidetone gain(%s) decimal %d",
966 __func__, value, usb_sidetone_gain);
967 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
968 }
969 return;
970}
971
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800972int usb_enable_sidetone(int device, bool enable)
Kuirong Wang1cad7142016-05-24 15:21:56 -0700973{
974 int ret = -ENODEV;
975 struct listnode *node_i;
976 struct usb_card_config *card_info;
977 int i;
978 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
979 __func__, device, enable);
980
981 list_for_each(node_i, &usbmod->usb_card_conf_list) {
982 card_info = node_to_item(node_i, struct usb_card_config, list);
983 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
984 __func__, card_info->usb_device_type, card_info->usb_card);
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700985 if (usb_output_device(card_info->usb_device_type)) {
Kuirong Wang1cad7142016-05-24 15:21:56 -0700986 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
987 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
988 card_info->usb_snd_mixer,
989 usb_sidetone_enable_str[i]);
990 if (ctl)
991 mixer_ctl_set_value(ctl, 0, enable);
992 else
993 break;
994
995 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800996 usb_set_sidetone_volume(card_info, enable, i);
Kuirong Wang1cad7142016-05-24 15:21:56 -0700997 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800998
Kuirong Wang1cad7142016-05-24 15:21:56 -0700999 ret = 0;
1000 break;
1001 }
1002 }
1003 }
1004 return ret;
1005}
1006
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001007bool usb_is_config_supported(unsigned int *bit_width,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001008 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -07001009 unsigned int *ch,
1010 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001011{
1012 struct listnode *node_i;
1013 struct usb_card_config *card_info;
1014 bool is_usb_supported = false;
1015
Kuirong Wang27152a12016-11-11 10:20:30 -08001016 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
1017 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001018 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1019 card_info = node_to_item(node_i, struct usb_card_config, list);
1020 ALOGI_IF(usb_audio_debug_enable,
1021 "%s: card_dev_type (0x%x), card_no(%d)",
1022 __func__, card_info->usb_device_type, card_info->usb_card);
1023 /* Currently only apply the first playback sound card configuration */
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001024 if ((is_playback && usb_output_device(card_info->usb_device_type)) ||
1025 (!is_playback && usb_input_device(card_info->usb_device_type))){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001026 is_usb_supported = usb_audio_backend_apply_policy(
1027 &card_info->usb_device_conf_list,
1028 bit_width,
1029 sample_rate,
1030 ch);
1031 break;
1032 }
1033 }
Ashish Jainb26edfb2016-08-25 00:10:11 +05301034 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
1035 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001036
1037 return is_usb_supported;
1038}
1039
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001040int usb_get_max_channels(bool is_playback)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001041{
1042 struct listnode *node_i, *node_j;
1043 struct usb_device_config *dev_info;
1044 struct usb_card_config *card_info;
1045 unsigned int max_ch = 1;
1046 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1047 card_info = node_to_item(node_i, struct usb_card_config, list);
1048 if (usb_output_device(card_info->usb_device_type) && !is_playback)
1049 continue;
1050 else if (usb_input_device(card_info->usb_device_type) && is_playback)
1051 continue;
1052
1053 list_for_each(node_j, &card_info->usb_device_conf_list) {
1054 dev_info = node_to_item(node_j, struct usb_device_config, list);
1055 max_ch = _MAX(max_ch, dev_info->channels);
1056 }
1057 }
1058
1059 return max_ch;
1060}
1061
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001062int usb_get_max_bit_width(bool is_playback)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001063{
1064 struct listnode *node_i, *node_j;
1065 struct usb_device_config *dev_info;
1066 struct usb_card_config *card_info;
1067 unsigned int max_bw = 16;
1068 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1069 card_info = node_to_item(node_i, struct usb_card_config, list);
1070 if (usb_output_device(card_info->usb_device_type) && !is_playback)
1071 continue;
1072 else if (usb_input_device(card_info->usb_device_type) && is_playback)
1073 continue;
1074
1075 list_for_each(node_j, &card_info->usb_device_conf_list) {
1076 dev_info = node_to_item(node_j, struct usb_device_config, list);
1077 max_bw = _MAX(max_bw, dev_info->bit_width);
1078 }
1079 }
1080
1081 return max_bw;
1082}
1083
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001084int usb_get_sup_sample_rates(bool is_playback,
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001085 uint32_t *sample_rates,
1086 uint32_t sample_rate_size)
1087{
1088 int type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
1089
1090 ALOGV("%s supported_sample_rates_mask 0x%x", __func__, supported_sample_rates_mask[type]);
1091 uint32_t bm = supported_sample_rates_mask[type];
1092 uint32_t tries = _MIN(sample_rate_size, (uint32_t)__builtin_popcount(bm));
1093
1094 int i = 0;
1095 while (tries--) {
1096 int idx = __builtin_ffs(bm) - 1;
1097 sample_rates[i++] = supported_sample_rates[idx];
1098 bm &= ~(1<<idx);
1099 }
1100
1101 return i;
1102}
1103
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001104bool usb_is_capture_supported()
Ashish Jain3e37a702016-11-25 12:27:15 +05301105{
1106 if (usbmod == NULL) {
1107 ALOGE("%s: USB device object is NULL", __func__);
1108 return false;
1109 }
1110 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
1111 return usbmod->is_capture_supported;
1112}
1113
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001114bool usb_is_tunnel_supported()
Zhou Song6f862822017-11-06 17:27:57 +08001115{
1116 return true;
1117}
1118
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001119void usb_add_device(audio_devices_t device, int card)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001120{
1121 struct usb_card_config *usb_card_info;
1122 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -08001123 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001124
Aalique Grahame22e49102018-12-18 14:23:57 -08001125 if ((property_get("vendor.audio.usb.enable.debug",
1126 check_debug_enable, NULL) > 0) ||
1127 (property_get("audio.usb.enable.debug",
1128 check_debug_enable, NULL) > 0)) {
1129 if (atoi(check_debug_enable))
1130 usb_audio_debug_enable = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001131 }
1132
1133 ALOGI_IF(usb_audio_debug_enable,
1134 "%s: parameters device(0x%x), card(%d)",
1135 __func__, device, card);
1136 if (usbmod == NULL) {
1137 ALOGE("%s: USB device object is NULL", __func__);
1138 goto exit;
1139 }
1140
1141 if (!(usb_valid_device(device)) || (card < 0)) {
1142 ALOGE("%s:device(0x%x), card(%d)",
1143 __func__, device, card);
1144 goto exit;
1145 }
1146
Kuirong Wang27152a12016-11-11 10:20:30 -08001147 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1148 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
1149 ALOGI_IF(usb_audio_debug_enable,
1150 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
1151 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
1152 /* If we have cached the capability */
1153 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
1154 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
1155 __func__, device, card);
1156 goto exit;
1157 }
1158 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001159 usb_card_info = calloc(1, sizeof(struct usb_card_config));
1160 if (usb_card_info == NULL) {
1161 ALOGE("%s: error unable to allocate memory",
1162 __func__);
1163 goto exit;
1164 }
1165 list_init(&usb_card_info->usb_device_conf_list);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001166 if (usb_output_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001167 if (!usb_get_device_pb_config(usb_card_info, card)){
1168 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001169 usb_card_info->usb_device_type = device;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001170 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001171 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1172 goto exit;
1173 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001174 } else if (usb_input_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001175 if (!usb_get_device_cap_config(usb_card_info, card)) {
1176 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001177 usb_card_info->usb_device_type = device;
Ashish Jain3e37a702016-11-25 12:27:15 +05301178 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001179 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1180 goto exit;
1181 }
1182 }
1183 /* free memory in error case */
1184 if (usb_card_info != NULL)
1185 free(usb_card_info);
1186exit:
1187 if (usb_audio_debug_enable)
1188 usb_print_active_device();
1189 return;
1190}
1191
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001192void usb_remove_device(audio_devices_t device, int card)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001193{
1194 struct listnode *node_i, *temp_i;
1195 struct listnode *node_j, *temp_j;
1196 struct usb_device_config *dev_info;
1197 struct usb_card_config *card_info;
1198 unsigned int i;
1199
1200 ALOGV("%s: device(0x%x), card(%d)",
1201 __func__, device, card);
1202
1203 if (usbmod == NULL) {
1204 ALOGE("%s: USB device object is NULL", __func__);
1205 goto exit;
1206 }
1207
1208 if (!(usb_valid_device(device)) || (card < 0)) {
1209 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1210 __func__, device, card);
1211 goto exit;
1212 }
1213 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1214 card_info = node_to_item(node_i, struct usb_card_config, list);
1215 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1216 __func__, card_info->usb_device_type, card_info->usb_card);
1217 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1218 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1219 dev_info = node_to_item(node_j, struct usb_device_config, list);
1220 ALOGV("%s: bit-width(%d) channel(%d)",
1221 __func__, dev_info->bit_width, dev_info->channels);
1222 for (i = 0; i < dev_info->rate_size; i++)
1223 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1224
1225 list_remove(node_j);
1226 free(node_to_item(node_j, struct usb_device_config, list));
1227 }
1228 list_remove(node_i);
1229 free(node_to_item(node_i, struct usb_card_config, list));
1230 }
1231 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001232 if (audio_is_usb_in_device(device)) { // XXX not sure if we need to check for card
1233 usbmod->is_capture_supported = false;
1234 supported_sample_rates_mask[USB_CAPTURE] = 0;
1235 } else
1236 supported_sample_rates_mask[USB_PLAYBACK] = 0;
1237
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001238exit:
1239 if (usb_audio_debug_enable)
1240 usb_print_active_device();
1241
1242 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001243}
1244
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001245bool usb_alive(int card) {
Kevin Rocardfce19002017-08-07 19:21:36 -07001246 char path[PATH_MAX] = {0};
1247 // snprintf should never fail
1248 (void) snprintf(path, sizeof(path), "/proc/asound/card%u/stream0", card);
1249 return access(path, F_OK) == 0;
1250}
1251
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001252unsigned long usb_find_service_interval(bool min,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001253 bool playback) {
1254 struct usb_card_config *card_info = NULL;
1255 struct usb_device_config *dev_info = NULL;
1256 struct listnode *node_i = NULL;
1257 struct listnode *node_j = NULL;
Aalique Grahame22e49102018-12-18 14:23:57 -08001258 unsigned long interval_us = min ? ULONG_MAX : 0;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001259 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1260 card_info = node_to_item(node_i, struct usb_card_config, list);
1261 list_for_each(node_j, &card_info->usb_device_conf_list) {
1262 dev_info = node_to_item(node_j, struct usb_device_config, list);
1263 bool match = (playback && (dev_info->type == USB_PLAYBACK)) ||
1264 (!playback && (dev_info->type == USB_CAPTURE));
1265 if (match) {
1266 interval_us = min ?
1267 _MIN(interval_us, dev_info->service_interval_us) :
1268 _MAX(interval_us, dev_info->service_interval_us);
1269 }
1270 }
1271 break;
1272 }
1273 return interval_us;
1274}
1275
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001276int usb_altset_for_service_interval(bool playback,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001277 unsigned long service_interval,
1278 uint32_t *bit_width,
1279 uint32_t *sample_rate,
1280 uint32_t *channels)
1281{
1282 struct usb_card_config *card_info = NULL;
Aalique Grahame22e49102018-12-18 14:23:57 -08001283 struct usb_device_config *dev_info = NULL;
1284 struct listnode *node_i = NULL;
1285 struct listnode *node_j = NULL;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001286 uint32_t bw = 0;
1287 uint32_t ch = 0;
1288 uint32_t sr = 0;
1289
1290 if (service_interval == 0)
1291 return 0;
1292 /* not a valid service interval to search for */
1293
1294#define FIND_BEST_MATCH(local_var, field, cond) \
1295 list_for_each(node_i, &usbmod->usb_card_conf_list) { \
1296 /* Currently only apply the first playback sound card configuration */ \
1297 card_info = node_to_item(node_i, struct usb_card_config, list); \
1298 list_for_each(node_j, &card_info->usb_device_conf_list) { \
1299 dev_info = node_to_item(node_j, struct usb_device_config, list); \
1300 bool match = (playback && (dev_info->type == USB_PLAYBACK)) || \
1301 (!playback && (dev_info->type == USB_CAPTURE)); \
1302 if (match && (cond)) { \
Garmond Leung003d9ea2018-08-14 17:05:08 -07001303 if (dev_info->field == *field) { \
1304 local_var = dev_info->field; \
1305 break; \
1306 } \
Garmond Leung5fd0b552018-04-17 11:56:12 -07001307 local_var = _MAX(local_var, dev_info->field); \
1308 } \
1309 } \
1310 break; \
1311 }
1312
1313 FIND_BEST_MATCH(bw, bit_width, dev_info->service_interval_us == service_interval);
1314 FIND_BEST_MATCH(ch, channels, \
1315 dev_info->service_interval_us == service_interval && \
1316 dev_info->bit_width == bw);
Garmond Leung003d9ea2018-08-14 17:05:08 -07001317 sr = *sample_rate;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001318 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1319 /* Currently only apply the first playback sound card configuration */
1320 card_info = node_to_item(node_i, struct usb_card_config, list);
1321 if ((playback && usb_output_device(card_info->usb_device_type)) ||
1322 (!playback && usb_input_device(card_info->usb_device_type))) {
1323 usb_get_best_match_for_sample_rate(&card_info->usb_device_conf_list,
1324 bw, ch, sr, &sr,
1325 service_interval,
1326 true);
1327 }
1328 break;
1329 }
1330
1331#define SET_OR_RETURN_ON_ERROR(arg, local_var, cond) \
1332 if (local_var != (cond)) arg = local_var; else return -1;
1333
1334 SET_OR_RETURN_ON_ERROR(*bit_width, bw, 0);
1335 SET_OR_RETURN_ON_ERROR(*sample_rate, sr, 0);
1336 SET_OR_RETURN_ON_ERROR(*channels, ch, 0);
1337 return 0;
1338#undef FIND_BEST_MATCH
1339#undef SET_OR_RETURN_ON_ERROR
1340}
1341
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001342int usb_get_service_interval(bool playback,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001343 unsigned long *service_interval)
1344{
1345 const char *ctl_name = "USB_AUDIO_RX service_interval";
1346 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
1347 ctl_name);
1348
1349 if (!playback) {
1350 ALOGE("%s not valid for capture", __func__);
1351 return -1;
1352 }
1353
1354 if (!ctl) {
1355 ALOGV("%s: could not get mixer %s", __func__, ctl_name);
1356 return -1;
1357 }
1358
1359 *service_interval = mixer_ctl_get_value(ctl, 0);
1360 return 0;
1361}
1362
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001363int usb_set_service_interval(bool playback,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001364 unsigned long service_interval,
1365 bool *reconfig)
1366{
1367 *reconfig = false;
1368 unsigned long current_service_interval = 0;
1369 const char *ctl_name = "USB_AUDIO_RX service_interval";
1370 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
1371 ctl_name);
1372
1373 if (!playback) {
1374 ALOGE("%s not valid for capture", __func__);
1375 return -1;
1376 }
1377
1378 if (!ctl) {
1379 ALOGV("%s: could not get mixer %s", __func__, ctl_name);
1380 return -1;
1381 }
1382
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001383 if (usb_get_service_interval(playback,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001384 &current_service_interval) != 0) {
1385 ALOGE("%s Unable to get current service interval", __func__);
1386 return -1;
1387 }
1388
1389 if (current_service_interval != service_interval) {
1390 mixer_ctl_set_value(ctl, 0, service_interval);
1391 *reconfig = usbmod->usb_reconfig = true;
1392 }
1393 else
1394 *reconfig = usbmod->usb_reconfig = false;
1395 return 0;
1396}
1397
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001398int usb_check_and_set_svc_int(struct audio_usecase *uc_info,
Garmond Leung5fd0b552018-04-17 11:56:12 -07001399 bool starting_output_stream)
1400{
1401 struct listnode *node = NULL;
1402 struct audio_usecase *usecase = uc_info;
1403 bool reconfig = false;
1404 bool burst_mode = true;
1405 unsigned long service_interval = 0;
1406 struct audio_device *adev = usbmod->adev;
1407
1408 ALOGV("%s: enter:", __func__);
1409
1410 if ((starting_output_stream == true &&
1411 ((uc_info->id == USECASE_AUDIO_PLAYBACK_MMAP) ||
1412 (uc_info->id == USECASE_AUDIO_PLAYBACK_ULL))) ||
1413 (voice_is_call_state_active(usbmod->adev))) {
1414 burst_mode = false;
1415 } else {
1416 /* set if the valid usecase do not already exist */
1417 list_for_each(node, &adev->usecase_list) {
1418 usecase = node_to_item(node, struct audio_usecase, list);
1419 if (usecase->type == PCM_PLAYBACK &&
1420 audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB )) {
1421 switch (usecase->id) {
1422 case USECASE_AUDIO_PLAYBACK_MMAP:
1423 case USECASE_AUDIO_PLAYBACK_ULL:
1424 {
1425 if (uc_info != usecase) {
1426 //another ULL stream exists
1427 ALOGV("%s: another ULL Stream in active use-case list burst mode = false.", __func__);
1428 burst_mode = false;
1429 } else {
1430 ALOGV("%s:current ULL uc is the same as incoming uc_info \
1431 which means we are stopping the output stream, \
1432 we don't want to set burst mode to false", __func__);
1433 }
1434 break;
1435 }
1436 default:
1437 break;
1438 }
1439 }
1440 }
1441 }
1442
1443 ALOGV("%s: burst mode(%d).", __func__,burst_mode);
1444
1445 service_interval =
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001446 usb_find_service_interval(!burst_mode, true /*playback*/);
Garmond Leung5fd0b552018-04-17 11:56:12 -07001447
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001448 usb_set_service_interval(true /*playback*/,
Yunfei Zhang7728dce2018-10-31 10:20:52 +08001449 service_interval,
1450 &reconfig);
Garmond Leung5fd0b552018-04-17 11:56:12 -07001451
1452 /* no change or not supported or no active usecases */
1453 if (reconfig)
1454 return -1;
1455 return 0;
1456}
1457
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001458bool usb_is_reconfig_req()
Garmond Leung5fd0b552018-04-17 11:56:12 -07001459{
1460 return usbmod->usb_reconfig;
1461}
1462
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001463void usb_set_reconfig(bool is_required)
Garmond Leung5fd0b552018-04-17 11:56:12 -07001464{
1465 usbmod->usb_reconfig = is_required;
1466}
1467
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001468bool usb_connected(struct str_parms *parms) {
Sharad Sangled0a50b22018-04-05 23:28:32 +05301469 int card = -1;
1470 struct listnode *node_i = NULL;
1471 struct usb_card_config *usb_card_info = NULL;
1472 bool usb_connected = false;
1473
Weiyin Jiang63831272018-06-28 11:41:01 +08001474 if ((parms != NULL) && str_parms_get_int(parms, "card", &card) >= 0) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001475 usb_connected = usb_alive(card);
Sharad Sangled0a50b22018-04-05 23:28:32 +05301476 } else {
1477 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1478 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001479 if (usb_alive(usb_card_info->usb_card)) {
Sharad Sangled0a50b22018-04-05 23:28:32 +05301480 usb_connected = true;
1481 break;
1482 }
1483 }
1484 }
1485 return usb_connected;
1486}
1487
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001488void usb_init(void *adev)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001489{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001490 if (usbmod == NULL) {
1491 usbmod = calloc(1, sizeof(struct usb_module));
1492 if (usbmod == NULL) {
1493 ALOGE("%s: error unable to allocate memory", __func__);
1494 goto exit;
1495 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001496 } else {
1497 memset(usbmod, 0, sizeof(*usbmod));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001498 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001499
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001500 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001501 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001502 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301503 usbmod->is_capture_supported = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001504 usbmod->usb_reconfig = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001505exit:
1506 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001507}
1508
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001509void usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001510{
1511 if (NULL != usbmod){
1512 free(usbmod);
1513 usbmod = NULL;
1514 }
1515}