| /* |
| * Copyright (c) 2012, 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 <sys/ioctl.h> |
| #include <sys/stat.h> |
| #include <linux/ioctl.h> |
| #include <fcntl.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <errno.h> |
| #include <stdlib.h> |
| |
| #include "alsa_ucm.h" |
| #include "msm8960_use_cases.h" |
| |
| /* 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 } |
| }; |
| |
| static void alsaucm_test_cmd_svr(void) |
| { |
| int fd; |
| ssize_t read_count; |
| char cmdstr[256] = {'\0'}; |
| char ch; |
| char *exit_str = "quit"; |
| |
| 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"); |
| } |
| } |
| |
| |
| 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; |
| } |
| snd_use_case_mgr_wait_for_parsing(uc_mgr); |
| 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; |
| } |
| 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; |
| } |
| |