Home | History | Annotate | Download | only in libalsa-intf
      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