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
26 #include <log/log.h>
27
28 #include "include/alsa_device_profile.h"
29 #include "include/alsa_format.h"
30 #include "include/alsa_logging.h"
31
32 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
33
34 /*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
35 #define BUFF_DURATION_MS 5
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(alsa_device_profile * profile)82 bool profile_is_initialized(alsa_device_profile* profile)
83 {
84 return profile->card >= 0 && profile->device >= 0;
85 }
86
profile_is_valid(alsa_device_profile * profile)87 bool profile_is_valid(alsa_device_profile* profile) {
88 return profile->is_valid;
89 }
90
profile_is_cached_for(alsa_device_profile * profile,int card,int device)91 bool profile_is_cached_for(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(alsa_device_profile * profile,unsigned sample_rate)110 unsigned profile_calc_min_period_size(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 num_sample_frames = (sample_rate * BUFF_DURATION_MS) / 1000;
117 if (num_sample_frames < profile->min_period_size) {
118 num_sample_frames = profile->min_period_size;
119 }
120 return round_to_16_mult(num_sample_frames) * 2;
121 }
122 }
123
profile_get_period_size(alsa_device_profile * profile,unsigned sample_rate)124 unsigned int profile_get_period_size(alsa_device_profile* profile, unsigned sample_rate)
125 {
126 unsigned int period_size = profile_calc_min_period_size(profile, sample_rate);
127 ALOGV("profile_get_period_size(rate:%d) = %d", sample_rate, period_size);
128 return period_size;
129 }
130
131 /*
132 * Sample Rate
133 */
profile_get_default_sample_rate(alsa_device_profile * profile)134 unsigned profile_get_default_sample_rate(alsa_device_profile* profile)
135 {
136 /*
137 * TODO this won't be right in general. we should store a preferred rate as we are scanning.
138 * But right now it will return the highest rate, which may be correct.
139 */
140 return profile_is_valid(profile) ? profile->sample_rates[0] : DEFAULT_SAMPLE_RATE;
141 }
142
profile_is_sample_rate_valid(alsa_device_profile * profile,unsigned rate)143 bool profile_is_sample_rate_valid(alsa_device_profile* profile, unsigned rate)
144 {
145 if (profile_is_valid(profile)) {
146 size_t index;
147 for (index = 0; profile->sample_rates[index] != 0; index++) {
148 if (profile->sample_rates[index] == rate) {
149 return true;
150 }
151 }
152
153 return false;
154 } else {
155 return rate == DEFAULT_SAMPLE_RATE;
156 }
157 }
158
159 /*
160 * Format
161 */
profile_get_default_format(alsa_device_profile * profile)162 enum pcm_format profile_get_default_format(alsa_device_profile* profile)
163 {
164 /*
165 * TODO this won't be right in general. we should store a preferred format as we are scanning.
166 */
167 return profile_is_valid(profile) ? profile->formats[0] : DEFAULT_SAMPLE_FORMAT;
168 }
169
profile_is_format_valid(alsa_device_profile * profile,enum pcm_format fmt)170 bool profile_is_format_valid(alsa_device_profile* profile, enum pcm_format fmt) {
171 if (profile_is_valid(profile)) {
172 size_t index;
173 for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
174 if (profile->formats[index] == fmt) {
175 return true;
176 }
177 }
178
179 return false;
180 } else {
181 return fmt == DEFAULT_SAMPLE_FORMAT;
182 }
183 }
184
185 /*
186 * Channels
187 */
profile_get_default_channel_count(alsa_device_profile * profile)188 unsigned profile_get_default_channel_count(alsa_device_profile* profile)
189 {
190 return profile_is_valid(profile) ? profile->channel_counts[0] : DEFAULT_CHANNEL_COUNT;
191 }
192
profile_is_channel_count_valid(alsa_device_profile * profile,unsigned count)193 bool profile_is_channel_count_valid(alsa_device_profile* profile, unsigned count)
194 {
195 if (profile_is_initialized(profile)) {
196 return count >= profile->min_channel_count && count <= profile->max_channel_count;
197 } else {
198 return count == DEFAULT_CHANNEL_COUNT;
199 }
200 }
201
profile_test_sample_rate(alsa_device_profile * profile,unsigned rate)202 static bool profile_test_sample_rate(alsa_device_profile* profile, unsigned rate)
203 {
204 struct pcm_config config = profile->default_config;
205 config.rate = rate;
206
207 bool works = false; /* let's be pessimistic */
208 struct pcm * pcm = pcm_open(profile->card, profile->device,
209 profile->direction, &config);
210
211 if (pcm != NULL) {
212 works = pcm_is_ready(pcm);
213 pcm_close(pcm);
214 }
215
216 return works;
217 }
218
profile_enum_sample_rates(alsa_device_profile * profile,unsigned min,unsigned max)219 static unsigned profile_enum_sample_rates(alsa_device_profile* profile, unsigned min, unsigned max)
220 {
221 unsigned num_entries = 0;
222 unsigned index;
223
224 for (index = 0; index < ARRAY_SIZE(std_sample_rates) &&
225 num_entries < ARRAY_SIZE(profile->sample_rates) - 1;
226 index++) {
227 if (std_sample_rates[index] >= min && std_sample_rates[index] <= max
228 && profile_test_sample_rate(profile, std_sample_rates[index])) {
229 profile->sample_rates[num_entries++] = std_sample_rates[index];
230 }
231 }
232 profile->sample_rates[num_entries] = 0; /* terminate */
233 return num_entries; /* return # of supported rates */
234 }
235
profile_enum_sample_formats(alsa_device_profile * profile,struct pcm_mask * mask)236 static unsigned profile_enum_sample_formats(alsa_device_profile* profile, struct pcm_mask * mask)
237 {
238 const int num_slots = ARRAY_SIZE(mask->bits);
239 const int bits_per_slot = sizeof(mask->bits[0]) * 8;
240
241 const int table_size = ARRAY_SIZE(pcm_format_value_map);
242
243 int slot_index, bit_index, table_index;
244 table_index = 0;
245 int num_written = 0;
246 for (slot_index = 0; slot_index < num_slots && table_index < table_size;
247 slot_index++) {
248 unsigned bit_mask = 1;
249 for (bit_index = 0;
250 bit_index < bits_per_slot && table_index < table_size;
251 bit_index++) {
252 if ((mask->bits[slot_index] & bit_mask) != 0) {
253 enum pcm_format format = pcm_format_value_map[table_index];
254 /* Never return invalid (unrecognized) or 8-bit */
255 if (format != PCM_FORMAT_INVALID && format != PCM_FORMAT_S8) {
256 profile->formats[num_written++] = format;
257 if (num_written == ARRAY_SIZE(profile->formats) - 1) {
258 /* leave at least one PCM_FORMAT_INVALID at the end */
259 goto end;
260 }
261 }
262 }
263 bit_mask <<= 1;
264 table_index++;
265 }
266 }
267 end:
268 profile->formats[num_written] = PCM_FORMAT_INVALID;
269 return num_written;
270 }
271
profile_enum_channel_counts(alsa_device_profile * profile,unsigned min,unsigned max)272 static unsigned profile_enum_channel_counts(alsa_device_profile* profile, unsigned min,
273 unsigned max)
274 {
275 /* modify alsa_device_profile.h if you change the std_channel_counts[] array. */
276 static const unsigned std_channel_counts[] = {8, 7, 6, 5, 4, 3, 2, 1};
277
278 unsigned num_counts = 0;
279 unsigned index;
280 /* TODO write a profile_test_channel_count() */
281 /* Ensure there is at least one invalid channel count to terminate the channel counts array */
282 for (index = 0; index < ARRAY_SIZE(std_channel_counts) &&
283 num_counts < ARRAY_SIZE(profile->channel_counts) - 1;
284 index++) {
285 /* TODO Do we want a channel counts test? */
286 if (std_channel_counts[index] >= min && std_channel_counts[index] <= max /* &&
287 profile_test_channel_count(profile, channel_counts[index])*/) {
288 profile->channel_counts[num_counts++] = std_channel_counts[index];
289 }
290 }
291 profile->channel_counts[num_counts] = 0;
292 return num_counts; /* return # of supported counts */
293 }
294
295 /*
296 * Reads and decodes configuration info from the specified ALSA card/device.
297 */
read_alsa_device_config(alsa_device_profile * profile,struct pcm_config * config)298 static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_config * config)
299 {
300 ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
301 profile->card, profile->device, profile->direction);
302
303 if (profile->card < 0 || profile->device < 0) {
304 return -EINVAL;
305 }
306
307 struct pcm_params * alsa_hw_params =
308 pcm_params_get(profile->card, profile->device, profile->direction);
309 if (alsa_hw_params == NULL) {
310 return -EINVAL;
311 }
312
313 profile->min_period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
314 profile->max_period_size = pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
315
316 profile->min_channel_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
317 profile->max_channel_count = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS);
318
319 int ret = 0;
320
321 /*
322 * This Logging will be useful when testing new USB devices.
323 */
324 #ifdef LOG_PCM_PARAMS
325 log_pcm_params(alsa_hw_params);
326 #endif
327
328 config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
329 config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
330 config->period_size = profile_calc_min_period_size(profile, config->rate);
331 config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
332 config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
333 #ifdef LOG_PCM_PARAMS
334 log_pcm_config(config, "read_alsa_device_config");
335 #endif
336 if (config->format == PCM_FORMAT_INVALID) {
337 ret = -EINVAL;
338 }
339
340 pcm_params_free(alsa_hw_params);
341
342 return ret;
343 }
344
profile_read_device_info(alsa_device_profile * profile)345 bool profile_read_device_info(alsa_device_profile* profile)
346 {
347 if (!profile_is_initialized(profile)) {
348 return false;
349 }
350
351 /* let's get some defaults */
352 read_alsa_device_config(profile, &profile->default_config);
353 ALOGV("default_config chans:%d rate:%d format:%d count:%d size:%d",
354 profile->default_config.channels, profile->default_config.rate,
355 profile->default_config.format, profile->default_config.period_count,
356 profile->default_config.period_size);
357
358 struct pcm_params * alsa_hw_params = pcm_params_get(profile->card,
359 profile->device,
360 profile->direction);
361 if (alsa_hw_params == NULL) {
362 return false;
363 }
364
365 /* Formats */
366 struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
367 profile_enum_sample_formats(profile, format_mask);
368
369 /* Channels */
370 profile_enum_channel_counts(
371 profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
372 pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
373
374 /* Sample Rates */
375 profile_enum_sample_rates(
376 profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
377 pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
378
379 profile->is_valid = true;
380
381 return true;
382 }
383
profile_get_sample_rate_strs(alsa_device_profile * profile)384 char * profile_get_sample_rate_strs(alsa_device_profile* profile)
385 {
386 /* if we assume that rate strings are about 5 characters (48000 is 5), plus ~1 for a
387 * delimiter "|" this buffer has room for about 22 rate strings which seems like
388 * way too much, but it's a stack variable so only temporary.
389 */
390 char buffer[128];
391 buffer[0] = '\0';
392 size_t buffSize = ARRAY_SIZE(buffer);
393 size_t curStrLen = 0;
394
395 char numBuffer[32];
396
397 size_t numEntries = 0;
398 size_t index;
399 for (index = 0; profile->sample_rates[index] != 0; index++) {
400 snprintf(numBuffer, sizeof(numBuffer), "%u", profile->sample_rates[index]);
401 // account for both the null, and potentially the bar.
402 if (buffSize - curStrLen < strlen(numBuffer) + (numEntries != 0 ? 2 : 1)) {
403 /* we don't have room for another, so bail at this point rather than
404 * return a malformed rate string
405 */
406 break;
407 }
408 if (numEntries++ != 0) {
409 strlcat(buffer, "|", buffSize);
410 }
411 curStrLen = strlcat(buffer, numBuffer, buffSize);
412 }
413
414 return strdup(buffer);
415 }
416
profile_get_format_strs(alsa_device_profile * profile)417 char * profile_get_format_strs(alsa_device_profile* profile)
418 {
419 /* if we assume that format strings are about 24 characters (AUDIO_FORMAT_PCM_16_BIT is 23),
420 * plus ~1 for a delimiter "|" this buffer has room for about 10 format strings which seems
421 * like way too much, but it's a stack variable so only temporary.
422 */
423 char buffer[256];
424 buffer[0] = '\0';
425 size_t buffSize = ARRAY_SIZE(buffer);
426 size_t curStrLen = 0;
427
428 size_t numEntries = 0;
429 size_t index = 0;
430 for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
431 // account for both the null, and potentially the bar.
432 if (buffSize - curStrLen < strlen(format_string_map[profile->formats[index]])
433 + (numEntries != 0 ? 2 : 1)) {
434 /* we don't have room for another, so bail at this point rather than
435 * return a malformed rate string
436 */
437 break;
438 }
439 if (numEntries++ != 0) {
440 strlcat(buffer, "|", buffSize);
441 }
442 curStrLen = strlcat(buffer, format_string_map[profile->formats[index]], buffSize);
443 }
444
445 return strdup(buffer);
446 }
447
profile_get_channel_count_strs(alsa_device_profile * profile)448 char * profile_get_channel_count_strs(alsa_device_profile* profile)
449 {
450 // FIXME implicit fixed channel count assumption here (FCC_8).
451 // we use only the canonical even number channel position masks.
452 static const char * const out_chans_strs[] = {
453 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
454 /* 1 */"AUDIO_CHANNEL_OUT_MONO",
455 /* 2 */"AUDIO_CHANNEL_OUT_STEREO",
456 /* 3 */ /* "AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
457 /* 4 */"AUDIO_CHANNEL_OUT_QUAD",
458 /* 5 */ /* "AUDIO_CHANNEL_OUT_QUAD|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
459 /* 6 */"AUDIO_CHANNEL_OUT_5POINT1",
460 /* 7 */ /* "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_BACK_CENTER" */ NULL,
461 /* 8 */"AUDIO_CHANNEL_OUT_7POINT1",
462 /* channel counts greater than this not considered */
463 };
464
465 static const char * const in_chans_strs[] = {
466 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
467 /* 1 */"AUDIO_CHANNEL_IN_MONO",
468 /* 2 */"AUDIO_CHANNEL_IN_STEREO",
469 /* channel counts greater than this not considered */
470 };
471
472 static const char * const index_chans_strs[] = {
473 /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
474 /* 1 */"AUDIO_CHANNEL_INDEX_MASK_1",
475 /* 2 */"AUDIO_CHANNEL_INDEX_MASK_2",
476 /* 3 */"AUDIO_CHANNEL_INDEX_MASK_3",
477 /* 4 */"AUDIO_CHANNEL_INDEX_MASK_4",
478 /* 5 */"AUDIO_CHANNEL_INDEX_MASK_5",
479 /* 6 */"AUDIO_CHANNEL_INDEX_MASK_6",
480 /* 7 */"AUDIO_CHANNEL_INDEX_MASK_7",
481 /* 8 */"AUDIO_CHANNEL_INDEX_MASK_8",
482 };
483
484 const bool isOutProfile = profile->direction == PCM_OUT;
485
486 const char * const * const chans_strs = isOutProfile ? out_chans_strs : in_chans_strs;
487 const size_t chans_strs_size =
488 isOutProfile ? ARRAY_SIZE(out_chans_strs) : ARRAY_SIZE(in_chans_strs);
489
490 /*
491 * If we assume each channel string is 26 chars ("AUDIO_CHANNEL_INDEX_MASK_8" is 26) + 1 for,
492 * the "|" delimiter, then we allocate room for 16 strings.
493 */
494 char buffer[27 * 16 + 1]; /* caution, may need to be expanded */
495 buffer[0] = '\0';
496 size_t buffSize = ARRAY_SIZE(buffer);
497 size_t curStrLen = 0;
498
499 /* We currently support MONO and STEREO, and always report STEREO but some (many)
500 * USB Audio Devices may only announce support for MONO (a headset mic for example), or
501 * The total number of output channels. SO, if the device itself doesn't explicitly
502 * support STEREO, append to the channel config strings we are generating.
503 *
504 * The MONO and STEREO positional channel masks are provided for legacy compatibility.
505 * For multichannel (n > 2) we only expose channel index masks.
506 */
507 // Always support stereo
508 curStrLen = strlcat(buffer, chans_strs[2], buffSize);
509
510 size_t index;
511 unsigned channel_count;
512 for (index = 0;
513 (channel_count = profile->channel_counts[index]) != 0;
514 index++) {
515
516 /* we only show positional information for mono (stereo handled already) */
517 if (channel_count < chans_strs_size
518 && chans_strs[channel_count] != NULL
519 && channel_count < 2 /* positional only for fewer than 2 channels */) {
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
524 */
525 break;
526 }
527
528 strlcat(buffer, "|", buffSize);
529 curStrLen = strlcat(buffer, chans_strs[channel_count], buffSize);
530 }
531
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
537 */
538 break;
539 }
540
541 strlcat(buffer, "|", buffSize);
542 curStrLen = strlcat(buffer, index_chans_strs[channel_count], buffSize);
543 }
544
545 return strdup(buffer);
546 }
547