1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <getopt.h>
36 #include <ctype.h>
37 #include <aw-alsa-lib/control.h>
38 #include <aw-alsa-lib/common.h>
39 #include <hal_cmd.h>
40
41
amixer_ctl_info_print(snd_ctl_info_t * info)42 static void amixer_ctl_info_print(snd_ctl_info_t *info)
43 {
44 if (info->type == SND_CTL_ELEM_TYPE_INTEGER) {
45 printf("numid=%u, name=\'%s\'\n", info->id, info->name);
46 printf("\t value=%lu, min=%u, max=%u\n",
47 info->value, info->min, info->max);
48 } else if (info->type == SND_CTL_ELEM_TYPE_ENUMERATED) {
49 printf("numid=%u, name=\'%s\'\n", info->id, info->name);
50 printf("\t value=%s, enum=", info->texts[info->value]);
51 int i = 0;
52 for (i = 0; i < info->items; i++) {
53 printf("%s ", info->texts[i]);
54 }
55 printf("\n");
56 } else {
57 printf("numid=%u, name=\'%s\' type error:%d\n",
58 info->id, info->name, info->type);
59 }
60 }
61
amixer_controls(const char * card_name)62 static int amixer_controls(const char *card_name)
63 {
64 int num, ret, i, count = 0;
65 snd_ctl_info_t info;
66
67 if ((card_name == NULL) || (!strcmp(card_name, "default")))
68 card_name = "audiocodec";
69
70 num = snd_ctl_num(card_name);
71 if (num == 0) {
72 printf("The card didn't have ctl.\n");
73 return 0;
74 } else if (num < 0)
75 return -1;
76
77 for (i = 0; i < num;i ++) {
78 memset(&info, 0, sizeof(snd_ctl_info_t));
79 ret = snd_ctl_get_bynum(card_name, i, &info);
80 if (ret < 0) {
81 printf("get %d elem failed\n", i);
82 return ret;
83 }
84 amixer_ctl_info_print(&info);
85 }
86 return 0;
87 }
88
parser_ctl_numid(const char * cmd,int * id)89 static int parser_ctl_numid(const char *cmd, int *id)
90 {
91 char *id_str = "numid=";
92
93 if (strncmp(cmd, id_str, strlen(id_str)) != 0)
94 return -1;
95 *id = atoi(cmd+strlen(id_str));
96 return 0;
97 }
98
amixer_usage(void)99 static void amixer_usage(void)
100 {
101 printf("Usage: amixer <options> [command]\n");
102 printf("\nAvailable options:\n");
103 printf(" -c,--card N select the card\n");
104 printf("\nAvailable commands:\n");
105 printf(" amixer show all controls for default card\n");
106 printf(" amixer set numid val set control contents for one control\n");
107 printf(" amixer get numid get control contents for one control\n");
108 }
109
amixer(int argc,char * argv[])110 static int amixer(int argc, char *argv[])
111 {
112 static char g_card_name[64] = "audiocodec";
113 int ret = 0;
114 int numid = 0;
115 char *ctl_name = NULL;
116 const char *card_name = NULL;
117 snd_ctl_info_t info;
118 int morehelp = 0;
119 const struct option long_option[] = {
120 {"help", 0, NULL, 'h'},
121 {"list", 0, NULL, 'l'},
122 {"card", 1, NULL, 'c'},
123 {NULL, 0, NULL, 0},
124 };
125
126 while (1) {
127 int c;
128
129 if ((c = getopt_long(argc, argv, "hlc:", long_option, NULL)) < 0)
130 break;
131 switch (c) {
132 case 'h':
133 amixer_usage();
134 return 0;
135 case 'l':
136 asound_list();
137 return 0;
138 case 'c': {
139 int card_index = 0;
140
141 if (isdigit((unsigned char)(*optarg))) {
142 sscanf(optarg, "%d", &card_index);
143 card_name = snd_card_name(card_index);
144 if (card_name == NULL) {
145 fprintf(stderr, "Invalid card number.\n");
146 morehelp++;
147 } else {
148 strncpy(g_card_name, card_name, 64);
149 }
150 } else
151 strncpy(g_card_name, optarg, 64);
152 fprintf(stderr, "Card Name:%s.\n", g_card_name);
153 }
154 break;
155 default:
156 fprintf(stderr, "Invalid switch or option needs an argument.\n");
157 morehelp++;
158 }
159 }
160
161 if (morehelp) {
162 amixer_usage();
163 return 1;
164 }
165
166 if ((argc == 1) || ((argc - optind) <= 0)) {
167 return amixer_controls(g_card_name);
168 }
169
170 if (!strcmp("get", argv[optind])) {
171 if (!snd_ctl_get_bynum(g_card_name, atoi(argv[optind + 1]), &info)) {
172 amixer_ctl_info_print(&info);
173 return 0;
174 }
175 } else if (!strcmp("set", argv[optind])) {
176 int value = -1;
177 numid = atoi(argv[optind + 1]);
178 if (argc >= 4)
179 value = atoi(argv[optind + 2]);
180
181 if (value >= 0) {
182 if (snd_ctl_get_bynum(g_card_name, numid, &info) != 0) {
183 printf("snd_ctl_get failed\n");
184 return -1;
185 }
186 snd_ctl_set_bynum(g_card_name, numid, value);
187 }
188 if (!snd_ctl_get_bynum(g_card_name, numid, &info)) {
189 amixer_ctl_info_print(&info);
190 return 0;
191 }
192 } else {
193 amixer_usage();
194 }
195
196 return 0;
197 }
198
cmd_amixer(int argc,char ** argv)199 int cmd_amixer(int argc, char ** argv)
200 {
201 amixer(argc, argv);
202 return 0;
203 }
204 FINSH_FUNCTION_EXPORT_CMD(cmd_amixer, amixer, amixer utils);
205