1 /*
2 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * 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
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of Code Aurora Forum, Inc. nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/ioctl.h>
31 #include <sys/stat.h>
32 #include <linux/ioctl.h>
33 #include <fcntl.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <stdlib.h>
38
39 #include "alsa_ucm.h"
40 #include "msm8960_use_cases.h"
41
42 /* Function prototypes */
43 static void print_help_menu(void);
44 static void alsaucm_test_cmd_svr(void);
45 static int process_cmd(char *cmdStr);
46
47 /* Global data */
48 snd_use_case_mgr_t *uc_mgr;
49
50 /* Defines */
51 enum ucm_cmd_id {
52 UCM_OPEN = 0,
53 UCM_SET,
54 UCM_LISTCARDS,
55 UCM_LIST,
56 UCM_GET,
57 UCM_GETI,
58 UCM_RESET,
59 UCM_RELOAD,
60 UCM_HELP,
61 UCM_QUIT,
62 UCM_UNKNOWN
63 };
64
65 struct cmd {
66 enum ucm_cmd_id code;
67 const char *cmd_str;
68 };
69
70 static struct cmd cmds[] = {
71 { UCM_OPEN, "open" },
72 { UCM_SET, "set" },
73 { UCM_LISTCARDS, "listcards" },
74 { UCM_LIST, "list" },
75 { UCM_GET, "get" },
76 { UCM_GETI, "geti" },
77 { UCM_RESET, "reset" },
78 { UCM_RELOAD, "reload" },
79 { UCM_HELP, "help" },
80 { UCM_QUIT, "quit" },
81 { UCM_UNKNOWN, NULL }
82 };
83
alsaucm_test_cmd_svr(void)84 static void alsaucm_test_cmd_svr(void)
85 {
86 int fd;
87 ssize_t read_count;
88 char cmdstr[256] = {'\0'};
89 char ch;
90 char *exit_str = "quit";
91
92 if (mknod("/data/alsaucm_test", S_IFIFO | 0666, 0) == 0) {
93 fd = open("/data/alsaucm_test", O_RDONLY);
94 while (1) {
95 read_count = read(fd, &ch, 1);
96 if (read_count == 0) {
97 sleep(2);
98 continue;
99 } else if (read_count < 0) {
100 fprintf(stderr, "alsaucm_test: error reading cmd\n");
101 break;
102 }
103
104 if (ch != '\n') {
105 strlcat(cmdstr, &ch , (2+strlen(cmdstr)));
106 continue;
107 } else {
108 if (!strncmp(cmdstr, exit_str, strlen(cmdstr))) {
109 /* free UCM instace */
110 if (uc_mgr) {
111 snd_use_case_mgr_close(uc_mgr);
112 uc_mgr = NULL;
113 }
114 break;
115 } else {
116 process_cmd(cmdstr);
117 memset(cmdstr, 0, sizeof(cmdstr));
118 }
119 }
120 }
121 printf("alsaucm_test: exit server mode\n");
122 close(fd);
123 remove("/data/alsaucm_test");
124 } else {
125 fprintf(stderr, "alsaucm_test: Failed to create server\n");
126 }
127 }
128
129
print_help_menu(void)130 static void print_help_menu(void)
131 {
132 printf("\nAvailable commands:\n"
133 " open NAME open card NAME\n"
134 " reset reset sound card to default state\n"
135 " reload reload configuration\n"
136 " listcards list available cards\n"
137 " list IDENTIFIER list command\n"
138 " get IDENTIFIER get string value\n"
139 " geti IDENTIFIER get integer value\n"
140 " set IDENTIFIER VALUE set string value\n"
141 " help help\n"
142 " quit quit\n");
143 }
144
main(int argc,char ** argv)145 int main(int argc, char **argv)
146 {
147 char *help_str = "help";
148 argc--;
149 argv++;
150
151 if (argc > 0) {
152 if (!strncmp(argv[0], help_str, strlen(argv[0])))
153 print_help_menu();
154 } else
155 alsaucm_test_cmd_svr();
156 return 0;
157 }
158
process_cmd(char * cmdStr)159 static int process_cmd(char *cmdStr)
160 {
161 const char **list = NULL , *str = NULL;
162 long lval;
163 int err, i;
164 char *command = NULL;
165 int count = 0;
166 char *identifier = NULL, *value = NULL;
167 struct cmd *cmd = NULL;
168
169 command = strtok_r(cmdStr, " ", &value);
170 identifier = strtok_r(NULL, " ", &value);
171
172 if (command == NULL) {
173 fprintf(stderr, "NULL pointer encountered. Invalid value for command");
174 return -1;
175 }
176
177 for (cmd = cmds; cmd->cmd_str != NULL; cmd++) {
178 if (strncmp(cmd->cmd_str, command, strlen(cmd->cmd_str)) == 0)
179 break;
180 }
181
182 if (cmd->cmd_str == NULL) {
183 fprintf(stderr, "Unknown command '%s'\n", command);
184 return -EINVAL;
185 }
186
187 if ((identifier == NULL) && ((cmd->code != UCM_HELP) &&
188 (cmd->code != UCM_LISTCARDS) && (cmd->code != UCM_RESET) &&
189 (cmd->code != UCM_RELOAD)))
190 {
191 fprintf(stderr, "NULL pointer encountered. Invalid value for identifier");
192 return -1;
193 }
194
195 switch (cmd->code) {
196 case UCM_HELP:
197 print_help_menu();
198 break;
199
200 case UCM_OPEN:
201 if (uc_mgr) {
202 snd_use_case_mgr_close(uc_mgr);
203 uc_mgr = NULL;
204 }
205
206 err = snd_use_case_mgr_open(&uc_mgr, identifier);
207 if (err < 0) {
208 fprintf(stderr, "%s: error failed to open sound card %s: %d\n", cmd->cmd_str, identifier, err);
209 return err;
210 }
211 snd_use_case_mgr_wait_for_parsing(uc_mgr);
212 break;
213
214 case UCM_LISTCARDS:
215 err = snd_use_case_card_list(&list);
216 if (err < 0) {
217 fprintf(stderr, "%s: error failed to get card list: %d\n", cmd->cmd_str, err);
218 return err;
219 }
220 if (err == 0) {
221 printf("list is empty\n");
222 return 0;
223 }
224
225 for (i = 0; i < err; i++)
226 printf(" %i: %s\n", i+1, list[i]);
227 snd_use_case_free_list(list, err);
228 break;
229
230 case UCM_RESET:
231 if (!uc_mgr) {
232 fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str);
233 return -EINVAL;
234 }
235
236 err = snd_use_case_mgr_reset(uc_mgr);
237 if (err < 0) {
238 fprintf(stderr, "%s: error failed to reset sound card %d\n", cmd->cmd_str, err);
239 return err;
240 }
241 break;
242
243 case UCM_RELOAD:
244 if (!uc_mgr) {
245 fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str);
246 return -EINVAL;
247 }
248
249 err = snd_use_case_mgr_reload(uc_mgr);
250 if (err < 0) {
251 fprintf(stderr, "%s: error failed to reload manager %d\n", cmd->cmd_str, err);
252 return err;
253 }
254 break;
255
256 case UCM_LIST:
257 if (!uc_mgr) {
258 fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str);
259 return -EINVAL;
260 }
261
262 err = snd_use_case_get_list(uc_mgr, identifier, &list);
263 if (err < 0) {
264 fprintf(stderr, "%s: error failed to get list %s: %d\n", cmd->cmd_str, identifier, err);
265 return err;
266 }
267 if (err == 0) {
268 printf("list is empty\n");
269 return 0;
270 }
271 for (i = 0; i < err; i++) {
272 printf(" %i: %s\n", i+1, list[i]);
273 }
274 snd_use_case_free_list(list, err);
275 break;
276
277 case UCM_SET:
278 if (!uc_mgr) {
279 fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str);
280 return -EINVAL;
281 }
282
283 err = snd_use_case_set(uc_mgr, identifier, value);
284 if (err < 0) {
285 fprintf(stderr, "%s: error failed to set %s=%s: %d\n", cmd->cmd_str, identifier, value, err);
286 return err;
287 }
288 break;
289
290 case UCM_GET:
291 if (!uc_mgr) {
292 fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str);
293 return -EINVAL;
294 }
295
296 err = snd_use_case_get(uc_mgr, identifier, &str);
297 if (err < 0) {
298 fprintf(stderr, "%s: error failed to get %s: %d\n", cmd->cmd_str, identifier, err);
299 return err;
300 }
301 printf(" %s=%s\n", identifier, str);
302 free((void *)str);
303 break;
304
305 case UCM_GETI:
306 if (!uc_mgr) {
307 fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str);
308 return -EINVAL;
309 }
310
311 err = snd_use_case_geti(uc_mgr, identifier, &lval);
312 if (err < 0) {
313 fprintf(stderr, "%s: error failed to get integer %s: %d\n", cmd->cmd_str, identifier, err);
314 return lval;
315 }
316 printf(" %s=%li\n", identifier, lval);
317 break;
318
319 default:
320 break;
321 }
322 return 0;
323 }
324
325