1 /* tinypcminfo.c 2 ** 3 ** Copyright 2012, The Android Open Source Project 4 ** 5 ** Redistribution and use in source and binary forms, with or without 6 ** modification, are permitted provided that the following conditions are met: 7 ** * Redistributions of source code must retain the above copyright 8 ** notice, this list of conditions and the following disclaimer. 9 ** * Redistributions in binary form must reproduce the above copyright 10 ** notice, this list of conditions and the following disclaimer in the 11 ** documentation and/or other materials provided with the distribution. 12 ** * Neither the name of The Android Open Source Project nor the names of 13 ** its contributors may be used to endorse or promote products derived 14 ** from this software without specific prior written permission. 15 ** 16 ** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND 17 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 ** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE 20 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 ** DAMAGE. 27 */ 28 29 #include <tinyalsa/asoundlib.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 #ifndef ARRAY_SIZE 35 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) 36 #endif 37 38 /* The format_lookup is in order of SNDRV_PCM_FORMAT_##index and 39 * matches the grouping in sound/asound.h. Note this is not 40 * continuous and has an empty gap from (25 - 30). 41 */ 42 static const char *format_lookup[] = { 43 /*[0] =*/ "S8", 44 "U8", 45 "S16_LE", 46 "S16_BE", 47 "U16_LE", 48 "U16_BE", 49 "S24_LE", 50 "S24_BE", 51 "U24_LE", 52 "U24_BE", 53 "S32_LE", 54 "S32_BE", 55 "U32_LE", 56 "U32_BE", 57 "FLOAT_LE", 58 "FLOAT_BE", 59 "FLOAT64_LE", 60 "FLOAT64_BE", 61 "IEC958_SUBFRAME_LE", 62 "IEC958_SUBFRAME_BE", 63 "MU_LAW", 64 "A_LAW", 65 "IMA_ADPCM", 66 "MPEG", 67 /*[24] =*/ "GSM", 68 [31] = "SPECIAL", 69 "S24_3LE", 70 "S24_3BE", 71 "U24_3LE", 72 "U24_3BE", 73 "S20_3LE", 74 "S20_3BE", 75 "U20_3LE", 76 "U20_3BE", 77 "S18_3LE", 78 "S18_3BE", 79 "U18_3LE", 80 /*[43] =*/ "U18_3BE", 81 #if 0 82 /* recent additions, may not be present on local asound.h */ 83 "G723_24", 84 "G723_24_1B", 85 "G723_40", 86 "G723_40_1B", 87 "DSD_U8", 88 "DSD_U16_LE", 89 #endif 90 }; 91 92 /* Returns a human readable name for the format associated with bit_index, 93 * NULL if bit_index is not known. 94 */ 95 inline const char *pcm_get_format_name(unsigned bit_index) 96 { 97 return bit_index < ARRAY_SIZE(format_lookup) ? format_lookup[bit_index] : NULL; 98 } 99 100 int main(int argc, char **argv) 101 { 102 unsigned int device = 0; 103 unsigned int card = 0; 104 int i; 105 106 if (argc < 3) { 107 fprintf(stderr, "Usage: %s -D card -d device\n", argv[0]); 108 return 1; 109 } 110 111 /* parse command line arguments */ 112 argv += 1; 113 while (*argv) { 114 if (strcmp(*argv, "-D") == 0) { 115 argv++; 116 if (*argv) 117 card = atoi(*argv); 118 } 119 if (strcmp(*argv, "-d") == 0) { 120 argv++; 121 if (*argv) 122 device = atoi(*argv); 123 } 124 if (*argv) 125 argv++; 126 } 127 128 printf("Info for card %d, device %d:\n", card, device); 129 130 for (i = 0; i < 2; i++) { 131 struct pcm_params *params; 132 struct pcm_mask *m; 133 unsigned int min; 134 unsigned int max; 135 136 printf("\nPCM %s:\n", i == 0 ? "out" : "in"); 137 138 params = pcm_params_get(card, device, i == 0 ? PCM_OUT : PCM_IN); 139 if (params == NULL) { 140 printf("Device does not exist.\n"); 141 continue; 142 } 143 144 m = pcm_params_get_mask(params, PCM_PARAM_ACCESS); 145 if (m) { /* bitmask, refer to SNDRV_PCM_ACCESS_*, generally interleaved */ 146 printf(" Access:\t%#08x\n", m->bits[0]); 147 } 148 m = pcm_params_get_mask(params, PCM_PARAM_FORMAT); 149 if (m) { /* bitmask, refer to: SNDRV_PCM_FORMAT_* */ 150 unsigned j, k, count = 0; 151 const unsigned bitcount = sizeof(m->bits[0]) * 8; 152 153 /* we only check first two format masks (out of 8) - others are zero. */ 154 printf(" Format[0]:\t%#08x\n", m->bits[0]); 155 printf(" Format[1]:\t%#08x\n", m->bits[1]); 156 157 /* print friendly format names, if they exist */ 158 for (k = 0; k < 2; ++k) { 159 for (j = 0; j < bitcount; ++j) { 160 const char *name; 161 162 if (m->bits[k] & (1 << j)) { 163 name = pcm_get_format_name(j + k*bitcount); 164 if (name) { 165 if (count++ == 0) { 166 printf(" Format Name:\t"); 167 } else { 168 printf (", "); 169 } 170 printf("%s", name); 171 } 172 } 173 } 174 } 175 if (count) { 176 printf("\n"); 177 } 178 } 179 m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT); 180 if (m) { /* bitmask, should be 1: SNDRV_PCM_SUBFORMAT_STD */ 181 printf(" Subformat:\t%#08x\n", m->bits[0]); 182 } 183 min = pcm_params_get_min(params, PCM_PARAM_RATE); 184 max = pcm_params_get_max(params, PCM_PARAM_RATE); 185 printf(" Rate:\tmin=%uHz\tmax=%uHz\n", min, max); 186 min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); 187 max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); 188 printf(" Channels:\tmin=%u\t\tmax=%u\n", min, max); 189 min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); 190 max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); 191 printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max); 192 min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE); 193 max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE); 194 printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max); 195 min = pcm_params_get_min(params, PCM_PARAM_PERIODS); 196 max = pcm_params_get_max(params, PCM_PARAM_PERIODS); 197 printf("Period count:\tmin=%u\t\tmax=%u\n", min, max); 198 199 pcm_params_free(params); 200 } 201 202 return 0; 203 } 204