2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "alsa_device_profile"
18 /*#define LOG_NDEBUG 0*/
19 /*#define LOG_PCM_PARAMS 0*/
28 #include "include/alsa_device_profile.h"
29 #include "include/alsa_format.h"
30 #include "include/alsa_logging.h"
32 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
34 /*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
35 #define BUFF_DURATION_MS 5
37 #define DEFAULT_PERIOD_SIZE 1024
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" */
47 static const unsigned const format_byte_size_map[] = {
48 2, /* PCM_FORMAT_S16_LE */
49 4, /* PCM_FORMAT_S32_LE */
50 1, /* PCM_FORMAT_S8 */
51 4, /* PCM_FORMAT_S24_LE */
52 3, /* PCM_FORMAT_S24_3LE */
55 extern int8_t const pcm_format_value_map[50];
57 /* Sort these in terms of preference (best first).
58 192 kHz is not first because it requires significant resources for possibly worse
59 quality and driver instability (depends on device).
60 The order here determines the default sample rate for the device.
61 AudioPolicyManager may not respect this ordering when picking sample rates.
62 Update MAX_PROFILE_SAMPLE_RATES after changing the array size.
64 TODO: remove 32000, 22050, 12000, 11025? Each sample rate check
65 requires opening the device which may cause pops. */
66 static const unsigned std_sample_rates[] =
67 {96000, 88200, 192000, 176400, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
69 static void profile_reset(alsa_device_profile* profile)
71 profile->card = profile->device = -1;
73 /* terminate the attribute arrays with invalid values */
74 profile->formats[0] = PCM_FORMAT_INVALID;
75 profile->sample_rates[0] = 0;
76 profile->channel_counts[0] = 0;
78 profile->min_period_size = profile->max_period_size = 0;
79 profile->min_channel_count = profile->max_channel_count = DEFAULT_CHANNEL_COUNT;
81 profile->is_valid = false;
84 void profile_init(alsa_device_profile* profile, int direction)
86 profile->direction = direction;
87 profile_reset(profile);
90 bool profile_is_initialized(alsa_device_profile* profile)
92 return profile->card >= 0 && profile->device >= 0;
95 bool profile_is_valid(alsa_device_profile* profile) {
96 return profile->is_valid;
99 bool profile_is_cached_for(alsa_device_profile* profile, int card, int device) {
100 return card == profile->card && device == profile->device;
103 void profile_decache(alsa_device_profile* profile) {
104 profile_reset(profile);
108 * Returns the supplied value rounded up to the next even multiple of 16
110 static unsigned int round_to_16_mult(unsigned int size)
112 return (size + 15) & ~15; /* 0xFFFFFFF0; */
116 * Returns the system defined minimum period size based on the supplied sample rate.
118 unsigned profile_calc_min_period_size(alsa_device_profile* profile, unsigned sample_rate)
120 ALOGV("profile_calc_min_period_size(%p, rate:%d)", profile, sample_rate);
121 if (profile == NULL) {
122 return DEFAULT_PERIOD_SIZE;
124 unsigned num_sample_frames = (sample_rate * BUFF_DURATION_MS) / 1000;
125 if (num_sample_frames < profile->min_period_size) {
126 num_sample_frames = profile->min_period_size;
128 return round_to_16_mult(num_sample_frames) * 2;
132 unsigned int profile_get_period_size(alsa_device_profile* profile, unsigned sample_rate)
134 unsigned int period_size = profile_calc_min_period_size(profile, sample_rate);
135 ALOGV("profile_get_period_size(rate:%d) = %d", sample_rate, period_size);
142 unsigned profile_get_default_sample_rate(alsa_device_profile* profile)
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.
148 return profile_is_valid(profile) ? profile->sample_rates[0] : DEFAULT_SAMPLE_RATE;
151 bool profile_is_sample_rate_valid(alsa_device_profile* profile, unsigned rate)
153 if (profile_is_valid(profile)) {
155 for (index = 0; profile->sample_rates[index] != 0; index++) {
156 if (profile->sample_rates[index] == rate) {
163 return rate == DEFAULT_SAMPLE_RATE;
170 enum pcm_format profile_get_default_format(alsa_device_profile* profile)
173 * TODO this won't be right in general. we should store a preferred format as we are scanning.
175 return profile_is_valid(profile) ? profile->formats[0] : DEFAULT_SAMPLE_FORMAT;
178 bool profile_is_format_valid(alsa_device_profile* profile, enum pcm_format fmt) {
179 if (profile_is_valid(profile)) {
181 for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
182 if (profile->formats[index] == fmt) {
189 return fmt == DEFAULT_SAMPLE_FORMAT;
196 unsigned profile_get_default_channel_count(alsa_device_profile* profile)
198 return profile_is_valid(profile) ? profile->channel_counts[0] : DEFAULT_CHANNEL_COUNT;
201 bool profile_is_channel_count_valid(alsa_device_profile* profile, unsigned count)
203 if (profile_is_initialized(profile)) {
204 return count >= profile->min_channel_count && count <= profile->max_channel_count;
206 return count == DEFAULT_CHANNEL_COUNT;
210 static bool profile_test_sample_rate(alsa_device_profile* profile, unsigned rate)
212 struct pcm_config config = profile->default_config;
215 bool works = false; /* let's be pessimistic */
216 struct pcm * pcm = pcm_open(profile->card, profile->device,
217 profile->direction, &config);
220 works = pcm_is_ready(pcm);
227 static unsigned profile_enum_sample_rates(alsa_device_profile* profile, unsigned min, unsigned max)
229 unsigned num_entries = 0;
232 for (index = 0; index < ARRAY_SIZE(std_sample_rates) &&
233 num_entries < ARRAY_SIZE(profile->sample_rates) - 1;
235 if (std_sample_rates[index] >= min && std_sample_rates[index] <= max
236 && profile_test_sample_rate(profile, std_sample_rates[index])) {
237 profile->sample_rates[num_entries++] = std_sample_rates[index];
240 profile->sample_rates[num_entries] = 0; /* terminate */
241 return num_entries; /* return # of supported rates */
244 static unsigned profile_enum_sample_formats(alsa_device_profile* profile, struct pcm_mask * mask)
246 const int num_slots = ARRAY_SIZE(mask->bits);
247 const int bits_per_slot = sizeof(mask->bits[0]) * 8;
249 const int table_size = ARRAY_SIZE(pcm_format_value_map);
251 int slot_index, bit_index, table_index;
254 for (slot_index = 0; slot_index < num_slots && table_index < table_size;
256 unsigned bit_mask = 1;
258 bit_index < bits_per_slot && table_index < table_size;
260 if ((mask->bits[slot_index] & bit_mask) != 0) {
261 enum pcm_format format = pcm_format_value_map[table_index];
262 /* Never return invalid (unrecognized) or 8-bit */
263 if (format != PCM_FORMAT_INVALID && format != PCM_FORMAT_S8) {
264 profile->formats[num_written++] = format;
265 if (num_written == ARRAY_SIZE(profile->formats) - 1) {
266 /* leave at least one PCM_FORMAT_INVALID at the end */
276 profile->formats[num_written] = PCM_FORMAT_INVALID;
280 static unsigned profile_enum_channel_counts(alsa_device_profile* profile, unsigned min,
283 /* modify alsa_device_profile.h if you change the std_channel_counts[] array. */
284 static const unsigned std_channel_counts[] = {8, 7, 6, 5, 4, 3, 2, 1};
286 unsigned num_counts = 0;
288 /* TODO write a profile_test_channel_count() */
289 /* Ensure there is at least one invalid channel count to terminate the channel counts array */
290 for (index = 0; index < ARRAY_SIZE(std_channel_counts) &&
291 num_counts < ARRAY_SIZE(profile->channel_counts) - 1;
293 /* TODO Do we want a channel counts test? */
294 if (std_channel_counts[index] >= min && std_channel_counts[index] <= max /* &&
295 profile_test_channel_count(profile, channel_counts[index])*/) {
296 profile->channel_counts[num_counts++] = std_channel_counts[index];
299 profile->channel_counts[num_counts] = 0;
300 return num_counts; /* return # of supported counts */
304 * Reads and decodes configuration info from the specified ALSA card/device.
306 static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_config * config)
308 ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
309 profile->card, profile->device, profile->direction);
311 if (profile->card < 0 || profile->device < 0) {
315 struct pcm_params * alsa_hw_params =
316 pcm_params_get(profile->card, profile->device, profile->direction);
317 if (alsa_hw_params == NULL) {
321 profile->min_period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
322 profile->max_period_size = pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
324 profile->min_channel_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
325 profile->max_channel_count = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS);
330 * This Logging will be useful when testing new USB devices.
332 #ifdef LOG_PCM_PARAMS
333 log_pcm_params(alsa_hw_params);
336 config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
337 config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
338 config->period_size = profile_calc_min_period_size(profile, config->rate);
339 config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
340 config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
341 #ifdef LOG_PCM_PARAMS
342 log_pcm_config(config, "read_alsa_device_config");
344 if (config->format == PCM_FORMAT_INVALID) {
348 pcm_params_free(alsa_hw_params);
353 bool profile_read_device_info(alsa_device_profile* profile)
355 if (!profile_is_initialized(profile)) {
359 /* let's get some defaults */
360 read_alsa_device_config(profile, &profile->default_config);
361 ALOGV("default_config chans:%d rate:%d format:%d count:%d size:%d",
362 profile->default_config.channels, profile->default_config.rate,
363 profile->default_config.format, profile->default_config.period_count,
364 profile->default_config.period_size);
366 struct pcm_params * alsa_hw_params = pcm_params_get(profile->card,
369 if (alsa_hw_params == NULL) {
374 struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
375 profile_enum_sample_formats(profile, format_mask);
378 profile_enum_channel_counts(
379 profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
380 pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
383 profile_enum_sample_rates(
384 profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
385 pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
387 profile->is_valid = true;
392 char * profile_get_sample_rate_strs(alsa_device_profile* profile)
394 /* if we assume that rate strings are about 5 characters (48000 is 5), plus ~1 for a
395 * delimiter "|" this buffer has room for about 22 rate strings which seems like
396 * way too much, but it's a stack variable so only temporary.
400 size_t buffSize = ARRAY_SIZE(buffer);
401 size_t curStrLen = 0;
405 size_t numEntries = 0;
407 for (index = 0; profile->sample_rates[index] != 0; index++) {
408 snprintf(numBuffer, sizeof(numBuffer), "%u", profile->sample_rates[index]);
409 // account for both the null, and potentially the bar.
410 if (buffSize - curStrLen < strlen(numBuffer) + (numEntries != 0 ? 2 : 1)) {
411 /* we don't have room for another, so bail at this point rather than
412 * return a malformed rate string
416 if (numEntries++ != 0) {
417 strlcat(buffer, "|", buffSize);
419 curStrLen = strlcat(buffer, numBuffer, buffSize);
422 return strdup(buffer);
425 char * profile_get_format_strs(alsa_device_profile* profile)
427 /* if we assume that format strings are about 24 characters (AUDIO_FORMAT_PCM_16_BIT is 23),
428 * plus ~1 for a delimiter "|" this buffer has room for about 10 format strings which seems
429 * like way too much, but it's a stack variable so only temporary.
433 size_t buffSize = ARRAY_SIZE(buffer);
434 size_t curStrLen = 0;
436 size_t numEntries = 0;
438 for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
439 // account for both the null, and potentially the bar.
440 if (buffSize - curStrLen < strlen(format_string_map[profile->formats[index]])
441 + (numEntries != 0 ? 2 : 1)) {
442 /* we don't have room for another, so bail at this point rather than
443 * return a malformed rate string
447 if (numEntries++ != 0) {
448 strlcat(buffer, "|", buffSize);
450 curStrLen = strlcat(buffer, format_string_map[profile->formats[index]], buffSize);
453 return strdup(buffer);
456 char * profile_get_channel_count_strs(alsa_device_profile* profile)
458 // FIXME implicit fixed channel count assumption here (FCC_8).
459 // we use only the canonical even number channel position masks.
460 static const char * const out_chans_strs[] = {
461 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
462 /* 1 */"AUDIO_CHANNEL_OUT_MONO",
463 /* 2 */"AUDIO_CHANNEL_OUT_STEREO",
464 /* 3 */ /* "AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
465 /* 4 */"AUDIO_CHANNEL_OUT_QUAD",
466 /* 5 */ /* "AUDIO_CHANNEL_OUT_QUAD|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
467 /* 6 */"AUDIO_CHANNEL_OUT_5POINT1",
468 /* 7 */ /* "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_BACK_CENTER" */ NULL,
469 /* 8 */"AUDIO_CHANNEL_OUT_7POINT1",
470 /* channel counts greater than this not considered */
473 static const char * const in_chans_strs[] = {
474 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
475 /* 1 */"AUDIO_CHANNEL_IN_MONO",
476 /* 2 */"AUDIO_CHANNEL_IN_STEREO",
477 /* channel counts greater than this not considered */
480 static const char * const index_chans_strs[] = {
481 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
482 /* 1 */"AUDIO_CHANNEL_INDEX_MASK_1",
483 /* 2 */"AUDIO_CHANNEL_INDEX_MASK_2",
484 /* 3 */"AUDIO_CHANNEL_INDEX_MASK_3",
485 /* 4 */"AUDIO_CHANNEL_INDEX_MASK_4",
486 /* 5 */"AUDIO_CHANNEL_INDEX_MASK_5",
487 /* 6 */"AUDIO_CHANNEL_INDEX_MASK_6",
488 /* 7 */"AUDIO_CHANNEL_INDEX_MASK_7",
489 /* 8 */"AUDIO_CHANNEL_INDEX_MASK_8",
492 const bool isOutProfile = profile->direction == PCM_OUT;
494 const char * const * const chans_strs = isOutProfile ? out_chans_strs : in_chans_strs;
495 const size_t chans_strs_size =
496 isOutProfile ? ARRAY_SIZE(out_chans_strs) : ARRAY_SIZE(in_chans_strs);
499 * If we assume each channel string is 26 chars ("AUDIO_CHANNEL_INDEX_MASK_8" is 26) + 1 for,
500 * the "|" delimiter, then we allocate room for 16 strings.
502 char buffer[27 * 16 + 1]; /* caution, may need to be expanded */
504 size_t buffSize = ARRAY_SIZE(buffer);
505 size_t curStrLen = 0;
507 /* We currently support MONO and STEREO, and always report STEREO but some (many)
508 * USB Audio Devices may only announce support for MONO (a headset mic for example), or
509 * The total number of output channels. SO, if the device itself doesn't explicitly
510 * support STEREO, append to the channel config strings we are generating.
512 * The MONO and STEREO positional channel masks are provided for legacy compatibility.
513 * For multichannel (n > 2) we only expose channel index masks.
515 // Always support stereo
516 curStrLen = strlcat(buffer, chans_strs[2], buffSize);
519 unsigned channel_count;
521 (channel_count = profile->channel_counts[index]) != 0;
524 /* we only show positional information for mono (stereo handled already) */
525 if (channel_count < chans_strs_size
526 && chans_strs[channel_count] != NULL
527 && channel_count < 2 /* positional only for fewer than 2 channels */) {
528 // account for the '|' and the '\0'
529 if (buffSize - curStrLen < strlen(chans_strs[channel_count]) + 2) {
530 /* we don't have room for another, so bail at this point rather than
531 * return a malformed rate string
536 strlcat(buffer, "|", buffSize);
537 curStrLen = strlcat(buffer, chans_strs[channel_count], buffSize);
540 // handle channel index masks for both input and output
541 // +2 to account for the '|' and the '\0'
542 if (buffSize - curStrLen < strlen(index_chans_strs[channel_count]) + 2) {
543 /* we don't have room for another, so bail at this point rather than
544 * return a malformed rate string
549 strlcat(buffer, "|", buffSize);
550 curStrLen = strlcat(buffer, index_chans_strs[channel_count], buffSize);
553 return strdup(buffer);