/* * Copyright (c) 2012, 2014 The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #ifndef ANDROID #include #define strlcat g_strlcat #endif #include "alsa_ucm.h" #include "msm8960_use_cases.h" #if defined(QC_PROP) #include "acdb-loader.h" #else #define acdb_loader_init_ACDB() 0 #define acdb_loader_deallocate_ACDB() 0 #endif /* Function prototypes */ static void print_help_menu(void); static void alsaucm_test_cmd_svr(void); static int process_cmd(char *cmdStr); /* Global data */ snd_use_case_mgr_t *uc_mgr; /* Defines */ enum ucm_cmd_id { UCM_OPEN = 0, UCM_SET, UCM_LISTCARDS, UCM_LIST, UCM_GET, UCM_GETI, UCM_RESET, UCM_RELOAD, UCM_HELP, UCM_QUIT, UCM_UNKNOWN }; struct cmd { enum ucm_cmd_id code; const char *cmd_str; }; static struct cmd cmds[] = { { UCM_OPEN, "open" }, { UCM_SET, "set" }, { UCM_LISTCARDS, "listcards" }, { UCM_LIST, "list" }, { UCM_GET, "get" }, { UCM_GETI, "geti" }, { UCM_RESET, "reset" }, { UCM_RELOAD, "reload" }, { UCM_HELP, "help" }, { UCM_QUIT, "quit" }, { UCM_UNKNOWN, NULL } }; #define CVD_VERSION_MIXER_CTL "CVD Version" #define MAX_CVD_VERSION_STRING_SIZE 100 static void get_cvd_version(char *cvd_version) { int ret = 0; int count; struct mixer_ctl *ctl; struct mixer *mixer; const char* device = "/dev/snd/controlC0"; mixer = mixer_open(device); if (!mixer) { fprintf(stderr, "fail to open mixer\n"); return; } ctl = mixer_get_ctl_by_name(mixer, CVD_VERSION_MIXER_CTL); if (!ctl) { fprintf(stderr, "fail to get mixer ctl\n"); goto done; } mixer_ctl_update(ctl); count = mixer_ctl_get_num_values(ctl); if (count > MAX_CVD_VERSION_STRING_SIZE) count = MAX_CVD_VERSION_STRING_SIZE; ret = mixer_ctl_get_array(ctl, cvd_version, count); if (ret != 0) { fprintf(stderr, "fail to get mixer_ctl_get_array\n"); goto done; } done: mixer_close(mixer); return; } static void alsaucm_test_cmd_svr(void) { int fd; ssize_t read_count; char cmdstr[256] = {'\0'}; char ch; char *exit_str = "quit"; char *cvd_version = NULL; cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE); if (!cvd_version) fprintf(stderr, "fail to allocate cvd_version\n"); else get_cvd_version(cvd_version); if ((acdb_loader_init_v2(NULL, cvd_version, 0)) < 0) { fprintf(stderr, "Failed to initialize ACDB\n"); if (cvd_version) free(cvd_version); return 0; } if (cvd_version) free(cvd_version); if (mknod("/data/alsaucm_test", S_IFIFO | 0666, 0) == 0) { fd = open("/data/alsaucm_test", O_RDONLY); while (1) { read_count = read(fd, &ch, 1); if (read_count == 0) { sleep(2); continue; } else if (read_count < 0) { fprintf(stderr, "alsaucm_test: error reading cmd\n"); break; } if (ch != '\n') { strlcat(cmdstr, &ch , (2+strlen(cmdstr))); continue; } else { if (!strncmp(cmdstr, exit_str, strlen(cmdstr))) { /* free UCM instace */ if (uc_mgr) { snd_use_case_mgr_close(uc_mgr); uc_mgr = NULL; } break; } else { process_cmd(cmdstr); memset(cmdstr, 0, sizeof(cmdstr)); } } } printf("alsaucm_test: exit server mode\n"); close(fd); remove("/data/alsaucm_test"); } else { fprintf(stderr, "alsaucm_test: Failed to create server\n"); } acdb_loader_deallocate_ACDB(); } static void print_help_menu(void) { printf("\nAvailable commands:\n" " open NAME open card NAME\n" " reset reset sound card to default state\n" " reload reload configuration\n" " listcards list available cards\n" " list IDENTIFIER list command\n" " get IDENTIFIER get string value\n" " geti IDENTIFIER get integer value\n" " set IDENTIFIER VALUE set string value\n" " help help\n" " quit quit\n"); } int main(int argc, char **argv) { char *help_str = "help"; argc--; argv++; if (argc > 0) { if (!strncmp(argv[0], help_str, strlen(argv[0]))) print_help_menu(); } else alsaucm_test_cmd_svr(); return 0; } static int process_cmd(char *cmdStr) { const char **list = NULL , *str = NULL; long lval; int err, i; char *command = NULL; int count = 0; char *identifier = NULL, *value = NULL; struct cmd *cmd = NULL; command = strtok_r(cmdStr, " ", &value); identifier = strtok_r(NULL, " ", &value); if (command == NULL) { fprintf(stderr, "NULL pointer encountered. Invalid value for command"); return -1; } for (cmd = cmds; cmd->cmd_str != NULL; cmd++) { if (strncmp(cmd->cmd_str, command, strlen(cmd->cmd_str)) == 0) break; } if (cmd->cmd_str == NULL) { fprintf(stderr, "Unknown command '%s'\n", command); return -EINVAL; } if ((identifier == NULL) && ((cmd->code != UCM_HELP) && (cmd->code != UCM_LISTCARDS) && (cmd->code != UCM_RESET) && (cmd->code != UCM_RELOAD))) { fprintf(stderr, "NULL pointer encountered. Invalid value for identifier"); return -1; } switch (cmd->code) { case UCM_HELP: print_help_menu(); break; case UCM_OPEN: if (uc_mgr) { snd_use_case_mgr_close(uc_mgr); uc_mgr = NULL; } err = snd_use_case_mgr_open(&uc_mgr, identifier); if (err < 0) { fprintf(stderr, "%s: error failed to open sound card %s: %d\n", cmd->cmd_str, identifier, err); return err; } break; case UCM_LISTCARDS: err = snd_use_case_card_list(&list); if (err < 0) { fprintf(stderr, "%s: error failed to get card list: %d\n", cmd->cmd_str, err); return err; } if (err == 0) { printf("list is empty\n"); return 0; } for (i = 0; i < err; i++) printf(" %i: %s\n", i+1, list[i]); snd_use_case_free_list(list, err); break; case UCM_RESET: if (!uc_mgr) { fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str); return -EINVAL; } err = snd_use_case_mgr_reset(uc_mgr); if (err < 0) { fprintf(stderr, "%s: error failed to reset sound card %d\n", cmd->cmd_str, err); return err; } break; case UCM_RELOAD: if (!uc_mgr) { fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str); return -EINVAL; } err = snd_use_case_mgr_reload(uc_mgr); if (err < 0) { fprintf(stderr, "%s: error failed to reload manager %d\n", cmd->cmd_str, err); return err; } break; case UCM_LIST: if (!uc_mgr) { fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str); return -EINVAL; } err = snd_use_case_get_list(uc_mgr, identifier, &list); if (err < 0) { fprintf(stderr, "%s: error failed to get list %s: %d\n", cmd->cmd_str, identifier, err); return err; } if (err == 0) { printf("list is empty\n"); return 0; } for (i = 0; i < err; i++) { printf(" %i: %s\n", i+1, list[i]); } snd_use_case_free_list(list, err); break; case UCM_SET: if (!uc_mgr) { fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str); return -EINVAL; } err = snd_use_case_set(uc_mgr, identifier, value); if (err < 0) { fprintf(stderr, "%s: error failed to set %s=%s: %d\n", cmd->cmd_str, identifier, value, err); return err; } break; case UCM_GET: if (!uc_mgr) { fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str); return -EINVAL; } err = snd_use_case_get(uc_mgr, identifier, &str); if (err < 0) { fprintf(stderr, "%s: error failed to get %s: %d\n", cmd->cmd_str, identifier, err); return err; } if (str != NULL) printf(" %s=%s\n", identifier, str); free((void *)str); break; case UCM_GETI: if (!uc_mgr) { fprintf(stderr, "No card is opened before. %s command can't be executed\n", cmd->cmd_str); return -EINVAL; } err = snd_use_case_geti(uc_mgr, identifier, &lval); if (err < 0) { fprintf(stderr, "%s: error failed to get integer %s: %d\n", cmd->cmd_str, identifier, err); return lval; } printf(" %s=%li\n", identifier, lval); break; default: break; } return 0; }