1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "alsa_device_profile"
18 /*#define LOG_NDEBUG 0*/
19 /*#define LOG_PCM_PARAMS 0*/
20
21 #include <errno.h>
22 #include <inttypes.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <cutils/properties.h>
26
27 #include <log/log.h>
28
29 #include "include/alsa_device_profile.h"
30 #include "include/alsa_format.h"
31 #include "include/alsa_logging.h"
32
33 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
34
35 #define PERIOD_DURATION_US (5 * 1000)
36
37 #define DEFAULT_PERIOD_SIZE 1024
38
39 static const char * const format_string_map[] = {
40 "AUDIO_FORMAT_PCM_16_BIT", /* "PCM_FORMAT_S16_LE", */
41 "AUDIO_FORMAT_PCM_32_BIT", /* "PCM_FORMAT_S32_LE", */
42 "AUDIO_FORMAT_PCM_8_BIT", /* "PCM_FORMAT_S8", */
43 "AUDIO_FORMAT_PCM_8_24_BIT", /* "PCM_FORMAT_S24_LE", */
44 "AUDIO_FORMAT_PCM_24_BIT_PACKED"/* "PCM_FORMAT_S24_3LE" */
45 };
46
47 extern int8_t const pcm_format_value_map[50];
48
49 /* Sort these in terms of preference (best first).
50 192 kHz is not first because it requires significant resources for possibly worse
51 quality and driver instability (depends on device).
52 The order here determines the default sample rate for the device.
53 AudioPolicyManager may not respect this ordering when picking sample rates.
54 Update MAX_PROFILE_SAMPLE_RATES after changing the array size.
55
56 TODO: remove 32000, 22050, 12000, 11025? Each sample rate check
57 requires opening the device which may cause pops. */
58 static const unsigned std_sample_rates[] =
59 {96000, 88200, 192000, 176400, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
60
profile_reset(alsa_device_profile * profile)61 static void profile_reset(alsa_device_profile* profile)
62 {
63 profile->card = profile->device = -1;
64 profile->extra_latency_ms = 0;
65
66 /* terminate the attribute arrays with invalid values */
67 profile->formats[0] = PCM_FORMAT_INVALID;
68 profile->sample_rates[0] = 0;
69 profile->channel_counts[0] = 0;
70
71 profile->min_period_size = profile->max_period_size = 0;
72 profile->min_channel_count = profile->max_channel_count = DEFAULT_CHANNEL_COUNT;
73
74 profile->is_valid = false;
75 }
76
profile_init(alsa_device_profile * profile,int direction)77 void profile_init(alsa_device_profile* profile, int direction)
78 {
79 profile->direction = direction;
80 profile_reset(profile);
81 }
82
profile_is_initialized(const alsa_device_profile * profile)83 bool profile_is_initialized(const alsa_device_profile* profile)
84 {
85 return profile->card >= 0 && profile->device >= 0;
86 }
87
profile_is_valid(const alsa_device_profile * profile)88 bool profile_is_valid(const alsa_device_profile* profile) {
89 return profile->is_valid;
90 }
91
profile_is_cached_for(const alsa_device_profile * profile,int card,int device)92 bool profile_is_cached_for(const alsa_device_profile* profile, int card, int device) {
93 return card == profile->card && device == profile->device;
94 }
95
profile_decache(alsa_device_profile * profile)96 void profile_decache(alsa_device_profile* profile) {
97 profile_reset(profile);
98 }
99
100 /*
101 * Returns the supplied value rounded up to the next even multiple of 16
102 */
round_to_16_mult(unsigned int size)103 static unsigned int round_to_16_mult(unsigned int size)
104 {
105 return (size + 15) & ~15; /* 0xFFFFFFF0; */
106 }
107
108 /*
109 * Returns the system defined minimum period size based on the supplied sample rate.
110 */
profile_calc_min_period_size(const alsa_device_profile * profile,unsigned sample_rate)111 unsigned profile_calc_min_period_size(const alsa_device_profile* profile, unsigned sample_rate)
112 {
113 ALOGV("profile_calc_min_period_size(%p, rate:%d)", profile, sample_rate);
114 if (profile == NULL) {
115 return DEFAULT_PERIOD_SIZE;
116 } else {
117 unsigned period_us = property_get_int32("ro.audio.usb.period_us", PERIOD_DURATION_US);
118 unsigned num_sample_frames = ((uint64_t)sample_rate * period_us) / 1000000;
119
120 if (num_sample_frames < profile->min_period_size) {
121 num_sample_frames = profile->min_period_size;
122 }
123 return round_to_16_mult(num_sample_frames);
124 }
125 }
126
profile_get_period_size(const alsa_device_profile * profile,unsigned sample_rate)127 unsigned int profile_get_period_size(const alsa_device_profile* profile, unsigned sample_rate)
128 {
129 unsigned int period_size = profile_calc_min_period_size(profile, sample_rate);
130 ALOGV("profile_get_period_size(rate:%d) = %d", sample_rate, period_size);
131 return period_size;
132 }
133
134 /*
135 * Sample Rate
136 */
profile_get_default_sample_rate(const alsa_device_profile * profile)137 unsigned profile_get_default_sample_rate(const alsa_device_profile* profile)
138 {
139 /*
140 * This is probably a poor algorithm. The default sample rate should be the highest (within
141 * limits) rate that is available for both input and output. HOWEVER, the profile has only
142 * one or the other, so that will need to be done at a higher level, like in the HAL.
143 */
144 /*
145 * TODO this won't be right in general. we should store a preferred rate as we are scanning.
146 * But right now it will return the highest rate, which may be correct.
147 */
148 return profile_is_valid(profile) ? profile->sample_rates[0] : DEFAULT_SAMPLE_RATE;
149 }
150
profile_get_highest_sample_rate(const alsa_device_profile * profile)151 unsigned profile_get_highest_sample_rate(const alsa_device_profile* profile) {
152 /* The hightest sample rate is always stored in the first element of sample_rates.
153 * Note that profile_reset() initiaizes the first element of samples_rates to 0
154 * Which is what we want to return if the profile had not been read anyway.
155 */
156 return profile->sample_rates[0];
157 }
158
profile_is_sample_rate_valid(const alsa_device_profile * profile,unsigned rate)159 bool profile_is_sample_rate_valid(const alsa_device_profile* profile, unsigned rate)
160 {
161 if (profile_is_valid(profile)) {
162 size_t index;
163 for (index = 0; profile->sample_rates[index] != 0; index++) {
164 if (profile->sample_rates[index] == rate) {
165 return true;
166 }
167 }
168
169 return false;
170 } else {
171 ALOGW("**** PROFILE NOT VALID!");
172 return rate == DEFAULT_SAMPLE_RATE;
173 }
174 }
175
176 /*
177 * Format
178 */
profile_get_default_format(const alsa_device_profile * profile)179 enum pcm_format profile_get_default_format(const alsa_device_profile* profile)
180 {
181 /*
182 * TODO this won't be right in general. we should store a preferred format as we are scanning.
183 */
184 return profile_is_valid(profile) ? profile->formats[0] : DEFAULT_SAMPLE_FORMAT;
185 }
186
profile_is_format_valid(const alsa_device_profile * profile,enum pcm_format fmt)187 bool profile_is_format_valid(const alsa_device_profile* profile, enum pcm_format fmt) {
188 if (profile_is_valid(profile)) {
189 size_t index;
190 for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
191 if (profile->formats[index] == fmt) {
192 return true;
193 }
194 }
195
196 return false;
197 } else {
198 return fmt == DEFAULT_SAMPLE_FORMAT;
199 }
200 }
201
202 /*
203 * Channels
204 */
profile_get_default_channel_count(const alsa_device_profile * profile)205 unsigned profile_get_default_channel_count(const alsa_device_profile* profile)
206 {
207 return profile_is_valid(profile) ? profile->channel_counts[0] : DEFAULT_CHANNEL_COUNT;
208 }
209
profile_get_closest_channel_count(const alsa_device_profile * profile,unsigned count)210 unsigned profile_get_closest_channel_count(const alsa_device_profile* profile, unsigned count)
211 {
212 if (profile_is_valid(profile)) {
213 if (count < profile->min_channel_count) {
214 return profile->min_channel_count;
215 } else if (count > profile->max_channel_count) {
216 return profile->max_channel_count;
217 } else {
218 return count;
219 }
220 } else {
221 return 0;
222 }
223 }
224
profile_is_channel_count_valid(const alsa_device_profile * profile,unsigned count)225 bool profile_is_channel_count_valid(const alsa_device_profile* profile, unsigned count)
226 {
227 if (profile_is_initialized(profile)) {
228 return count >= profile->min_channel_count && count <= profile->max_channel_count;
229 } else {
230 return count == DEFAULT_CHANNEL_COUNT;
231 }
232 }
233
profile_test_sample_rate(const alsa_device_profile * profile,unsigned rate)234 static bool profile_test_sample_rate(const alsa_device_profile* profile, unsigned rate)
235 {
236 struct pcm_config config = profile->default_config;
237 config.rate = rate;
238 // This method tests whether a sample rate is supported by the USB device
239 // by attempting to open it.
240 //
241 // The profile default_config currently contains the minimum channel count.
242 // As some usb devices cannot sustain the sample rate across all its supported
243 // channel counts, we try the largest usable channel count. This is
244 // bounded by FCC_LIMIT.
245 //
246 // If config.channels > FCC_LIMIT then we still test it for sample rate compatibility.
247 // It is possible that the USB device does not support less than a certain number
248 // of channels, and that minimum number is > FCC_LIMIT. Then the default_config
249 // channels will be > FCC_LIMIT (and we still proceed with the test).
250 //
251 // For example, the FocusRite Scarlett 18i20 supports between 16 to 20 playback
252 // channels and between 14 to 18 capture channels.
253 // If FCC_LIMIT is 8, we still need to use and test 16 output channels for playback
254 // and 14 input channels for capture, as that will be the ALSA opening configuration.
255 // The Android USB audio HAL layer will automatically zero pad to accommodate the
256 // 16 playback or 14 capture channel configuration from the (up to FCC_LIMIT)
257 // channels delivered by AudioFlinger.
258 if (config.channels < FCC_LIMIT) {
259 config.channels = profile->max_channel_count;
260 if (config.channels > FCC_LIMIT) config.channels = FCC_LIMIT;
261 }
262 bool works = false; /* let's be pessimistic */
263 struct pcm * pcm = pcm_open(profile->card, profile->device,
264 profile->direction, &config);
265
266 if (pcm != NULL) {
267 works = pcm_is_ready(pcm);
268 pcm_close(pcm);
269 }
270
271 return works;
272 }
273
profile_enum_sample_rates(alsa_device_profile * profile,unsigned min,unsigned max)274 static unsigned profile_enum_sample_rates(alsa_device_profile* profile, unsigned min, unsigned max)
275 {
276 unsigned num_entries = 0;
277 unsigned index;
278
279 for (index = 0; index < ARRAY_SIZE(std_sample_rates) &&
280 num_entries < ARRAY_SIZE(profile->sample_rates) - 1;
281 index++) {
282 if (std_sample_rates[index] >= min && std_sample_rates[index] <= max
283 && profile_test_sample_rate(profile, std_sample_rates[index])) {
284 profile->sample_rates[num_entries++] = std_sample_rates[index];
285 }
286 }
287 profile->sample_rates[num_entries] = 0; /* terminate */
288 return num_entries; /* return # of supported rates */
289 }
290
profile_enum_sample_formats(alsa_device_profile * profile,const struct pcm_mask * mask)291 static unsigned profile_enum_sample_formats(alsa_device_profile* profile,
292 const struct pcm_mask * mask)
293 {
294 const int num_slots = ARRAY_SIZE(mask->bits);
295 const int bits_per_slot = sizeof(mask->bits[0]) * 8;
296
297 const int table_size = ARRAY_SIZE(pcm_format_value_map);
298
299 int slot_index, bit_index, table_index;
300 table_index = 0;
301 int num_written = 0;
302 for (slot_index = 0; slot_index < num_slots && table_index < table_size;
303 slot_index++) {
304 unsigned bit_mask = 1;
305 for (bit_index = 0;
306 bit_index < bits_per_slot && table_index < table_size;
307 bit_index++) {
308 if ((mask->bits[slot_index] & bit_mask) != 0) {
309 enum pcm_format format = pcm_format_value_map[table_index];
310 /* Never return invalid (unrecognized) or 8-bit */
311 if (format != PCM_FORMAT_INVALID && format != PCM_FORMAT_S8) {
312 profile->formats[num_written++] = format;
313 if (num_written == ARRAY_SIZE(profile->formats) - 1) {
314 /* leave at least one PCM_FORMAT_INVALID at the end */
315 goto end;
316 }
317 }
318 }
319 bit_mask <<= 1;
320 table_index++;
321 }
322 }
323 end:
324 profile->formats[num_written] = PCM_FORMAT_INVALID;
325 return num_written;
326 }
327
profile_enum_channel_counts(alsa_device_profile * profile,unsigned min,unsigned max)328 static unsigned profile_enum_channel_counts(alsa_device_profile* profile, unsigned min,
329 unsigned max)
330 {
331 /* modify alsa_device_profile.h if you change the std_channel_counts[] array. */
332 // The order of this array controls the order for channel mask generation.
333 // In general, this is just counting from max to min not skipping anything,
334 // but need not be that way.
335 static const unsigned std_channel_counts[FCC_24] = {
336 24, 23, 22, 21, 20, 19, 18, 17,
337 16, 15, 14, 13, 12, 11, 10, 9,
338 8, 7, 6, 5, 4, 3, 2, 1
339 };
340
341 unsigned num_counts = 0;
342 unsigned index;
343 int max_allowed_index = -1; // index of maximum allowed channel count reported by device.
344 /* TODO write a profile_test_channel_count() */
345 /* Ensure there is at least one invalid channel count to terminate the channel counts array */
346 for (index = 0; index < ARRAY_SIZE(std_channel_counts) &&
347 num_counts < ARRAY_SIZE(profile->channel_counts) - 1;
348 index++) {
349 const unsigned test_count = std_channel_counts[index];
350 /* TODO Do we want a channel counts test? */
351 if (test_count <= FCC_LIMIT) {
352 if (test_count >= min && test_count <= max /* &&
353 profile_test_channel_count(profile, channel_counts[index])*/) {
354 profile->channel_counts[num_counts++] = test_count;
355 }
356 if (max_allowed_index < 0 ||
357 std_channel_counts[max_allowed_index] < test_count) {
358 max_allowed_index = index;
359 }
360 }
361 }
362 // if we have no match with the standard counts, we use the largest (preferred) std count.
363 // Note: the usb hal will adjust channel data properly to fit.
364 if (num_counts == 0 && max_allowed_index >= 0) {
365 ALOGW("usb device does not match std channel counts, setting to %d",
366 std_channel_counts[max_allowed_index]);
367 profile->channel_counts[num_counts++] = std_channel_counts[max_allowed_index];
368 }
369 profile->channel_counts[num_counts] = 0;
370 return num_counts; /* return # of supported counts */
371 }
372
373 /*
374 * Reads and decodes configuration info from the specified ALSA card/device.
375 */
read_alsa_device_config(alsa_device_profile * profile,struct pcm_config * config)376 static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_config * config)
377 {
378 ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
379 profile->card, profile->device, profile->direction);
380
381 if (profile->card < 0 || profile->device < 0) {
382 return -EINVAL;
383 }
384
385 struct pcm_params * alsa_hw_params =
386 pcm_params_get(profile->card, profile->device, profile->direction);
387 if (alsa_hw_params == NULL) {
388 return -EINVAL;
389 }
390
391 profile->min_period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
392 profile->max_period_size = pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
393
394 profile->min_channel_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
395 profile->max_channel_count = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS);
396
397 int ret = 0;
398
399 /*
400 * This Logging will be useful when testing new USB devices.
401 */
402 #ifdef LOG_PCM_PARAMS
403 log_pcm_params(alsa_hw_params);
404 #endif
405
406 config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
407 // For output devices, let's make sure we choose at least stereo
408 // (assuming the device supports it).
409 if (profile->direction == PCM_OUT &&
410 config->channels < 2 && pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS) >= 2) {
411 config->channels = 2;
412 }
413 config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
414 // Prefer 48K or 44.1K
415 if (config->rate < 48000 &&
416 pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE) >= 48000) {
417 config->rate = 48000;
418 } else if (config->rate < 44100 &&
419 pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE) >= 44100) {
420 config->rate = 44100;
421 }
422 config->period_size = profile_calc_min_period_size(profile, config->rate);
423 config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
424 config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
425 #ifdef LOG_PCM_PARAMS
426 log_pcm_config(config, "read_alsa_device_config");
427 #endif
428 if (config->format == PCM_FORMAT_INVALID) {
429 ret = -EINVAL;
430 }
431
432 pcm_params_free(alsa_hw_params);
433
434 return ret;
435 }
436
profile_fill_builtin_device_info(alsa_device_profile * profile,struct pcm_config * config,unsigned buffer_frame_count)437 bool profile_fill_builtin_device_info(alsa_device_profile* profile, struct pcm_config* config,
438 unsigned buffer_frame_count) {
439 if (!profile_is_initialized(profile)) {
440 return false;
441 }
442 profile->extra_latency_ms = property_get_int32(
443 "ro.hardware.audio.tinyalsa.host_latency_ms", 0);
444 profile->default_config.channels = config->channels;
445 profile->default_config.rate = config->rate;
446 profile->default_config.format = config->format;
447 int period_count = property_get_int32(
448 "ro.hardware.audio.tinyalsa.period_count", DEFAULT_PERIOD_COUNT);
449 if (period_count <= 0) period_count = DEFAULT_PERIOD_COUNT;
450 profile->default_config.period_count = period_count;
451 int period_size_multiplier = property_get_int32(
452 "ro.hardware.audio.tinyalsa.period_size_multiplier", 1);
453 if (period_size_multiplier <= 0) period_size_multiplier = 1;
454 profile->default_config.period_size =
455 period_size_multiplier * buffer_frame_count / period_count;
456 profile->min_period_size = profile->max_period_size = profile->default_config.period_size;
457 profile->formats[0] = config->format;
458 profile->formats[1] = PCM_FORMAT_INVALID;
459 profile->channel_counts[0] = config->channels;
460 profile->channel_counts[1] = 0;
461 profile->min_channel_count = profile->max_channel_count = config->channels;
462 profile->sample_rates[0] = config->rate;
463 profile->sample_rates[1] = 0;
464 profile->is_valid = true;
465 return true;
466 }
467
profile_read_device_info(alsa_device_profile * profile)468 bool profile_read_device_info(alsa_device_profile* profile)
469 {
470 if (!profile_is_initialized(profile)) {
471 return false;
472 }
473
474 /* let's get some defaults */
475 read_alsa_device_config(profile, &profile->default_config);
476 ALOGV("default_config chans:%d rate:%d format:%d count:%d size:%d",
477 profile->default_config.channels, profile->default_config.rate,
478 profile->default_config.format, profile->default_config.period_count,
479 profile->default_config.period_size);
480
481 struct pcm_params * alsa_hw_params = pcm_params_get(profile->card,
482 profile->device,
483 profile->direction);
484 if (alsa_hw_params == NULL) {
485 return false;
486 }
487
488 /* Formats */
489 const struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
490 profile_enum_sample_formats(profile, format_mask);
491
492 /* Channels */
493 profile_enum_channel_counts(
494 profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
495 pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
496
497 /* Sample Rates */
498 profile_enum_sample_rates(
499 profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
500 pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
501
502 profile->is_valid = true;
503
504 pcm_params_free(alsa_hw_params);
505 return true;
506 }
507
profile_get_sample_rate_strs(const alsa_device_profile * profile)508 char * profile_get_sample_rate_strs(const alsa_device_profile* profile)
509 {
510 /* if we assume that rate strings are about 5 characters (48000 is 5), plus ~1 for a
511 * delimiter "|" this buffer has room for about 22 rate strings which seems like
512 * way too much, but it's a stack variable so only temporary.
513 */
514 char buffer[128];
515 buffer[0] = '\0';
516 size_t buffSize = ARRAY_SIZE(buffer);
517 size_t curStrLen = 0;
518
519 char numBuffer[32];
520
521 size_t numEntries = 0;
522 size_t index;
523 for (index = 0; profile->sample_rates[index] != 0; index++) {
524 snprintf(numBuffer, sizeof(numBuffer), "%u", profile->sample_rates[index]);
525 // account for both the null, and potentially the bar.
526 if (buffSize - curStrLen < strlen(numBuffer) + (numEntries != 0 ? 2 : 1)) {
527 /* we don't have room for another, so bail at this point rather than
528 * return a malformed rate string
529 */
530 break;
531 }
532 if (numEntries++ != 0) {
533 strlcat(buffer, "|", buffSize);
534 }
535 curStrLen = strlcat(buffer, numBuffer, buffSize);
536 }
537
538 return strdup(buffer);
539 }
540
profile_get_format_strs(const alsa_device_profile * profile)541 char * profile_get_format_strs(const alsa_device_profile* profile)
542 {
543 /* if we assume that format strings are about 24 characters (AUDIO_FORMAT_PCM_16_BIT is 23),
544 * plus ~1 for a delimiter "|" this buffer has room for about 10 format strings which seems
545 * like way too much, but it's a stack variable so only temporary.
546 */
547 char buffer[256];
548 buffer[0] = '\0';
549 size_t buffSize = ARRAY_SIZE(buffer);
550 size_t curStrLen = 0;
551
552 size_t numEntries = 0;
553 size_t index = 0;
554 for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
555 // account for both the null, and potentially the bar.
556 if (buffSize - curStrLen < strlen(format_string_map[profile->formats[index]])
557 + (numEntries != 0 ? 2 : 1)) {
558 /* we don't have room for another, so bail at this point rather than
559 * return a malformed rate string
560 */
561 break;
562 }
563 if (numEntries++ != 0) {
564 strlcat(buffer, "|", buffSize);
565 }
566 curStrLen = strlcat(buffer, format_string_map[profile->formats[index]], buffSize);
567 }
568
569 return strdup(buffer);
570 }
571
profile_get_channel_count_strs(const alsa_device_profile * profile)572 char * profile_get_channel_count_strs(const alsa_device_profile* profile)
573 {
574 // we use only the canonical even number channel position masks.
575 static const char * const out_chans_strs[] = {
576 [0] = "AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
577 [1] = "AUDIO_CHANNEL_OUT_MONO",
578 [2] = "AUDIO_CHANNEL_OUT_STEREO",
579 [4] = "AUDIO_CHANNEL_OUT_QUAD",
580 [6] = "AUDIO_CHANNEL_OUT_5POINT1",
581 [FCC_8] = "AUDIO_CHANNEL_OUT_7POINT1",
582 [FCC_12] = "AUDIO_CHANNEL_OUT_7POINT1POINT4",
583 [FCC_24] = "AUDIO_CHANNEL_OUT_22POINT2",
584 };
585
586 static const char * const in_chans_strs[] = {
587 [0] = "AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
588 [1] = "AUDIO_CHANNEL_IN_MONO",
589 [2] = "AUDIO_CHANNEL_IN_STEREO",
590 /* channel counts greater than this not considered */
591 };
592
593 static const char * const index_chans_strs[] = {
594 [0] = "AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
595
596 [1] = "AUDIO_CHANNEL_INDEX_MASK_1",
597 [2] = "AUDIO_CHANNEL_INDEX_MASK_2",
598 [3] = "AUDIO_CHANNEL_INDEX_MASK_3",
599 [4] = "AUDIO_CHANNEL_INDEX_MASK_4",
600 [5] = "AUDIO_CHANNEL_INDEX_MASK_5",
601 [6] = "AUDIO_CHANNEL_INDEX_MASK_6",
602 [7] = "AUDIO_CHANNEL_INDEX_MASK_7",
603 [8] = "AUDIO_CHANNEL_INDEX_MASK_8",
604
605 [9] = "AUDIO_CHANNEL_INDEX_MASK_9",
606 [10] = "AUDIO_CHANNEL_INDEX_MASK_10",
607 [11] = "AUDIO_CHANNEL_INDEX_MASK_11",
608 [12] = "AUDIO_CHANNEL_INDEX_MASK_12",
609 [13] = "AUDIO_CHANNEL_INDEX_MASK_13",
610 [14] = "AUDIO_CHANNEL_INDEX_MASK_14",
611 [15] = "AUDIO_CHANNEL_INDEX_MASK_15",
612 [16] = "AUDIO_CHANNEL_INDEX_MASK_16",
613
614 [17] = "AUDIO_CHANNEL_INDEX_MASK_17",
615 [18] = "AUDIO_CHANNEL_INDEX_MASK_18",
616 [19] = "AUDIO_CHANNEL_INDEX_MASK_19",
617 [20] = "AUDIO_CHANNEL_INDEX_MASK_20",
618 [21] = "AUDIO_CHANNEL_INDEX_MASK_21",
619 [22] = "AUDIO_CHANNEL_INDEX_MASK_22",
620 [23] = "AUDIO_CHANNEL_INDEX_MASK_23",
621 [24] = "AUDIO_CHANNEL_INDEX_MASK_24",
622 };
623
624 const bool isOutProfile = profile->direction == PCM_OUT;
625
626 const char * const * const chans_strs = isOutProfile ? out_chans_strs : in_chans_strs;
627 size_t chans_strs_size =
628 isOutProfile ? ARRAY_SIZE(out_chans_strs) : ARRAY_SIZE(in_chans_strs);
629 if (chans_strs_size > FCC_LIMIT + 1) chans_strs_size = FCC_LIMIT + 1; // starts with 0.
630
631 /*
632 * MAX_CHANNEL_NAME_LEN: The longest channel name so far is "AUDIO_CHANNEL_OUT_7POINT1POINT4"
633 * at 31 chars, add 1 for the "|" delimiter, so we allocate 48 chars to be safe.
634 *
635 * We allocate room for channel index and channel position strings (2x).
636 */
637 const size_t MAX_CHANNEL_NAME_LEN = 48;
638 char buffer[MAX_CHANNEL_NAME_LEN * (FCC_LIMIT * 2) + 1];
639 buffer[0] = '\0';
640 size_t buffSize = ARRAY_SIZE(buffer);
641 size_t curStrLen = 0;
642
643 /* We currently support MONO and STEREO, and always report STEREO but some (many)
644 * USB Audio Devices may only announce support for MONO (a headset mic for example), or
645 * The total number of output channels. SO, if the device itself doesn't explicitly
646 * support STEREO, append to the channel config strings we are generating.
647 *
648 * The MONO and STEREO positional channel masks are provided for legacy compatibility.
649 * For multichannel (n > 2) we only expose channel index masks.
650 */
651 // Always support stereo
652 curStrLen = strlcat(buffer, chans_strs[2], buffSize);
653
654 size_t index;
655 unsigned channel_count;
656 for (index = 0;
657 (channel_count = profile->channel_counts[index]) != 0;
658 index++) {
659
660 if (channel_count > FCC_LIMIT) continue;
661
662 /* we only show positional information for mono (stereo handled already) */
663 if (channel_count < chans_strs_size
664 && chans_strs[channel_count] != NULL
665 && channel_count < 2 /* positional only for fewer than 2 channels */) {
666 // account for the '|' and the '\0'
667 if (buffSize - curStrLen < strlen(chans_strs[channel_count]) + 2) {
668 /* we don't have room for another, so bail at this point rather than
669 * return a malformed rate string
670 */
671 break;
672 }
673
674 if (curStrLen != 0) strlcat(buffer, "|", buffSize);
675 curStrLen = strlcat(buffer, chans_strs[channel_count], buffSize);
676 }
677
678 // handle channel index masks for both input and output
679 // +2 to account for the '|' and the '\0'
680 if (buffSize - curStrLen < strlen(index_chans_strs[channel_count]) + 2) {
681 /* we don't have room for another, so bail at this point rather than
682 * return a malformed rate string
683 */
684 break;
685 }
686
687 if (curStrLen != 0) strlcat(buffer, "|", buffSize);
688 curStrLen = strlcat(buffer, index_chans_strs[channel_count], buffSize);
689 }
690
691 return strdup(buffer);
692 }
693
profile_dump(const alsa_device_profile * profile,int fd)694 void profile_dump(const alsa_device_profile* profile, int fd)
695 {
696 if (profile == NULL) {
697 dprintf(fd, " %s\n", "No USB Profile");
698 return; /* bail early */
699 }
700
701 if (!profile->is_valid) {
702 dprintf(fd, " Profile is INVALID");
703 }
704
705 /* card/device/direction */
706 dprintf(fd, " card:%d, device:%d - %s\n",
707 profile->card, profile->device, profile->direction == PCM_OUT ? "OUT" : "IN");
708
709 /* formats */
710 dprintf(fd, " Formats: ");
711 for (int fmtIndex = 0;
712 fmtIndex < MAX_PROFILE_FORMATS && profile->formats[fmtIndex] != PCM_FORMAT_INVALID;
713 fmtIndex++) {
714 dprintf(fd, "%d ", profile->formats[fmtIndex]);
715 }
716 dprintf(fd, "\n");
717
718 /* sample rates */
719 dprintf(fd, " Rates: ");
720 for (int rateIndex = 0;
721 rateIndex < MAX_PROFILE_SAMPLE_RATES && profile->sample_rates[rateIndex] != 0;
722 rateIndex++) {
723 dprintf(fd, "%u ", profile->sample_rates[rateIndex]);
724 }
725 dprintf(fd, "\n");
726
727 // channel counts
728 dprintf(fd, " Channel Counts: ");
729 for (int cntIndex = 0;
730 cntIndex < MAX_PROFILE_CHANNEL_COUNTS && profile->channel_counts[cntIndex] != 0;
731 cntIndex++) {
732 dprintf(fd, "%u ", profile->channel_counts[cntIndex]);
733 }
734 dprintf(fd, "\n");
735
736 dprintf(fd, " min/max period size [%u : %u]\n",
737 profile->min_period_size,profile-> max_period_size);
738 dprintf(fd, " min/max channel count [%u : %u]\n",
739 profile->min_channel_count, profile->max_channel_count);
740
741 // struct pcm_config default_config;
742 dprintf(fd, " Default Config:\n");
743 dprintf(fd, " channels: %d\n", profile->default_config.channels);
744 dprintf(fd, " rate: %d\n", profile->default_config.rate);
745 dprintf(fd, " period_size: %d\n", profile->default_config.period_size);
746 dprintf(fd, " period_count: %d\n", profile->default_config.period_count);
747 dprintf(fd, " format: %d\n", profile->default_config.format);
748 }
749