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