| /* 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; | |
| } |