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  */
pcm_get_format_name(unsigned bit_index)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 
main(int argc,char ** argv)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