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