M7350/qcom-opensource/mm-audio/libalsa-intf/alsaucm_test.c
2024-09-09 08:57:42 +00:00

396 lines
11 KiB
C

/*
* 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 <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>
#ifndef ANDROID
#include <stdint.h>
#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;
}