[alsa-devel] [PATCH v2] ucm: add cset-tlv
Hsin-Yu Chao
hychao at chromium.org
Wed Mar 23 10:16:42 CET 2016
This patch enables UCM to set a file in TLV format to kcontrol by:
cset-tlv "name='<kcontrol-name>' <path-to-file>"
This new 'cset-tlv' command will be used to write audio DSP to
specific alsa control, where the driver expectes a file in TLV
format.
Signed-off-by: Hsin-Yu Chao <hychao at chromium.org>
---
src/ucm/main.c | 91 +++++++++++++++++++++++++++++++++++++++++++++--------
src/ucm/parser.c | 10 ++++++
src/ucm/ucm_local.h | 1 +
3 files changed, 89 insertions(+), 13 deletions(-)
diff --git a/src/ucm/main.c b/src/ucm/main.c
index 7e44603..c6bbf27 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -161,6 +161,54 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr,
return 0;
}
+static int read_tlv_file(char **res,
+ const char *filepath)
+{
+ int err = 0;
+ int fd;
+ struct stat st;
+ size_t sz;
+ ssize_t sz_read;
+ unsigned int *tlv;
+
+ 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;
+ if (sz > 1024 * 1024 || sz < 8) {
+ uc_error("unsupported file size");
+ 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;
+ free(*res);
+ *res = NULL;
+ }
+ /* Check if the tlv file specifies valid size. */
+ tlv = (unsigned int *)(*res);
+ if (tlv[1] + 2 * sizeof(unsigned int) != sz) {
+ uc_error("Invalid tlv size");
+ free(*res);
+ *res = NULL;
+ }
+
+ __fail:
+ close(fd);
+ return err;
+}
+
static int binary_file_parse(snd_ctl_elem_value_t *dst,
snd_ctl_elem_info_t *info,
const char *filepath)
@@ -226,6 +274,7 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
snd_ctl_elem_id_t *id;
snd_ctl_elem_value_t *value;
snd_ctl_elem_info_t *info;
+ char *res = NULL;
snd_ctl_elem_id_malloc(&id);
snd_ctl_elem_value_malloc(&value);
@@ -241,23 +290,36 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
err = -EINVAL;
goto __fail;
}
- snd_ctl_elem_value_set_id(value, id);
snd_ctl_elem_info_set_id(info, id);
- err = snd_ctl_elem_read(ctl, value);
- if (err < 0)
- goto __fail;
err = snd_ctl_elem_info(ctl, info);
if (err < 0)
goto __fail;
- 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);
- if (err < 0)
- goto __fail;
+ if (type == SEQUENCE_ELEMENT_TYPE_CSET_TLV) {
+ if (!snd_ctl_elem_info_is_tlv_writable(info)) {
+ err = -EINVAL;
+ goto __fail;
+ }
+ err = read_tlv_file(&res, pos);
+ if (err < 0)
+ goto __fail;
+ err = snd_ctl_elem_tlv_write(ctl, id, (unsigned int *)res);
+ if (err < 0)
+ goto __fail;
+ } else {
+ snd_ctl_elem_value_set_id(value, id);
+ err = snd_ctl_elem_read(ctl, value);
+ if (err < 0)
+ goto __fail;
+ 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);
+ if (err < 0)
+ goto __fail;
+ }
err = 0;
__fail:
if (id != NULL)
@@ -266,6 +328,8 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
free(value);
if (info != NULL)
free(info);
+ if (res != NULL)
+ free(res);
return err;
}
@@ -298,6 +362,7 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
break;
case SEQUENCE_ELEMENT_TYPE_CSET:
case SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE:
+ case SEQUENCE_ELEMENT_TYPE_CSET_TLV:
if (cdev == NULL) {
char *playback_ctl = NULL;
char *capture_ctl = NULL;
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index 9e1cb41..d781e1b 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -316,6 +316,16 @@ static int parse_sequence(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
continue;
}
+ if (strcmp(cmd, "cset-tlv") == 0) {
+ curr->type = SEQUENCE_ELEMENT_TYPE_CSET_TLV;
+ err = parse_string(n, &curr->data.cset);
+ if (err < 0) {
+ uc_error("error: cset-tlv 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 3a5d2c2..b89de2a 100644
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -48,6 +48,7 @@
#define SEQUENCE_ELEMENT_TYPE_SLEEP 3
#define SEQUENCE_ELEMENT_TYPE_EXEC 4
#define SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE 5
+#define SEQUENCE_ELEMENT_TYPE_CSET_TLV 6
struct ucm_value {
struct list_head list;
--
2.1.2
More information about the Alsa-devel
mailing list