You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
9.5 KiB
324 lines
9.5 KiB
/* |
|
* Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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; |
|
} |
|
|
|
|