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 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 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 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 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