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 static const unsigned std_channel_counts[] = {8, 4, 2, 1};
285 unsigned num_counts = 0;
287 /* TODO write a profile_test_channel_count() */
288 /* Ensure there is at least one invalid channel count to terminate the channel counts array */
289 for (index = 0; index < ARRAY_SIZE(std_channel_counts) &&
290 num_counts < ARRAY_SIZE(profile->channel_counts) - 1;
292 /* TODO Do we want a channel counts test? */
293 if (std_channel_counts[index] >= min && std_channel_counts[index] <= max /* &&
294 profile_test_channel_count(profile, channel_counts[index])*/) {
295 profile->channel_counts[num_counts++] = std_channel_counts[index];
298 profile->channel_counts[num_counts] = 0;
299 return num_counts; /* return # of supported counts */
303 * Reads and decodes configuration info from the specified ALSA card/device.
305 static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_config * config)
307 ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
308 profile->card, profile->device, profile->direction);
310 if (profile->card < 0 || profile->device < 0) {
314 struct pcm_params * alsa_hw_params =
315 pcm_params_get(profile->card, profile->device, profile->direction);
316 if (alsa_hw_params == NULL) {
320 profile->min_period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
321 profile->max_period_size = pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
323 profile->min_channel_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
324 profile->max_channel_count = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS);
329 * This Logging will be useful when testing new USB devices.
331 #ifdef LOG_PCM_PARAMS
332 log_pcm_params(alsa_hw_params);
335 config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
336 config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
337 config->period_size = profile_calc_min_period_size(profile, config->rate);
338 config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
339 config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
340 #ifdef LOG_PCM_PARAMS
341 log_pcm_config(config, "read_alsa_device_config");
343 if (config->format == PCM_FORMAT_INVALID) {
347 pcm_params_free(alsa_hw_params);
352 bool profile_read_device_info(alsa_device_profile* profile)
354 if (!profile_is_initialized(profile)) {
358 /* let's get some defaults */
359 read_alsa_device_config(profile, &profile->default_config);
360 ALOGV("default_config chans:%d rate:%d format:%d count:%d size:%d",
361 profile->default_config.channels, profile->default_config.rate,
362 profile->default_config.format, profile->default_config.period_count,
363 profile->default_config.period_size);
365 struct pcm_params * alsa_hw_params = pcm_params_get(profile->card,
368 if (alsa_hw_params == NULL) {
373 struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
374 profile_enum_sample_formats(profile, format_mask);
377 profile_enum_channel_counts(
378 profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
379 pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
382 profile_enum_sample_rates(
383 profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
384 pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
386 profile->is_valid = true;
391 char * profile_get_sample_rate_strs(alsa_device_profile* profile)
393 /* if we assume that rate strings are about 5 characters (48000 is 5), plus ~1 for a
394 * delimiter "|" this buffer has room for about 22 rate strings which seems like
395 * way too much, but it's a stack variable so only temporary.
399 size_t buffSize = ARRAY_SIZE(buffer);
400 size_t curStrLen = 0;
404 size_t numEntries = 0;
406 for (index = 0; profile->sample_rates[index] != 0; index++) {
407 snprintf(numBuffer, sizeof(numBuffer), "%u", profile->sample_rates[index]);
408 // account for both the null, and potentially the bar.
409 if (buffSize - curStrLen < strlen(numBuffer) + (numEntries != 0 ? 2 : 1)) {
410 /* we don't have room for another, so bail at this point rather than
411 * return a malformed rate string
415 if (numEntries++ != 0) {
416 strlcat(buffer, "|", buffSize);
418 curStrLen = strlcat(buffer, numBuffer, buffSize);
421 return strdup(buffer);
424 char * profile_get_format_strs(alsa_device_profile* profile)
426 /* if we assume that format strings are about 24 characters (AUDIO_FORMAT_PCM_16_BIT is 23),
427 * plus ~1 for a delimiter "|" this buffer has room for about 10 format strings which seems
428 * like way too much, but it's a stack variable so only temporary.
432 size_t buffSize = ARRAY_SIZE(buffer);
433 size_t curStrLen = 0;
435 size_t numEntries = 0;
437 for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
438 // account for both the null, and potentially the bar.
439 if (buffSize - curStrLen < strlen(format_string_map[profile->formats[index]])
440 + (numEntries != 0 ? 2 : 1)) {
441 /* we don't have room for another, so bail at this point rather than
442 * return a malformed rate string
446 if (numEntries++ != 0) {
447 strlcat(buffer, "|", buffSize);
449 curStrLen = strlcat(buffer, format_string_map[profile->formats[index]], buffSize);
452 return strdup(buffer);
455 char * profile_get_channel_count_strs(alsa_device_profile* profile)
457 static const char * const out_chans_strs[] = {
458 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
459 /* 1 */"AUDIO_CHANNEL_OUT_MONO",
460 /* 2 */"AUDIO_CHANNEL_OUT_STEREO",
461 /* 3 */ /* "AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
462 /* 4 */"AUDIO_CHANNEL_OUT_QUAD",
463 /* 5 */ /* "AUDIO_CHANNEL_OUT_QUAD|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
464 /* 6 */"AUDIO_CHANNEL_OUT_5POINT1",
465 /* 7 */ /* "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_BACK_CENTER" */ NULL,
466 /* 8 */ "AUDIO_CHANNEL_OUT_7POINT1",
467 /* channel counts greater than this not considered */
470 static const char * const in_chans_strs[] = {
471 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
472 /* 1 */"AUDIO_CHANNEL_IN_MONO",
473 /* 2 */"AUDIO_CHANNEL_IN_STEREO",
474 /* channel counts greater than this not considered */
477 static const char * const index_chans_strs[] = {
478 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
479 /* 1 */"AUDIO_CHANNEL_INDEX_MASK_1",
480 /* 2 */"AUDIO_CHANNEL_INDEX_MASK_2",
481 /* 3 */"AUDIO_CHANNEL_INDEX_MASK_3",
482 /* 4 */"AUDIO_CHANNEL_INDEX_MASK_4",
483 /* 5 */"AUDIO_CHANNEL_INDEX_MASK_5",
484 /* 6 */"AUDIO_CHANNEL_INDEX_MASK_6",
485 /* 7 */"AUDIO_CHANNEL_INDEX_MASK_7",
486 /* 8 */"AUDIO_CHANNEL_INDEX_MASK_8",
489 const bool isOutProfile = profile->direction == PCM_OUT;
491 const char * const * const chans_strs = isOutProfile ? out_chans_strs : in_chans_strs;
492 const size_t chans_strs_size =
493 isOutProfile ? ARRAY_SIZE(out_chans_strs) : ARRAY_SIZE(in_chans_strs);
496 * If we assume each channel string is 26 chars ("AUDIO_CHANNEL_INDEX_MASK_8" is 26) + 1 for,
497 * the "|" delimiter, then we allocate room for 16 strings.
499 char buffer[27 * 16 + 1]; /* caution, may need to be expanded */
501 size_t buffSize = ARRAY_SIZE(buffer);
502 size_t curStrLen = 0;
504 /* We currently support MONO and STEREO, and always report STEREO but some (many)
505 * USB Audio Devices may only announce support for MONO (a headset mic for example), or
506 * The total number of output channels. SO, if the device itself doesn't explicitly
507 * support STEREO, append to the channel config strings we are generating.
509 // Always support stereo
510 curStrLen = strlcat(buffer, chans_strs[2], buffSize);
513 unsigned channel_count;
515 (channel_count = profile->channel_counts[index]) != 0;
517 if (channel_count < chans_strs_size
518 && chans_strs[channel_count] != NULL
519 && channel_count != 2 /* stereo already supported */) {
520 // account for the '|' and the '\0'
521 if (buffSize - curStrLen < strlen(chans_strs[channel_count]) + 2) {
522 /* we don't have room for another, so bail at this point rather than
523 * return a malformed rate string
528 strlcat(buffer, "|", buffSize);
529 curStrLen = strlcat(buffer, chans_strs[channel_count], buffSize);
532 // handle channel index masks for both input and output
533 // +2 to account for the '|' and the '\0'
534 if (buffSize - curStrLen < strlen(index_chans_strs[channel_count]) + 2) {
535 /* we don't have room for another, so bail at this point rather than
536 * return a malformed rate string
541 strlcat(buffer, "|", buffSize);
542 curStrLen = strlcat(buffer, index_chans_strs[channel_count], buffSize);
545 return strdup(buffer);