diff options
author | Lu, Han <han.lu@intel.com> | 2015-01-22 09:32:47 +0800 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-01-23 17:21:27 +0100 |
commit | 6ea14c3624c0cbcf90e7d5859b4af629523b8d82 (patch) | |
tree | 784ff6d0f8c9d4109900ad5d77369a547925cca3 | |
parent | 3b5fac6d10c580aee14642df8f94caad15dd53f0 (diff) | |
download | alsa-lib-6ea14c3624c0cbcf90e7d5859b4af629523b8d82.tar.gz |
ucm: add binary configure file parse
with cset command, UCM set kcontrol parameters directly:
cset "name='<KCONTROL_NAME>' 1<,2,3,...>"
This patch enables UCM to set kcontrol with parameters from
configure file:
cset-bin-file "name='<KCONTROL_NAME>' <path/to/file>"
where "cset-bin-file" is a newly added keyword alongside of "cset",
to indicate cset with binary data in file.
The binary data in file is parameter for audio DSPs, and it's just
passed by UCM/ALSA as raw data. The data type of parameter elements
must be byte, and the count must matches driver definition.
Signed-off-by: Lu, Han <han.lu@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | src/ucm/main.c | 65 | ||||
-rw-r--r-- | src/ucm/parser.c | 10 | ||||
-rw-r--r-- | src/ucm/ucm_local.h | 1 |
3 files changed, 73 insertions, 3 deletions
diff --git a/src/ucm/main.c b/src/ucm/main.c index 37ae4c84..182f1747 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -34,6 +34,7 @@ #include <ctype.h> #include <stdarg.h> #include <pthread.h> +#include <sys/stat.h> /* * misc @@ -160,11 +161,65 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr, return 0; } +static int binary_file_parse(snd_ctl_elem_value_t *dst, + snd_ctl_elem_info_t *info, + const char *filepath) +{ + int err = 0; + int fd; + struct stat st; + size_t sz; + ssize_t sz_read; + char *res; + snd_ctl_elem_type_t type; + unsigned int idx, count; + + type = snd_ctl_elem_info_get_type(info); + if (type != SND_CTL_ELEM_TYPE_BYTES) { + uc_error("only support byte type!"); + err = -EINVAL; + return err; + } + fd = open(filepath, O_RDONLY); + if (fd < 0) { + err = -errno; + return err; + } + if (stat(filepath, &st) == -1) { + err = -errno; + goto __fail; + } + sz = st.st_size; + count = snd_ctl_elem_info_get_count(info); + if (sz != count || sz > sizeof(dst->value.bytes)) { + uc_error("invalid parameter size %d!", sz); + err = -EINVAL; + goto __fail; + } + res = malloc(sz); + if (res == NULL) { + err = -ENOMEM; + goto __fail; + } + sz_read = read(fd, res, sz); + if (sz_read < 0 || (size_t)sz_read != sz) { + err = -errno; + goto __fail_read; + } + for (idx = 0; idx < sz; idx++) + snd_ctl_elem_value_set_byte(dst, idx, *(res + idx)); + __fail_read: + free(res); + __fail: + close(fd); + return err; +} + extern int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str, const char **ret_ptr); -static int execute_cset(snd_ctl_t *ctl, const char *cset) +static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type) { const char *pos; int err; @@ -194,7 +249,10 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset) err = snd_ctl_elem_info(ctl, info); if (err < 0) goto __fail; - err = snd_ctl_ascii_value_parse(ctl, value, info, pos); + if (type == SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE) + err = binary_file_parse(value, info, pos); + else + err = snd_ctl_ascii_value_parse(ctl, value, info, pos); if (err < 0) goto __fail; err = snd_ctl_elem_write(ctl, value); @@ -239,6 +297,7 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr, goto __fail_nomem; break; case SEQUENCE_ELEMENT_TYPE_CSET: + case SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE: if (cdev == NULL) { const char *cdev1 = NULL, *cdev2 = NULL; err = get_value3(&cdev1, "PlaybackCTL", @@ -274,7 +333,7 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr, goto __fail; } } - err = execute_cset(ctl, s->data.cset); + err = execute_cset(ctl, s->data.cset, s->type); if (err < 0) { uc_error("unable to execute cset '%s'\n", s->data.cset); goto __fail; diff --git a/src/ucm/parser.c b/src/ucm/parser.c index d7517f69..9e1cb41a 100644 --- a/src/ucm/parser.c +++ b/src/ucm/parser.c @@ -306,6 +306,16 @@ static int parse_sequence(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, continue; } + if (strcmp(cmd, "cset-bin-file") == 0) { + curr->type = SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE; + err = parse_string(n, &curr->data.cset); + if (err < 0) { + uc_error("error: cset-bin-file requires a string!"); + return err; + } + continue; + } + if (strcmp(cmd, "usleep") == 0) { curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP; err = snd_config_get_integer(n, &curr->data.sleep); diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h index 87f14a29..c1655c70 100644 --- a/src/ucm/ucm_local.h +++ b/src/ucm/ucm_local.h @@ -47,6 +47,7 @@ #define SEQUENCE_ELEMENT_TYPE_CSET 2 #define SEQUENCE_ELEMENT_TYPE_SLEEP 3 #define SEQUENCE_ELEMENT_TYPE_EXEC 4 +#define SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE 5 struct ucm_value { struct list_head list; |