You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
6.7 KiB
203 lines
6.7 KiB
/* 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. |
|
*/ |
|
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 %d, device %d:\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; |
|
}
|
|
|