• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define OPTPARSE_IMPLEMENTATION
35 #include "optparse.h"
36 
37 #ifndef ARRAY_SIZE
38 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
39 #endif
40 
41 /* The format_lookup is in order of SNDRV_PCM_FORMAT_##index and
42  * matches the grouping in sound/asound.h.  Note this is not
43  * continuous and has an empty gap from (25 - 30).
44  */
45 static const char *format_lookup[] = {
46         /*[0] =*/ "S8",
47         "U8",
48         "S16_LE",
49         "S16_BE",
50         "U16_LE",
51         "U16_BE",
52         "S24_LE",
53         "S24_BE",
54         "U24_LE",
55         "U24_BE",
56         "S32_LE",
57         "S32_BE",
58         "U32_LE",
59         "U32_BE",
60         "FLOAT_LE",
61         "FLOAT_BE",
62         "FLOAT64_LE",
63         "FLOAT64_BE",
64         "IEC958_SUBFRAME_LE",
65         "IEC958_SUBFRAME_BE",
66         "MU_LAW",
67         "A_LAW",
68         "IMA_ADPCM",
69         "MPEG",
70         /*[24] =*/ "GSM",
71         [31] = "SPECIAL",
72         "S24_3LE",
73         "S24_3BE",
74         "U24_3LE",
75         "U24_3BE",
76         "S20_3LE",
77         "S20_3BE",
78         "U20_3LE",
79         "U20_3BE",
80         "S18_3LE",
81         "S18_3BE",
82         "U18_3LE",
83         /*[43] =*/ "U18_3BE",
84 #if 0
85         /* recent additions, may not be present on local asound.h */
86         "G723_24",
87         "G723_24_1B",
88         "G723_40",
89         "G723_40_1B",
90         "DSD_U8",
91         "DSD_U16_LE",
92 #endif
93 };
94 
95 /* Returns a human readable name for the format associated with bit_index,
96  * NULL if bit_index is not known.
97  */
pcm_get_format_name(unsigned bit_index)98 static inline const char *pcm_get_format_name(unsigned bit_index)
99 {
100     return bit_index < ARRAY_SIZE(format_lookup) ? format_lookup[bit_index] : NULL;
101 }
102 
main(int argc,char ** argv)103 int main(int argc, char **argv)
104 {
105     unsigned int device = 0;
106     unsigned int card = 0;
107     int i;
108     struct optparse opts;
109     struct optparse_long long_options[] = {
110         { "help",   'h', OPTPARSE_NONE     },
111         { "card",   'D', OPTPARSE_REQUIRED },
112         { "device", 'd', OPTPARSE_REQUIRED },
113         { 0, 0, 0 }
114     };
115 
116     (void)argc; /* silence -Wunused-parameter */
117     /* parse command line arguments */
118     optparse_init(&opts, argv);
119     while ((i = optparse_long(&opts, long_options, NULL)) != -1) {
120         switch (i) {
121         case 'D':
122             card = atoi(opts.optarg);
123             break;
124         case 'd':
125             device = atoi(opts.optarg);
126             break;
127         case 'h':
128             fprintf(stderr, "Usage: %s -D card -d device\n", argv[0]);
129             return 0;
130         case '?':
131             fprintf(stderr, "%s\n", opts.errmsg);
132             return EXIT_FAILURE;
133         }
134     }
135 
136     printf("Info for card %u, device %u:\n", card, device);
137 
138     for (i = 0; i < 2; i++) {
139         struct pcm_params *params;
140         const struct pcm_mask *m;
141         unsigned int min;
142         unsigned int max;
143 
144         printf("\nPCM %s:\n", i == 0 ? "out" : "in");
145 
146         params = pcm_params_get(card, device, i == 0 ? PCM_OUT : PCM_IN);
147         if (params == NULL) {
148             printf("Device does not exist.\n");
149             continue;
150         }
151 
152         m = pcm_params_get_mask(params, PCM_PARAM_ACCESS);
153         if (m) { /* bitmask, refer to SNDRV_PCM_ACCESS_*, generally interleaved */
154             printf("      Access:\t%#08x\n", m->bits[0]);
155         }
156         m = pcm_params_get_mask(params, PCM_PARAM_FORMAT);
157         if (m) { /* bitmask, refer to: SNDRV_PCM_FORMAT_* */
158             unsigned j, k, count = 0;
159             const unsigned bitcount = sizeof(m->bits[0]) * 8;
160 
161             /* we only check first two format masks (out of 8) - others are zero. */
162             printf("   Format[0]:\t%#08x\n", m->bits[0]);
163             printf("   Format[1]:\t%#08x\n", m->bits[1]);
164 
165             /* print friendly format names, if they exist */
166             for (k = 0; k < 2; ++k) {
167                 for (j = 0; j < bitcount; ++j) {
168                     const char *name;
169 
170                     if (m->bits[k] & (1 << j)) {
171                         name = pcm_get_format_name(j + k*bitcount);
172                         if (name) {
173                             if (count++ == 0) {
174                                 printf(" Format Name:\t");
175                             } else {
176                                 printf (", ");
177                             }
178                             printf("%s", name);
179                         }
180                     }
181                 }
182             }
183             if (count) {
184                 printf("\n");
185             }
186         }
187         m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT);
188         if (m) { /* bitmask, should be 1: SNDRV_PCM_SUBFORMAT_STD */
189             printf("   Subformat:\t%#08x\n", m->bits[0]);
190         }
191         min = pcm_params_get_min(params, PCM_PARAM_RATE);
192         max = pcm_params_get_max(params, PCM_PARAM_RATE);
193         printf("        Rate:\tmin=%uHz\tmax=%uHz\n", min, max);
194         min = pcm_params_get_min(params, PCM_PARAM_CHANNELS);
195         max = pcm_params_get_max(params, PCM_PARAM_CHANNELS);
196         printf("    Channels:\tmin=%u\t\tmax=%u\n", min, max);
197         min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS);
198         max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS);
199         printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max);
200         min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE);
201         max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE);
202         printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max);
203         min = pcm_params_get_min(params, PCM_PARAM_PERIODS);
204         max = pcm_params_get_max(params, PCM_PARAM_PERIODS);
205         printf("Period count:\tmin=%u\t\tmax=%u\n", min, max);
206 
207         pcm_params_free(params);
208     }
209 
210     return 0;
211 }
212