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