204 lines
6.7 KiB
C
204 lines
6.7 KiB
C
|
/* tinypcminfo.c
|
||
|
**
|
||
|
** Copyright 2012, The Android Open Source Project
|
||
|
**
|
||
|
** Redistribution and use in source and binary forms, with or without
|
||
|
** modification, are permitted provided that the following conditions are met:
|
||
|
** * Redistributions of source code must retain the above copyright
|
||
|
** notice, this list of conditions and the following disclaimer.
|
||
|
** * Redistributions in binary form must reproduce the above copyright
|
||
|
** notice, this list of conditions and the following disclaimer in the
|
||
|
** documentation and/or other materials provided with the distribution.
|
||
|
** * Neither the name of The Android Open Source Project nor the names of
|
||
|
** its contributors may be used to endorse or promote products derived
|
||
|
** from this software without specific prior written permission.
|
||
|
**
|
||
|
** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
|
||
|
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
|
||
|
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
|
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||
|
** DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#include <tinyalsa/asoundlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#ifndef ARRAY_SIZE
|
||
|
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
|
||
|
#endif
|
||
|
|
||
|
/* The format_lookup is in order of SNDRV_PCM_FORMAT_##index and
|
||
|
* matches the grouping in sound/asound.h. Note this is not
|
||
|
* continuous and has an empty gap from (25 - 30).
|
||
|
*/
|
||
|
static const char *format_lookup[] = {
|
||
|
/*[0] =*/ "S8",
|
||
|
"U8",
|
||
|
"S16_LE",
|
||
|
"S16_BE",
|
||
|
"U16_LE",
|
||
|
"U16_BE",
|
||
|
"S24_LE",
|
||
|
"S24_BE",
|
||
|
"U24_LE",
|
||
|
"U24_BE",
|
||
|
"S32_LE",
|
||
|
"S32_BE",
|
||
|
"U32_LE",
|
||
|
"U32_BE",
|
||
|
"FLOAT_LE",
|
||
|
"FLOAT_BE",
|
||
|
"FLOAT64_LE",
|
||
|
"FLOAT64_BE",
|
||
|
"IEC958_SUBFRAME_LE",
|
||
|
"IEC958_SUBFRAME_BE",
|
||
|
"MU_LAW",
|
||
|
"A_LAW",
|
||
|
"IMA_ADPCM",
|
||
|
"MPEG",
|
||
|
/*[24] =*/ "GSM",
|
||
|
[31] = "SPECIAL",
|
||
|
"S24_3LE",
|
||
|
"S24_3BE",
|
||
|
"U24_3LE",
|
||
|
"U24_3BE",
|
||
|
"S20_3LE",
|
||
|
"S20_3BE",
|
||
|
"U20_3LE",
|
||
|
"U20_3BE",
|
||
|
"S18_3LE",
|
||
|
"S18_3BE",
|
||
|
"U18_3LE",
|
||
|
/*[43] =*/ "U18_3BE",
|
||
|
#if 0
|
||
|
/* recent additions, may not be present on local asound.h */
|
||
|
"G723_24",
|
||
|
"G723_24_1B",
|
||
|
"G723_40",
|
||
|
"G723_40_1B",
|
||
|
"DSD_U8",
|
||
|
"DSD_U16_LE",
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
/* Returns a human readable name for the format associated with bit_index,
|
||
|
* NULL if bit_index is not known.
|
||
|
*/
|
||
|
static inline const char *pcm_get_format_name(unsigned bit_index)
|
||
|
{
|
||
|
return bit_index < ARRAY_SIZE(format_lookup) ? format_lookup[bit_index] : NULL;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
unsigned int device = 0;
|
||
|
unsigned int card = 0;
|
||
|
int i;
|
||
|
|
||
|
if (argc < 3) {
|
||
|
fprintf(stderr, "Usage: %s -D card -d device\n", argv[0]);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* parse command line arguments */
|
||
|
argv += 1;
|
||
|
while (*argv) {
|
||
|
if (strcmp(*argv, "-D") == 0) {
|
||
|
argv++;
|
||
|
if (*argv)
|
||
|
card = atoi(*argv);
|
||
|
}
|
||
|
if (strcmp(*argv, "-d") == 0) {
|
||
|
argv++;
|
||
|
if (*argv)
|
||
|
device = atoi(*argv);
|
||
|
}
|
||
|
if (*argv)
|
||
|
argv++;
|
||
|
}
|
||
|
|
||
|
printf("Info for card %u, device %u:\n", card, device);
|
||
|
|
||
|
for (i = 0; i < 2; i++) {
|
||
|
struct pcm_params *params;
|
||
|
struct pcm_mask *m;
|
||
|
unsigned int min;
|
||
|
unsigned int max;
|
||
|
|
||
|
printf("\nPCM %s:\n", i == 0 ? "out" : "in");
|
||
|
|
||
|
params = pcm_params_get(card, device, i == 0 ? PCM_OUT : PCM_IN);
|
||
|
if (params == NULL) {
|
||
|
printf("Device does not exist.\n");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
m = pcm_params_get_mask(params, PCM_PARAM_ACCESS);
|
||
|
if (m) { /* bitmask, refer to SNDRV_PCM_ACCESS_*, generally interleaved */
|
||
|
printf(" Access:\t%#08x\n", m->bits[0]);
|
||
|
}
|
||
|
m = pcm_params_get_mask(params, PCM_PARAM_FORMAT);
|
||
|
if (m) { /* bitmask, refer to: SNDRV_PCM_FORMAT_* */
|
||
|
unsigned j, k, count = 0;
|
||
|
const unsigned bitcount = sizeof(m->bits[0]) * 8;
|
||
|
|
||
|
/* we only check first two format masks (out of 8) - others are zero. */
|
||
|
printf(" Format[0]:\t%#08x\n", m->bits[0]);
|
||
|
printf(" Format[1]:\t%#08x\n", m->bits[1]);
|
||
|
|
||
|
/* print friendly format names, if they exist */
|
||
|
for (k = 0; k < 2; ++k) {
|
||
|
for (j = 0; j < bitcount; ++j) {
|
||
|
const char *name;
|
||
|
|
||
|
if (m->bits[k] & (1 << j)) {
|
||
|
name = pcm_get_format_name(j + k*bitcount);
|
||
|
if (name) {
|
||
|
if (count++ == 0) {
|
||
|
printf(" Format Name:\t");
|
||
|
} else {
|
||
|
printf (", ");
|
||
|
}
|
||
|
printf("%s", name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (count) {
|
||
|
printf("\n");
|
||
|
}
|
||
|
}
|
||
|
m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT);
|
||
|
if (m) { /* bitmask, should be 1: SNDRV_PCM_SUBFORMAT_STD */
|
||
|
printf(" Subformat:\t%#08x\n", m->bits[0]);
|
||
|
}
|
||
|
min = pcm_params_get_min(params, PCM_PARAM_RATE);
|
||
|
max = pcm_params_get_max(params, PCM_PARAM_RATE);
|
||
|
printf(" Rate:\tmin=%uHz\tmax=%uHz\n", min, max);
|
||
|
min = pcm_params_get_min(params, PCM_PARAM_CHANNELS);
|
||
|
max = pcm_params_get_max(params, PCM_PARAM_CHANNELS);
|
||
|
printf(" Channels:\tmin=%u\t\tmax=%u\n", min, max);
|
||
|
min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS);
|
||
|
max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS);
|
||
|
printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max);
|
||
|
min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE);
|
||
|
max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE);
|
||
|
printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max);
|
||
|
min = pcm_params_get_min(params, PCM_PARAM_PERIODS);
|
||
|
max = pcm_params_get_max(params, PCM_PARAM_PERIODS);
|
||
|
printf("Period count:\tmin=%u\t\tmax=%u\n", min, max);
|
||
|
|
||
|
pcm_params_free(params);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|