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