blob: 3b2f1b399a36397ca0c069156b178fa5924ece83 [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
Aalique Grahame22e49102018-12-18 14:23:57 -080047#ifdef USB_TUNNEL_ENABLED
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080048#define USB_BUFF_SIZE 2048
49#define CHANNEL_NUMBER_STR "Channels: "
50#define PLAYBACK_PROFILE_STR "Playback:"
51#define CAPTURE_PROFILE_STR "Capture:"
Garmond Leung5fd0b552018-04-17 11:56:12 -070052#define DATA_PACKET_INTERVAL_STR "Data packet interval:"
Kuirong Wang1cad7142016-05-24 15:21:56 -070053#define USB_SIDETONE_GAIN_STR "usb_sidetone_gain"
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080054#define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A)))
55#define SAMPLE_RATE_8000 8000
56#define SAMPLE_RATE_11025 11025
Weiyin Jiangcba6f962018-03-18 11:52:05 +080057#define SAMPLE_RATE_192000 192000
Kuirong Wanga9f7cee2016-03-07 11:21:52 -080058// Supported sample rates for USB
59static 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;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800101};
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700102
103struct usb_module {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800104 struct listnode usb_card_conf_list;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700105 struct audio_device *adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700106 int sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +0530107 bool is_capture_supported;
Garmond Leung5fd0b552018-04-17 11:56:12 -0700108 bool usb_reconfig;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700109};
110
111static struct usb_module *usbmod = NULL;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800112static bool usb_audio_debug_enable = false;
Kuirong Wang1cad7142016-05-24 15:21:56 -0700113static int usb_sidetone_gain = 0;
114
115static const char * const usb_sidetone_enable_str[] = {
116 "Sidetone Playback Switch",
Kuirong Wang4ddd75f2016-09-21 11:20:31 -0700117 "Mic Playback Switch",
Kuirong Wang1cad7142016-05-24 15:21:56 -0700118};
119
Kuirong Wang1cad7142016-05-24 15:21:56 -0700120static void usb_mixer_print_enum(struct mixer_ctl *ctl)
121{
122 unsigned int num_enums;
123 unsigned int i;
124 const char *string;
125
126 num_enums = mixer_ctl_get_num_enums(ctl);
127
128 for (i = 0; i < num_enums; i++) {
129 string = mixer_ctl_get_enum_string(ctl, i);
130 ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
131 }
132}
133
134static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
135{
136 struct mixer_ctl *ctl;
137 enum mixer_ctl_type type;
138 unsigned int num_values;
139 unsigned int i;
140 int min, max;
141
142 if (isdigit(control[0]))
143 ctl = mixer_get_ctl(mixer, atoi(control));
144 else
145 ctl = mixer_get_ctl_by_name(mixer, control);
146
147 if (!ctl) {
148 fprintf(stderr, "Invalid mixer control\n");
149 return;
150 }
151
152 type = mixer_ctl_get_type(ctl);
153 num_values = mixer_ctl_get_num_values(ctl);
154
155 ALOGI("%s:", mixer_ctl_get_name(ctl));
156
157 for (i = 0; i < num_values; i++) {
158 switch (type) {
159 case MIXER_CTL_TYPE_INT:
160 ALOGI(" %d", mixer_ctl_get_value(ctl, i));
161 break;
162 case MIXER_CTL_TYPE_BOOL:
163 ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
164 break;
165 case MIXER_CTL_TYPE_ENUM:
166 usb_mixer_print_enum(ctl);
167 break;
168 case MIXER_CTL_TYPE_BYTE:
169 ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
170 break;
171 default:
172 ALOGI(" unknown");
173 break;
174 }
175 }
176
177 if (type == MIXER_CTL_TYPE_INT) {
178 min = mixer_ctl_get_range_min(ctl);
179 max = mixer_ctl_get_range_max(ctl);
180 ALOGI(" (range %d->%d)", min, max);
181 }
182}
183
184static void usb_soundcard_list_controls(struct mixer *mixer)
185{
186 struct mixer_ctl *ctl;
187 const char *name, *type;
188 unsigned int num_ctls, num_values;
189 unsigned int i;
190
191 num_ctls = mixer_get_num_ctls(mixer);
192
193 ALOGI("Number of controls: %d\n", num_ctls);
194
195 ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
196 for (i = 0; i < num_ctls; i++) {
197 ctl = mixer_get_ctl(mixer, i);
198 if (ctl != NULL) {
199 name = mixer_ctl_get_name(ctl);
200 type = mixer_ctl_get_type_string(ctl);
201 num_values = mixer_ctl_get_num_values(ctl);
202 ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
203 if (name != NULL)
204 usb_soundcard_detail_control(mixer, name);
205 }
206 }
207}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700208
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800209static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
210 char *dev_mixer_ctl_name)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700211{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800212 struct mixer_ctl *ctl;
213 unsigned int dev_token;
214 unsigned int pcm_device_number = 0;
215
216 /*
217 * usb_dev_token_id is 32 bit number and is defined as below:
218 * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
219 */
220 dev_token = (card << 16 ) |
221 (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
222
223 ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
224 if (!ctl) {
225 ALOGE("%s: Could not get ctl for mixer cmd - %s",
226 __func__, dev_mixer_ctl_name);
227 return -EINVAL;
228 }
229 mixer_ctl_set_value(ctl, 0, dev_token);
230
231 return 0;
232}
233
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700234static int usb_set_endian_mixer_ctl(int endian, char *endian_mixer_ctl_name)
235{
236 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
237 endian_mixer_ctl_name);
238 if (!ctl) {
239 ALOGE("%s: Could not get ctl for mixer cmd - %s",
240 __func__, endian_mixer_ctl_name);
241 return -EINVAL;
242 }
243
244 switch (endian) {
245 case 0:
246 case 1:
247 mixer_ctl_set_value(ctl, 0, endian);
248 break;
249 default:
250 ALOGW("%s: endianness(%d) not supported",
251 __func__, endian);
252 break;
253 }
254 return 0;
255}
256
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700257static int usb_get_sample_rates(int type, char *rates_str,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800258 struct usb_device_config *config)
259{
260 uint32_t i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700261 char *next_sr_string, *temp_ptr;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800262 uint32_t sr, min_sr, max_sr, sr_size = 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700263
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800264 /* Sample rate string can be in any of the folloing two bit_widthes:
265 * Rates: 8000 - 48000 (continuous)
266 * Rates: 8000, 44100, 48000
267 * Support both the bit_widths
268 */
269 ALOGV("%s: rates_str %s", __func__, rates_str);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700270 next_sr_string = strtok_r(rates_str, "Rates: ", &temp_ptr);
271 if (next_sr_string == NULL) {
272 ALOGE("%s: could not find min rates string", __func__);
273 return -EINVAL;
274 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800275 if (strstr(rates_str, "continuous") != NULL) {
Kuirong Wang591a98a2016-06-27 12:41:41 -0700276 min_sr = (uint32_t)atoi(next_sr_string);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700277 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800278 if (next_sr_string == NULL) {
279 ALOGE("%s: could not find max rates string", __func__);
280 return -EINVAL;
281 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700282 max_sr = (uint32_t)atoi(next_sr_string);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800283
Kuirong Wang591a98a2016-06-27 12:41:41 -0700284 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800285 if (supported_sample_rates[i] >= min_sr &&
Kuirong Wang591a98a2016-06-27 12:41:41 -0700286 supported_sample_rates[i] <= max_sr) {
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800287 // FIXME: we don't support >192KHz in recording path for now
288 if ((supported_sample_rates[i] > SAMPLE_RATE_192000) &&
289 (type == USB_CAPTURE))
290 continue;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800291 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700292 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wang591a98a2016-06-27 12:41:41 -0700293 ALOGI_IF(usb_audio_debug_enable,
294 "%s: continuous sample rate supported_sample_rates[%d] %d",
295 __func__, i, supported_sample_rates[i]);
296 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800297 }
Kuirong Wang591a98a2016-06-27 12:41:41 -0700298 } else {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800299 do {
300 sr = (uint32_t)atoi(next_sr_string);
Weiyin Jiangcba6f962018-03-18 11:52:05 +0800301 // FIXME: we don't support >192KHz in recording path for now
302 if ((sr > SAMPLE_RATE_192000) && (type == USB_CAPTURE)) {
303 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
304 continue;
305 }
306
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800307 for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
308 if (supported_sample_rates[i] == sr) {
309 ALOGI_IF(usb_audio_debug_enable,
310 "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
311 __func__, sr, i, supported_sample_rates[i]);
312 config->rates[sr_size++] = supported_sample_rates[i];
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700313 supported_sample_rates_mask[type] |= (1<<i);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800314 }
315 }
316 next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
317 } while (next_sr_string != NULL);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700318 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800319 config->rate_size = sr_size;
320 return 0;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700321}
322
Garmond Leung5fd0b552018-04-17 11:56:12 -0700323static int usb_get_service_interval(const char *interval_str_start,
324 struct usb_device_config *usb_device_info)
325{
326 unsigned long interval = 0;
327 char time_unit[8] = {0};
328 int multiplier = 0;
329
330 char *eol = strchr(interval_str_start, '\n');
331 if (!eol) {
332 ALOGE("%s: No EOL found", __func__);
333 return -1;
334 }
335 char *tmp = (char *)calloc(1, eol-interval_str_start+1);
336 if (!tmp) {
337 ALOGE("%s: failed to allocate tmp", __func__);
338 return -1;
339 }
340 memcpy(tmp, interval_str_start, eol-interval_str_start);
341 sscanf(tmp, "%lu %2s", &interval, &time_unit[0]);
342 if (!strcmp(time_unit, "us")) {
343 multiplier = 1;
344 } else if (!strcmp(time_unit, "ms")) {
345 multiplier = 1000;
346 } else if (!strcmp(time_unit, "s")) {
347 multiplier = 1000000;
348 } else {
349 ALOGE("%s: unknown time_unit %s, assume default", __func__, time_unit);
350 interval = DEFAULT_SERVICE_INTERVAL_US;
351 multiplier = 1;
352 }
353 interval *= multiplier;
354 ALOGD("%s: set service_interval_us %lu", __func__, interval);
355 usb_device_info->service_interval_us = interval;
356 free(tmp);
357 return 0;
358}
359
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800360static int usb_get_capability(int type,
361 struct usb_card_config *usb_card_info,
362 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700363{
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700364 int32_t size = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800365 int32_t fd=-1;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800366 int32_t channels_no;
Kuirong Wange9894162016-08-26 15:16:39 -0700367 char *str_start = NULL;
368 char *str_end = NULL;
369 char *channel_start = NULL;
370 char *bit_width_start = NULL;
371 char *rates_str_start = NULL;
372 char *target = NULL;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700373 char *read_buf = NULL;
374 char *rates_str = NULL;
Garmond Leung5fd0b552018-04-17 11:56:12 -0700375 char *interval_str_start = NULL;
Kuirong Wange9894162016-08-26 15:16:39 -0700376 char path[128];
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700377 int ret = 0;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800378 char *bit_width_str = NULL;
379 struct usb_device_config * usb_device_info;
Kuirong Wange9894162016-08-26 15:16:39 -0700380 bool check = false;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700381
Kuirong Wange9894162016-08-26 15:16:39 -0700382 memset(path, 0, sizeof(path));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800383 ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
384 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
385
Kuirong Wange9894162016-08-26 15:16:39 -0700386 ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800387 card);
Kuirong Wange9894162016-08-26 15:16:39 -0700388 if(ret < 0) {
389 ALOGE("%s: failed on snprintf (%d) to path %s\n",
390 __func__, ret, path);
391 goto done;
392 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700393
394 fd = open(path, O_RDONLY);
395 if (fd <0) {
396 ALOGE("%s: error failed to open config file %s error: %d\n",
397 __func__, path, errno);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700398 ret = -EINVAL;
399 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700400 }
401
Apoorv Raghuvanshidad3b782014-01-29 15:31:32 -0800402 read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700403
404 if (!read_buf) {
405 ALOGE("Failed to create read_buf");
406 ret = -ENOMEM;
407 goto done;
408 }
409
Kuirong Wange9894162016-08-26 15:16:39 -0700410 if(read(fd, read_buf, USB_BUFF_SIZE) < 0) {
411 ALOGE("file read error\n");
412 goto done;
413 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800414 str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
415 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700416 if (str_start == NULL) {
417 ALOGE("%s: error %s section not found in usb config file",
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800418 __func__, ((type == USB_PLAYBACK) ?
419 PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700420 ret = -EINVAL;
421 goto done;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700422 }
Kuirong Wange9894162016-08-26 15:16:39 -0700423 str_end = strstr(read_buf, ((type == USB_PLAYBACK) ?
424 CAPTURE_PROFILE_STR : PLAYBACK_PROFILE_STR));
425 if (str_end > str_start)
426 check = true;
427
428 ALOGV("%s: usb_config = %s, check %d\n", __func__, str_start, check);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700429
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800430 while (str_start != NULL) {
Kuirong Wange9894162016-08-26 15:16:39 -0700431 str_start = strstr(str_start, "Altset");
432 if ((str_start == NULL) || (check && (str_start >= str_end))) {
433 ALOGV("%s: done parsing %s\n", __func__, str_start);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800434 break;
435 }
Kuirong Wange9894162016-08-26 15:16:39 -0700436 ALOGV("%s: remaining string %s\n", __func__, str_start);
437 str_start += sizeof("Altset");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800438 usb_device_info = calloc(1, sizeof(struct usb_device_config));
439 if (usb_device_info == NULL) {
440 ALOGE("%s: error unable to allocate memory",
441 __func__);
442 ret = -ENOMEM;
443 break;
444 }
Garmond Leung5fd0b552018-04-17 11:56:12 -0700445 usb_device_info->type = type;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800446 /* Bit bit_width parsing */
447 bit_width_start = strstr(str_start, "Format: ");
448 if (bit_width_start == NULL) {
449 ALOGI("%s: Could not find bit_width string", __func__);
450 free(usb_device_info);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700451 continue;
452 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800453 target = strchr(bit_width_start, '\n');
454 if (target == NULL) {
455 ALOGI("%s:end of line not found", __func__);
456 free(usb_device_info);
457 continue;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700458 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800459 size = target - bit_width_start;
460 if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
461 ALOGE("%s: unable to allocate memory to hold bit width strings",
462 __func__);
463 ret = -EINVAL;
464 free(usb_device_info);
465 break;
466 }
467 memcpy(bit_width_str, bit_width_start, size);
468 bit_width_str[size] = '\0';
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700469
470 const char * formats[] = { "S32", "S24_3", "S24", "S16" };
471 const int bit_width[] = { 32, 24, 24, 16};
472 for (size_t i = 0; i < ARRAY_SIZE(formats); i++) {
473 const char * s = strstr(bit_width_str, formats[i]);
474 if (s) {
475 usb_device_info->bit_width = bit_width[i];
476 usb_card_info->endian = strstr(s, "BE") ? 1 : 0;
477 break;
478 }
479 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800480
481 if (bit_width_str)
482 free(bit_width_str);
483
484 /* channels parsing */
485 channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
486 if (channel_start == NULL) {
487 ALOGI("%s: could not find Channels string", __func__);
488 free(usb_device_info);
489 continue;
490 }
491 channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
492 usb_device_info->channels = channels_no;
493
494 /* Sample rates parsing */
495 rates_str_start = strstr(str_start, "Rates: ");
496 if (rates_str_start == NULL) {
497 ALOGI("%s: cant find rates string", __func__);
498 free(usb_device_info);
499 continue;
500 }
501 target = strchr(rates_str_start, '\n');
502 if (target == NULL) {
503 ALOGI("%s: end of line not found", __func__);
504 free(usb_device_info);
505 continue;
506 }
507 size = target - rates_str_start;
508 if ((rates_str = (char *)malloc(size + 1)) == NULL) {
509 ALOGE("%s: unable to allocate memory to hold sample rate strings",
510 __func__);
511 ret = -EINVAL;
512 free(usb_device_info);
513 break;
514 }
515 memcpy(rates_str, rates_str_start, size);
516 rates_str[size] = '\0';
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700517 ret = usb_get_sample_rates(type, rates_str, usb_device_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800518 if (rates_str)
519 free(rates_str);
520 if (ret < 0) {
521 ALOGI("%s: error unable to get sample rate values",
522 __func__);
523 free(usb_device_info);
524 continue;
525 }
Garmond Leung5fd0b552018-04-17 11:56:12 -0700526 // Data packet interval is an optional field.
527 // Assume 0ms interval if this cannot be read
528 // LPASS USB and HLOS USB will figure out the default to use
529 usb_device_info->service_interval_us = DEFAULT_SERVICE_INTERVAL_US;
530 interval_str_start = strstr(str_start, DATA_PACKET_INTERVAL_STR);
531 if (interval_str_start != NULL) {
532 interval_str_start += strlen(DATA_PACKET_INTERVAL_STR);
533 ret = usb_get_service_interval(interval_str_start, usb_device_info);
534 if (ret < 0) {
535 ALOGE("%s: error unable to get service interval, assume default",
536 __func__);
537 }
538 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800539 /* Add to list if every field is valid */
540 list_add_tail(&usb_card_info->usb_device_conf_list,
541 &usb_device_info->list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700542 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700543
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700544done:
545 if (fd >= 0) close(fd);
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -0700546 if (read_buf) free(read_buf);
547 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700548}
549
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800550static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
551 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700552{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800553 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700554
555 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800556 if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
557 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700558 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800559 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700560 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800561 usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700562 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_RX endian");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800563exit:
564
565 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700566}
567
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800568static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
569 int card)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700570{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800571 int ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700572
573 /* get capabilities */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800574 if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
575 ALOGE("%s: could not get Playback capabilities from usb device",
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700576 __func__);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800577 goto exit;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700578 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800579 usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700580 usb_set_endian_mixer_ctl(usb_card_info->endian, "USB_AUDIO_TX endian");
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700581
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800582exit:
583 return ret;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700584}
585
Kuirong Wang1cad7142016-05-24 15:21:56 -0700586static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
587{
588 struct mixer_ctl *ctl;
589 unsigned int index;
590
591 for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
592 usb_card_info->usb_sidetone_index[index] = -1;
593
594 usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
595 for (index = 0;
596 index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
597 index++) {
598 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
599 usb_sidetone_enable_str[index]);
600 if (ctl) {
601 usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
602 /* Disable device sidetone by default */
603 mixer_ctl_set_value(ctl, 0, false);
Aalique Grahame22e49102018-12-18 14:23:57 -0800604 ALOGV("%s: sidetone mixer Control found(%s) ... disabling by default",
605 __func__, usb_sidetone_enable_str[index]);
Kuirong Wang1cad7142016-05-24 15:21:56 -0700606 break;
607 }
608 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800609
610 audio_extn_usb_get_sidetone_volume(usb_card_info);
Kuirong Wang1cad7142016-05-24 15:21:56 -0700611
612 if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
613 usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
614
615 return;
616}
617
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700618static inline bool usb_output_device(audio_devices_t device) {
619 // ignore accessory for now
620 if (device == AUDIO_DEVICE_OUT_USB_ACCESSORY)
621 return false;
622 return audio_is_usb_out_device(device);
623}
624
625static inline bool usb_input_device(audio_devices_t device) {
626 // ignore accessory for now
627 if (device == AUDIO_DEVICE_IN_USB_ACCESSORY)
628 return false;
629 return audio_is_usb_in_device(device);
630}
631
632static bool usb_valid_device(audio_devices_t device)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700633{
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700634 return usb_output_device(device) ||
635 usb_input_device(device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800636}
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700637
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800638static void usb_print_active_device(void){
639 struct listnode *node_i, *node_j;
640 struct usb_device_config *dev_info;
641 struct usb_card_config *card_info;
642 unsigned int i;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700643
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800644 ALOGI("%s", __func__);
645 list_for_each(node_i, &usbmod->usb_card_conf_list) {
646 card_info = node_to_item(node_i, struct usb_card_config, list);
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700647 ALOGI("%s: card_dev_type (0x%x), card_no(%d), %s",
648 __func__, card_info->usb_device_type,
649 card_info->usb_card, card_info->endian ? "BE" : "LE");
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800650 list_for_each(node_j, &card_info->usb_device_conf_list) {
651 dev_info = node_to_item(node_j, struct usb_device_config, list);
652 ALOGI("%s: bit-width(%d) channel(%d)",
Haynes Mathew Georgec8f816c2016-10-25 12:02:02 -0700653 __func__, dev_info->bit_width, dev_info->channels);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800654 for (i = 0; i < dev_info->rate_size; i++)
655 ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
656 }
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700657 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800658}
659
660static bool usb_get_best_match_for_bit_width(
661 struct listnode *dev_list,
662 unsigned int stream_bit_width,
663 unsigned int *bit_width)
664{
665 struct listnode *node_i;
666 struct usb_device_config *dev_info;
667 unsigned int candidate = 0;
668
669 list_for_each(node_i, dev_list) {
670 dev_info = node_to_item(node_i, struct usb_device_config, list);
671 ALOGI_IF(usb_audio_debug_enable,
672 "%s: USB bw(%d), stream bw(%d), candidate(%d)",
673 __func__, dev_info->bit_width,
674 stream_bit_width, candidate);
675 if (dev_info->bit_width == stream_bit_width) {
676 *bit_width = dev_info->bit_width;
677 ALOGV("%s: Found match bit-width (%d)",
678 __func__, dev_info->bit_width);
679 goto exit;
680 } else if (candidate == 0) {
681 candidate = dev_info->bit_width;
682 }
683 /*
684 * If stream bit is 24, USB supports both 16 bit and 32 bit, then
685 * higher bit width 32 is picked up instead of 16-bit
686 */
687 else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
688 ABS_SUB(stream_bit_width, candidate)) {
689 candidate = dev_info->bit_width;
690 }
691 else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
692 ABS_SUB(stream_bit_width, candidate)) &&
693 (dev_info->bit_width > candidate)) {
694 candidate = dev_info->bit_width;
695 }
696 }
697 ALOGV("%s: No match found, use the best candidate bw(%d)",
698 __func__, candidate);
699 *bit_width = candidate;
700exit:
701 return true;
702}
703
704static bool usb_get_best_match_for_channels(
705 struct listnode *dev_list,
706 unsigned int bit_width,
707 unsigned int stream_ch,
708 unsigned int *ch)
709{
710 struct listnode *node_i;
711 struct usb_device_config *dev_info;
712 unsigned int candidate = 0;
713
714 list_for_each(node_i, dev_list) {
715 dev_info = node_to_item(node_i, struct usb_device_config, list);
716 ALOGI_IF(usb_audio_debug_enable,
717 "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
718 __func__, dev_info->channels, dev_info->bit_width,
719 stream_ch, bit_width, candidate);
720 if (dev_info->bit_width != bit_width)
721 continue;
722 if (dev_info->channels== stream_ch) {
723 *ch = dev_info->channels;
724 ALOGV("%s: Found match channels (%d)",
725 __func__, dev_info->channels);
726 goto exit;
727 } else if (candidate == 0)
728 candidate = dev_info->channels;
729 /*
730 * If stream channel is 4, USB supports both 3 and 5, then
731 * higher channel 5 is picked up instead of 3
732 */
733 else if (ABS_SUB(stream_ch, dev_info->channels) <
734 ABS_SUB(stream_ch, candidate)) {
735 candidate = dev_info->channels;
736 } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
737 ABS_SUB(stream_ch, candidate)) &&
738 (dev_info->channels > candidate)) {
739 candidate = dev_info->channels;
740 }
741 }
742 ALOGV("%s: No match found, use the best candidate ch(%d)",
743 __func__, candidate);
744 *ch = candidate;
745exit:
746 return true;
747
748}
749
750static bool usb_sample_rate_multiple(
751 unsigned int stream_sample_rate,
752 unsigned int base)
753{
754 return (((stream_sample_rate / base) * base) == stream_sample_rate);
755}
756
757static bool usb_find_sample_rate_candidate(unsigned int base,
758 unsigned stream_rate,
759 unsigned int usb_rate,
760 unsigned int cur_candidate,
761 unsigned int *update_candidate)
762{
763 /* For sample rate, we should consider fracational sample rate as high priority.
764 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
765 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
766 */
767 if (!usb_sample_rate_multiple(cur_candidate, base) &&
768 usb_sample_rate_multiple(usb_rate, base)) {
769 *update_candidate = usb_rate;
770 } else if (usb_sample_rate_multiple(cur_candidate, base) &&
771 usb_sample_rate_multiple(usb_rate, base)) {
772 if (ABS_SUB(stream_rate, usb_rate) <
773 ABS_SUB(stream_rate, cur_candidate)) {
774 *update_candidate = usb_rate;
775 } else if ((ABS_SUB(stream_rate, usb_rate) ==
776 ABS_SUB(stream_rate, cur_candidate)) &&
777 (usb_rate > cur_candidate)) {
778 *update_candidate = usb_rate;
779 }
780 } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
781 !usb_sample_rate_multiple(usb_rate, base)) {
782 if (ABS_SUB(stream_rate, usb_rate) <
783 ABS_SUB(stream_rate, cur_candidate)) {
784 *update_candidate = usb_rate;
785 } else if ((ABS_SUB(stream_rate, usb_rate) ==
786 ABS_SUB(stream_rate, cur_candidate)) &&
787 (usb_rate > cur_candidate)) {
788 *update_candidate = usb_rate;
789 }
790 }
791 return true;
792}
793
794static bool usb_get_best_match_for_sample_rate(
795 struct listnode *dev_list,
796 unsigned int bit_width,
797 unsigned int ch,
798 unsigned int stream_sample_rate,
Garmond Leung5fd0b552018-04-17 11:56:12 -0700799 unsigned int *sr,
800 unsigned int service_interval,
801 bool do_service_interval_check)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800802{
803 struct listnode *node_i;
804 struct usb_device_config *dev_info;
805 unsigned int candidate = 48000;
806 unsigned int base = SAMPLE_RATE_8000;
807 bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
808 unsigned int i;
809
810 ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
811 __func__, ch, bit_width, stream_sample_rate, multiple_8k);
812
813 list_for_each(node_i, dev_list) {
814 dev_info = node_to_item(node_i, struct usb_device_config, list);
815 ALOGI_IF(usb_audio_debug_enable,
816 "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
817 __func__, dev_info->channels, dev_info->bit_width,
818 ch, bit_width, stream_sample_rate, candidate);
Garmond Leung5fd0b552018-04-17 11:56:12 -0700819
820 if ((dev_info->bit_width != bit_width) ||
821 (dev_info->channels != ch) ||
822 (do_service_interval_check && (dev_info->service_interval_us !=
823 service_interval)))
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800824 continue;
825
826 candidate = 0;
827 for (i = 0; i < dev_info->rate_size; i++) {
828 ALOGI_IF(usb_audio_debug_enable,
829 "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
830 __func__, dev_info->channels,
831 dev_info->bit_width, dev_info->rates[i],
832 ch, bit_width, stream_sample_rate, candidate);
833 if (stream_sample_rate == dev_info->rates[i]) {
834 *sr = dev_info->rates[i];
835 ALOGV("%s: Found match sample rate (%d)",
836 __func__, dev_info->rates[i]);
837 goto exit;
838 } else if (candidate == 0) {
839 candidate = dev_info->rates[i];
840 /*
841 * For sample rate, we should consider fracational sample rate as high priority.
842 * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
843 * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
844 */
845 } else if (multiple_8k) {
846 usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
847 stream_sample_rate,
848 dev_info->rates[i],
849 candidate,
850 &candidate);
851 } else {
852 usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
853 stream_sample_rate,
854 dev_info->rates[i],
855 candidate,
856 &candidate);
857 }
858 }
859 }
860 ALOGV("%s: No match found, use the best candidate sr(%d)",
861 __func__, candidate);
862 *sr = candidate;
863exit:
864 return true;
865}
866
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800867static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
868 unsigned int *bit_width,
869 unsigned int *sample_rate,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530870 unsigned int *ch)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800871{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800872 bool is_usb_supported = true;
873
874 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530875 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800876 if (list_empty(dev_list)) {
877 *sample_rate = 48000;
878 *bit_width = 16;
Ashish Jainb26edfb2016-08-25 00:10:11 +0530879 *ch = 2;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800880 ALOGI("%s: list is empty,fall back to default setting", __func__);
881 goto exit;
882 }
883 usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
884 usb_get_best_match_for_channels(dev_list,
885 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530886 *ch,
887 ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800888 usb_get_best_match_for_sample_rate(dev_list,
889 *bit_width,
Ashish Jainb26edfb2016-08-25 00:10:11 +0530890 *ch,
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800891 *sample_rate,
Garmond Leung5fd0b552018-04-17 11:56:12 -0700892 sample_rate,
893 0 /*service int*/,
894 false /*do service int check*/);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800895exit:
896 ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
Ashish Jainb26edfb2016-08-25 00:10:11 +0530897 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800898 return is_usb_supported;
899}
900
Kuirong Wang1cad7142016-05-24 15:21:56 -0700901void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
902 char *value, int len)
903{
904 int err;
905
906 err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
907 value, len);
908 if (err >= 0) {
909 usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
910 ALOGV("%s: sidetone gain(%s) decimal %d",
911 __func__, value, usb_sidetone_gain);
912 str_parms_del(parms, USB_SIDETONE_GAIN_STR);
913 }
914 return;
915}
916
917int audio_extn_usb_enable_sidetone(int device, bool enable)
918{
919 int ret = -ENODEV;
920 struct listnode *node_i;
921 struct usb_card_config *card_info;
922 int i;
923 ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
924 __func__, device, enable);
925
926 list_for_each(node_i, &usbmod->usb_card_conf_list) {
927 card_info = node_to_item(node_i, struct usb_card_config, list);
928 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
929 __func__, card_info->usb_device_type, card_info->usb_card);
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700930 if (usb_output_device(card_info->usb_device_type)) {
Kuirong Wang1cad7142016-05-24 15:21:56 -0700931 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
932 struct mixer_ctl *ctl = mixer_get_ctl_by_name(
933 card_info->usb_snd_mixer,
934 usb_sidetone_enable_str[i]);
935 if (ctl)
936 mixer_ctl_set_value(ctl, 0, enable);
937 else
938 break;
939
940 if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
Aalique Grahame22e49102018-12-18 14:23:57 -0800941 audio_extn_usb_set_sidetone_volume(card_info, enable, i);
Kuirong Wang1cad7142016-05-24 15:21:56 -0700942 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800943
Kuirong Wang1cad7142016-05-24 15:21:56 -0700944 ret = 0;
945 break;
946 }
947 }
948 }
949 return ret;
950}
951
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800952bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
953 unsigned int *sample_rate,
Kuirong Wange9894162016-08-26 15:16:39 -0700954 unsigned int *ch,
955 bool is_playback)
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800956{
957 struct listnode *node_i;
958 struct usb_card_config *card_info;
959 bool is_usb_supported = false;
960
Kuirong Wang27152a12016-11-11 10:20:30 -0800961 ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d) is_playback(%d)",
962 __func__, *bit_width, *sample_rate, *ch, is_playback);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800963 list_for_each(node_i, &usbmod->usb_card_conf_list) {
964 card_info = node_to_item(node_i, struct usb_card_config, list);
965 ALOGI_IF(usb_audio_debug_enable,
966 "%s: card_dev_type (0x%x), card_no(%d)",
967 __func__, card_info->usb_device_type, card_info->usb_card);
968 /* Currently only apply the first playback sound card configuration */
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700969 if ((is_playback && usb_output_device(card_info->usb_device_type)) ||
970 (!is_playback && usb_input_device(card_info->usb_device_type))){
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800971 is_usb_supported = usb_audio_backend_apply_policy(
972 &card_info->usb_device_conf_list,
973 bit_width,
974 sample_rate,
975 ch);
976 break;
977 }
978 }
Ashish Jainb26edfb2016-08-25 00:10:11 +0530979 ALOGV("%s: updated: bit-width(%d) sample_rate(%d) channels (%d)",
980 __func__, *bit_width, *sample_rate, *ch);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800981
982 return is_usb_supported;
983}
984
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700985int audio_extn_usb_get_max_channels(bool is_playback)
986{
987 struct listnode *node_i, *node_j;
988 struct usb_device_config *dev_info;
989 struct usb_card_config *card_info;
990 unsigned int max_ch = 1;
991 list_for_each(node_i, &usbmod->usb_card_conf_list) {
992 card_info = node_to_item(node_i, struct usb_card_config, list);
993 if (usb_output_device(card_info->usb_device_type) && !is_playback)
994 continue;
995 else if (usb_input_device(card_info->usb_device_type) && is_playback)
996 continue;
997
998 list_for_each(node_j, &card_info->usb_device_conf_list) {
999 dev_info = node_to_item(node_j, struct usb_device_config, list);
1000 max_ch = _MAX(max_ch, dev_info->channels);
1001 }
1002 }
1003
1004 return max_ch;
1005}
1006
1007int audio_extn_usb_get_max_bit_width(bool is_playback)
1008{
1009 struct listnode *node_i, *node_j;
1010 struct usb_device_config *dev_info;
1011 struct usb_card_config *card_info;
1012 unsigned int max_bw = 16;
1013 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1014 card_info = node_to_item(node_i, struct usb_card_config, list);
1015 if (usb_output_device(card_info->usb_device_type) && !is_playback)
1016 continue;
1017 else if (usb_input_device(card_info->usb_device_type) && is_playback)
1018 continue;
1019
1020 list_for_each(node_j, &card_info->usb_device_conf_list) {
1021 dev_info = node_to_item(node_j, struct usb_device_config, list);
1022 max_bw = _MAX(max_bw, dev_info->bit_width);
1023 }
1024 }
1025
1026 return max_bw;
1027}
1028
1029int audio_extn_usb_get_sup_sample_rates(bool is_playback,
1030 uint32_t *sample_rates,
1031 uint32_t sample_rate_size)
1032{
1033 int type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
1034
1035 ALOGV("%s supported_sample_rates_mask 0x%x", __func__, supported_sample_rates_mask[type]);
1036 uint32_t bm = supported_sample_rates_mask[type];
1037 uint32_t tries = _MIN(sample_rate_size, (uint32_t)__builtin_popcount(bm));
1038
1039 int i = 0;
1040 while (tries--) {
1041 int idx = __builtin_ffs(bm) - 1;
1042 sample_rates[i++] = supported_sample_rates[idx];
1043 bm &= ~(1<<idx);
1044 }
1045
1046 return i;
1047}
1048
Ashish Jain3e37a702016-11-25 12:27:15 +05301049bool audio_extn_usb_is_capture_supported()
1050{
1051 if (usbmod == NULL) {
1052 ALOGE("%s: USB device object is NULL", __func__);
1053 return false;
1054 }
1055 ALOGV("%s: capture_supported %d",__func__,usbmod->is_capture_supported);
1056 return usbmod->is_capture_supported;
1057}
1058
Zhou Song6f862822017-11-06 17:27:57 +08001059bool audio_extn_usb_is_tunnel_supported()
1060{
1061 return true;
1062}
1063
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001064void audio_extn_usb_add_device(audio_devices_t device, int card)
1065{
1066 struct usb_card_config *usb_card_info;
1067 char check_debug_enable[PROPERTY_VALUE_MAX];
Kuirong Wang27152a12016-11-11 10:20:30 -08001068 struct listnode *node_i;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001069
Aalique Grahame22e49102018-12-18 14:23:57 -08001070 if ((property_get("vendor.audio.usb.enable.debug",
1071 check_debug_enable, NULL) > 0) ||
1072 (property_get("audio.usb.enable.debug",
1073 check_debug_enable, NULL) > 0)) {
1074 if (atoi(check_debug_enable))
1075 usb_audio_debug_enable = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001076 }
1077
1078 ALOGI_IF(usb_audio_debug_enable,
1079 "%s: parameters device(0x%x), card(%d)",
1080 __func__, device, card);
1081 if (usbmod == NULL) {
1082 ALOGE("%s: USB device object is NULL", __func__);
1083 goto exit;
1084 }
1085
1086 if (!(usb_valid_device(device)) || (card < 0)) {
1087 ALOGE("%s:device(0x%x), card(%d)",
1088 __func__, device, card);
1089 goto exit;
1090 }
1091
Kuirong Wang27152a12016-11-11 10:20:30 -08001092 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1093 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
1094 ALOGI_IF(usb_audio_debug_enable,
1095 "%s: list has capability for card_dev_type (0x%x), card_no(%d)",
1096 __func__, usb_card_info->usb_device_type, usb_card_info->usb_card);
1097 /* If we have cached the capability */
1098 if ((usb_card_info->usb_device_type == device) && (usb_card_info->usb_card == card)) {
1099 ALOGV("%s: capability for device(0x%x), card(%d) is cached, no need to update",
1100 __func__, device, card);
1101 goto exit;
1102 }
1103 }
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001104 usb_card_info = calloc(1, sizeof(struct usb_card_config));
1105 if (usb_card_info == NULL) {
1106 ALOGE("%s: error unable to allocate memory",
1107 __func__);
1108 goto exit;
1109 }
1110 list_init(&usb_card_info->usb_device_conf_list);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001111 if (usb_output_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001112 if (!usb_get_device_pb_config(usb_card_info, card)){
1113 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001114 usb_card_info->usb_device_type = device;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001115 usb_get_sidetone_mixer(usb_card_info);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001116 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1117 goto exit;
1118 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001119 } else if (usb_input_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001120 if (!usb_get_device_cap_config(usb_card_info, card)) {
1121 usb_card_info->usb_card = card;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001122 usb_card_info->usb_device_type = device;
Ashish Jain3e37a702016-11-25 12:27:15 +05301123 usbmod->is_capture_supported = true;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001124 list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
1125 goto exit;
1126 }
1127 }
1128 /* free memory in error case */
1129 if (usb_card_info != NULL)
1130 free(usb_card_info);
1131exit:
1132 if (usb_audio_debug_enable)
1133 usb_print_active_device();
1134 return;
1135}
1136
1137void audio_extn_usb_remove_device(audio_devices_t device, int card)
1138{
1139 struct listnode *node_i, *temp_i;
1140 struct listnode *node_j, *temp_j;
1141 struct usb_device_config *dev_info;
1142 struct usb_card_config *card_info;
1143 unsigned int i;
1144
1145 ALOGV("%s: device(0x%x), card(%d)",
1146 __func__, device, card);
1147
1148 if (usbmod == NULL) {
1149 ALOGE("%s: USB device object is NULL", __func__);
1150 goto exit;
1151 }
1152
1153 if (!(usb_valid_device(device)) || (card < 0)) {
1154 ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
1155 __func__, device, card);
1156 goto exit;
1157 }
1158 list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
1159 card_info = node_to_item(node_i, struct usb_card_config, list);
1160 ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
1161 __func__, card_info->usb_device_type, card_info->usb_card);
1162 if ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
1163 list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
1164 dev_info = node_to_item(node_j, struct usb_device_config, list);
1165 ALOGV("%s: bit-width(%d) channel(%d)",
1166 __func__, dev_info->bit_width, dev_info->channels);
1167 for (i = 0; i < dev_info->rate_size; i++)
1168 ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
1169
1170 list_remove(node_j);
1171 free(node_to_item(node_j, struct usb_device_config, list));
1172 }
1173 list_remove(node_i);
1174 free(node_to_item(node_i, struct usb_card_config, list));
1175 }
1176 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001177 if (audio_is_usb_in_device(device)) { // XXX not sure if we need to check for card
1178 usbmod->is_capture_supported = false;
1179 supported_sample_rates_mask[USB_CAPTURE] = 0;
1180 } else
1181 supported_sample_rates_mask[USB_PLAYBACK] = 0;
1182
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001183exit:
1184 if (usb_audio_debug_enable)
1185 usb_print_active_device();
1186
1187 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001188}
1189
Kevin Rocardfce19002017-08-07 19:21:36 -07001190bool audio_extn_usb_alive(int card) {
1191 char path[PATH_MAX] = {0};
1192 // snprintf should never fail
1193 (void) snprintf(path, sizeof(path), "/proc/asound/card%u/stream0", card);
1194 return access(path, F_OK) == 0;
1195}
1196
Aalique Grahame22e49102018-12-18 14:23:57 -08001197#ifdef USB_BURST_MODE_ENABLED
Garmond Leung5fd0b552018-04-17 11:56:12 -07001198unsigned long audio_extn_usb_find_service_interval(bool min,
1199 bool playback) {
1200 struct usb_card_config *card_info = NULL;
1201 struct usb_device_config *dev_info = NULL;
1202 struct listnode *node_i = NULL;
1203 struct listnode *node_j = NULL;
Aalique Grahame22e49102018-12-18 14:23:57 -08001204 unsigned long interval_us = min ? ULONG_MAX : 0;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001205 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1206 card_info = node_to_item(node_i, struct usb_card_config, list);
1207 list_for_each(node_j, &card_info->usb_device_conf_list) {
1208 dev_info = node_to_item(node_j, struct usb_device_config, list);
1209 bool match = (playback && (dev_info->type == USB_PLAYBACK)) ||
1210 (!playback && (dev_info->type == USB_CAPTURE));
1211 if (match) {
1212 interval_us = min ?
1213 _MIN(interval_us, dev_info->service_interval_us) :
1214 _MAX(interval_us, dev_info->service_interval_us);
1215 }
1216 }
1217 break;
1218 }
1219 return interval_us;
1220}
1221
1222int audio_extn_usb_altset_for_service_interval(bool playback,
1223 unsigned long service_interval,
1224 uint32_t *bit_width,
1225 uint32_t *sample_rate,
1226 uint32_t *channels)
1227{
1228 struct usb_card_config *card_info = NULL;
Aalique Grahame22e49102018-12-18 14:23:57 -08001229 struct usb_device_config *dev_info = NULL;
1230 struct listnode *node_i = NULL;
1231 struct listnode *node_j = NULL;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001232 uint32_t bw = 0;
1233 uint32_t ch = 0;
1234 uint32_t sr = 0;
1235
1236 if (service_interval == 0)
1237 return 0;
1238 /* not a valid service interval to search for */
1239
1240#define FIND_BEST_MATCH(local_var, field, cond) \
1241 list_for_each(node_i, &usbmod->usb_card_conf_list) { \
1242 /* Currently only apply the first playback sound card configuration */ \
1243 card_info = node_to_item(node_i, struct usb_card_config, list); \
1244 list_for_each(node_j, &card_info->usb_device_conf_list) { \
1245 dev_info = node_to_item(node_j, struct usb_device_config, list); \
1246 bool match = (playback && (dev_info->type == USB_PLAYBACK)) || \
1247 (!playback && (dev_info->type == USB_CAPTURE)); \
1248 if (match && (cond)) { \
Garmond Leung003d9ea2018-08-14 17:05:08 -07001249 if (dev_info->field == *field) { \
1250 local_var = dev_info->field; \
1251 break; \
1252 } \
Garmond Leung5fd0b552018-04-17 11:56:12 -07001253 local_var = _MAX(local_var, dev_info->field); \
1254 } \
1255 } \
1256 break; \
1257 }
1258
1259 FIND_BEST_MATCH(bw, bit_width, dev_info->service_interval_us == service_interval);
1260 FIND_BEST_MATCH(ch, channels, \
1261 dev_info->service_interval_us == service_interval && \
1262 dev_info->bit_width == bw);
Garmond Leung003d9ea2018-08-14 17:05:08 -07001263 sr = *sample_rate;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001264 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1265 /* Currently only apply the first playback sound card configuration */
1266 card_info = node_to_item(node_i, struct usb_card_config, list);
1267 if ((playback && usb_output_device(card_info->usb_device_type)) ||
1268 (!playback && usb_input_device(card_info->usb_device_type))) {
1269 usb_get_best_match_for_sample_rate(&card_info->usb_device_conf_list,
1270 bw, ch, sr, &sr,
1271 service_interval,
1272 true);
1273 }
1274 break;
1275 }
1276
1277#define SET_OR_RETURN_ON_ERROR(arg, local_var, cond) \
1278 if (local_var != (cond)) arg = local_var; else return -1;
1279
1280 SET_OR_RETURN_ON_ERROR(*bit_width, bw, 0);
1281 SET_OR_RETURN_ON_ERROR(*sample_rate, sr, 0);
1282 SET_OR_RETURN_ON_ERROR(*channels, ch, 0);
1283 return 0;
1284#undef FIND_BEST_MATCH
1285#undef SET_OR_RETURN_ON_ERROR
1286}
1287
1288int audio_extn_usb_get_service_interval(bool playback,
1289 unsigned long *service_interval)
1290{
1291 const char *ctl_name = "USB_AUDIO_RX service_interval";
1292 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
1293 ctl_name);
1294
1295 if (!playback) {
1296 ALOGE("%s not valid for capture", __func__);
1297 return -1;
1298 }
1299
1300 if (!ctl) {
1301 ALOGV("%s: could not get mixer %s", __func__, ctl_name);
1302 return -1;
1303 }
1304
1305 *service_interval = mixer_ctl_get_value(ctl, 0);
1306 return 0;
1307}
1308
1309int audio_extn_usb_set_service_interval(bool playback,
1310 unsigned long service_interval,
1311 bool *reconfig)
1312{
1313 *reconfig = false;
1314 unsigned long current_service_interval = 0;
1315 const char *ctl_name = "USB_AUDIO_RX service_interval";
1316 struct mixer_ctl *ctl = mixer_get_ctl_by_name(usbmod->adev->mixer,
1317 ctl_name);
1318
1319 if (!playback) {
1320 ALOGE("%s not valid for capture", __func__);
1321 return -1;
1322 }
1323
1324 if (!ctl) {
1325 ALOGV("%s: could not get mixer %s", __func__, ctl_name);
1326 return -1;
1327 }
1328
1329 if (audio_extn_usb_get_service_interval(playback,
1330 &current_service_interval) != 0) {
1331 ALOGE("%s Unable to get current service interval", __func__);
1332 return -1;
1333 }
1334
1335 if (current_service_interval != service_interval) {
1336 mixer_ctl_set_value(ctl, 0, service_interval);
1337 *reconfig = usbmod->usb_reconfig = true;
1338 }
1339 else
1340 *reconfig = usbmod->usb_reconfig = false;
1341 return 0;
1342}
1343
1344int audio_extn_usb_check_and_set_svc_int(struct audio_usecase *uc_info,
1345 bool starting_output_stream)
1346{
1347 struct listnode *node = NULL;
1348 struct audio_usecase *usecase = uc_info;
1349 bool reconfig = false;
1350 bool burst_mode = true;
1351 unsigned long service_interval = 0;
1352 struct audio_device *adev = usbmod->adev;
1353
1354 ALOGV("%s: enter:", __func__);
1355
1356 if ((starting_output_stream == true &&
1357 ((uc_info->id == USECASE_AUDIO_PLAYBACK_MMAP) ||
1358 (uc_info->id == USECASE_AUDIO_PLAYBACK_ULL))) ||
1359 (voice_is_call_state_active(usbmod->adev))) {
1360 burst_mode = false;
1361 } else {
1362 /* set if the valid usecase do not already exist */
1363 list_for_each(node, &adev->usecase_list) {
1364 usecase = node_to_item(node, struct audio_usecase, list);
1365 if (usecase->type == PCM_PLAYBACK &&
1366 audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB )) {
1367 switch (usecase->id) {
1368 case USECASE_AUDIO_PLAYBACK_MMAP:
1369 case USECASE_AUDIO_PLAYBACK_ULL:
1370 {
1371 if (uc_info != usecase) {
1372 //another ULL stream exists
1373 ALOGV("%s: another ULL Stream in active use-case list burst mode = false.", __func__);
1374 burst_mode = false;
1375 } else {
1376 ALOGV("%s:current ULL uc is the same as incoming uc_info \
1377 which means we are stopping the output stream, \
1378 we don't want to set burst mode to false", __func__);
1379 }
1380 break;
1381 }
1382 default:
1383 break;
1384 }
1385 }
1386 }
1387 }
1388
1389 ALOGV("%s: burst mode(%d).", __func__,burst_mode);
1390
1391 service_interval =
1392 audio_extn_usb_find_service_interval(!burst_mode, true /*playback*/);
1393
Yunfei Zhang7728dce2018-10-31 10:20:52 +08001394 audio_extn_usb_set_service_interval(true /*playback*/,
1395 service_interval,
1396 &reconfig);
Garmond Leung5fd0b552018-04-17 11:56:12 -07001397
1398 /* no change or not supported or no active usecases */
1399 if (reconfig)
1400 return -1;
1401 return 0;
1402}
1403
1404bool audio_extn_usb_is_reconfig_req()
1405{
1406 return usbmod->usb_reconfig;
1407}
1408
1409void audio_extn_usb_set_reconfig(bool is_required)
1410{
1411 usbmod->usb_reconfig = is_required;
1412}
Aalique Grahame22e49102018-12-18 14:23:57 -08001413#endif /* USB_BURST_MODE_ENABLED end */
Garmond Leung5fd0b552018-04-17 11:56:12 -07001414
Sharad Sangled0a50b22018-04-05 23:28:32 +05301415bool audio_extn_usb_connected(struct str_parms *parms) {
1416 int card = -1;
1417 struct listnode *node_i = NULL;
1418 struct usb_card_config *usb_card_info = NULL;
1419 bool usb_connected = false;
1420
Weiyin Jiang63831272018-06-28 11:41:01 +08001421 if ((parms != NULL) && str_parms_get_int(parms, "card", &card) >= 0) {
Sharad Sangled0a50b22018-04-05 23:28:32 +05301422 usb_connected = audio_extn_usb_alive(card);
1423 } else {
1424 list_for_each(node_i, &usbmod->usb_card_conf_list) {
1425 usb_card_info = node_to_item(node_i, struct usb_card_config, list);
1426 if (audio_extn_usb_alive(usb_card_info->usb_card)) {
1427 usb_connected = true;
1428 break;
1429 }
1430 }
1431 }
1432 return usb_connected;
1433}
1434
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001435void audio_extn_usb_init(void *adev)
1436{
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001437 if (usbmod == NULL) {
1438 usbmod = calloc(1, sizeof(struct usb_module));
1439 if (usbmod == NULL) {
1440 ALOGE("%s: error unable to allocate memory", __func__);
1441 goto exit;
1442 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001443 } else {
1444 memset(usbmod, 0, sizeof(*usbmod));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001445 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001446
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001447 list_init(&usbmod->usb_card_conf_list);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001448 usbmod->adev = (struct audio_device*)adev;
Kuirong Wang1cad7142016-05-24 15:21:56 -07001449 usbmod->sidetone_gain = usb_sidetone_gain;
Ashish Jain3e37a702016-11-25 12:27:15 +05301450 usbmod->is_capture_supported = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07001451 usbmod->usb_reconfig = false;
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001452exit:
1453 return;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001454}
1455
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001456void audio_extn_usb_deinit(void)
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001457{
1458 if (NULL != usbmod){
1459 free(usbmod);
1460 usbmod = NULL;
1461 }
1462}
Aalique Grahame22e49102018-12-18 14:23:57 -08001463
1464#ifdef USB_SIDETONE_VOLUME
1465static const char * const usb_sidetone_volume_str[] = {
1466 "Sidetone Playback Volume",
1467 "Mic Playback Volume",
1468};
1469
1470static int usb_get_sidetone_gain(struct usb_card_config *card_info)
1471{
1472 int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
1473 if (gain > card_info->usb_sidetone_vol_max)
1474 gain = card_info->usb_sidetone_vol_max;
1475 return gain;
1476}
1477
1478void audio_extn_usb_get_sidetone_volume(struct usb_card_config *usb_card_info)
1479{
1480 struct mixer_ctl *ctl;
1481 unsigned int index;
1482
1483 for (index = 0;
1484 index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
1485 index++) {
1486 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
1487 usb_sidetone_volume_str[index]);
1488 if (ctl) {
1489 usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
1490 usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
1491 usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
1492 break;
1493 }
1494 }
1495}
1496
1497void audio_extn_usb_set_sidetone_volume(struct usb_card_config *usb_card_info,
1498 bool enable, int index)
1499{
1500 struct mixer_ctl *ctl;
1501
1502 ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
1503 usb_sidetone_volume_str[index]);
1504
1505 if (ctl == NULL)
1506 ALOGV("%s: sidetone gain mixer command is not found",
1507 __func__);
1508 else if (enable)
1509 mixer_ctl_set_value(ctl, 0,
1510 usb_get_sidetone_gain(usb_card_info));
1511}
1512#endif /* USB_SIDETONE_VOLUME end */
1513#endif /* USB_TUNNEL_ENABLED end */