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