alsa-lib/alsa-git.patch
2020-02-09 20:19:22 +01:00

22621 lines
716 KiB
Diff

From c79f09e1f5e8b559b58dacdb00708d995b2e3aa5 Mon Sep 17 00:00:00 2001
From: paulhsia <paulhsia@chromium.org>
Date: Sat, 30 Nov 2019 03:35:30 +0800
Subject: [PATCH 01/69] ucm: Use strncmp to avoid access-out-of-boundary
If the length of the identifier is less than the length of the prefix,
access-out-of-boundary will occur in memcmp().
Signed-off-by: paulhsia <paulhsia@chromium.org>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/main.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/ucm/main.c b/src/ucm/main.c
index b0b6ffb3..252e50d9 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -61,11 +61,13 @@ static int check_identifier(const char *identifier, const char *prefix)
{
int len;
- if (strcmp(identifier, prefix) == 0)
- return 1;
len = strlen(prefix);
- if (memcmp(identifier, prefix, len) == 0 && identifier[len] == '/')
+ if (strncmp(identifier, prefix, len) != 0)
+ return 0;
+
+ if (identifier[len] == 0 || identifier[len] == '/')
return 1;
+
return 0;
}
--
2.24.1
From 9baf64da2f26844434ecea4825052937a3abe06c Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 29 Nov 2019 22:28:26 +0100
Subject: [PATCH 02/69] ucm: return always at least NULL if no list is
available in snd_use_case_get_list()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/main.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/ucm/main.c b/src/ucm/main.c
index 252e50d9..b80db65f 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -1160,8 +1160,10 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr,
modifier = find_modifier(uc_mgr, verb, name, 0);
if (modifier) {
- if (modifier->dev_list.type != type)
+ if (modifier->dev_list.type != type) {
+ *list = NULL;
return 0;
+ }
return get_list(&modifier->dev_list.list, list,
struct dev_list_node, list,
name);
@@ -1169,8 +1171,10 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr,
device = find_device(uc_mgr, verb, name, 0);
if (device) {
- if (device->dev_list.type != type)
+ if (device->dev_list.type != type) {
+ *list = NULL;
return 0;
+ }
return get_list(&device->dev_list.list, list,
struct dev_list_node, list,
name);
--
2.24.1
From ebdd2b6cdb8119cf75f0dd0a3b283d271b3a547e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 30 Nov 2019 20:31:55 +0100
Subject: [PATCH 03/69] ucm: add _identifiers list
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 1 +
src/ucm/main.c | 268 ++++++++++++++++++++++++++++++++++-----------
2 files changed, 208 insertions(+), 61 deletions(-)
diff --git a/include/use-case.h b/include/use-case.h
index 8e7e838c..85c58ac0 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -206,6 +206,7 @@ int snd_use_case_free_list(const char *list[], int items);
* - _enadevs - get list of enabled devices
* - _enamods - get list of enabled modifiers
*
+ * - _identifiers/{modifier}|{device}[/{verb}] - list of value identifiers
* - _supporteddevs/{modifier}|{device}[/{verb}] - list of supported devices
* - _conflictingdevs/{modifier}|{device}[/{verb}] - list of conflicting devices
*
diff --git a/src/ucm/main.c b/src/ucm/main.c
index b80db65f..d2078a23 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -1072,7 +1072,6 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
/**
* \brief Get list of verbs in pair verbname+comment
* \param list Returned list
- * \param verbname For verb (NULL = current)
* \return Number of list entries if success, otherwise a negative error code
*/
static int get_verb_list(snd_use_case_mgr_t *uc_mgr, const char **list[])
@@ -1181,7 +1180,6 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr,
}
return -ENOENT;
-
}
/**
@@ -1210,41 +1208,201 @@ static int get_conflicting_device_list(snd_use_case_mgr_t *uc_mgr,
#ifndef DOC_HIDDEN
struct myvalue {
- struct list_head list;
- char *value;
+ struct list_head list;
+ const char *text;
};
#endif
+/**
+ * \brief Convert myvalue list string list
+ * \param list myvalue list
+ * \param res string list
+ * \retval Number of list entries if success, otherwise a negativer error code
+ */
+static int myvalue_to_str_list(struct list_head *list, char ***res)
+{
+ struct list_head *pos;
+ struct myvalue *value;
+ char **p;
+ int cnt;
+
+ cnt = alloc_str_list(list, 1, res);
+ if (cnt < 0)
+ return cnt;
+ p = *res;
+ list_for_each(pos, list) {
+ value = list_entry(pos, struct myvalue, list);
+ *p = strdup(value->text);
+ if (*p == NULL) {
+ snd_use_case_free_list((const char **)p, cnt);
+ return -ENOMEM;
+ }
+ p++;
+ }
+ return cnt;
+}
+
+/**
+ * \brief Free myvalue list
+ * \param list myvalue list
+ */
+static void myvalue_list_free(struct list_head *list)
+{
+ struct list_head *pos, *npos;
+ struct myvalue *value;
+
+ list_for_each_safe(pos, npos, list) {
+ value = list_entry(pos, struct myvalue, list);
+ list_del(&value->list);
+ free(value);
+ }
+}
+
+/**
+ * \brief Merge one value to the myvalue list
+ * \param list The list with values
+ * \param value The value to be merged (without duplicates)
+ * \return 1 if dup, 0 if success, otherwise a negative error code
+ */
+static int merge_value(struct list_head *list, const char *text)
+{
+ struct list_head *pos;
+ struct myvalue *value;
+
+ list_for_each(pos, list) {
+ value = list_entry(pos, struct myvalue, list);
+ if (strcmp(value->text, text) == 0)
+ return 1;
+ }
+ value = malloc(sizeof(*value));
+ if (value == NULL)
+ return -ENOMEM;
+ value->text = text;
+ list_add_tail(&value->list, list);
+ return 0;
+}
+
+/**
+ * \brief Find all values for given identifier
+ * \param list Returned list
+ * \param source Source list with ucm_value structures
+ * \return Zero if success, otherwise a negative error code
+ */
+static int add_identifiers(struct list_head *list,
+ struct list_head *source)
+{
+ struct ucm_value *v;
+ struct list_head *pos;
+ int err;
+
+ list_for_each(pos, source) {
+ v = list_entry(pos, struct ucm_value, list);
+ err = merge_value(list, v->name);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+/**
+ * \brief Find all values for given identifier
+ * \param list Returned list
+ * \param identifier Identifier
+ * \param source Source list with ucm_value structures
+ */
static int add_values(struct list_head *list,
const char *identifier,
struct list_head *source)
{
- struct ucm_value *v;
- struct myvalue *val;
- struct list_head *pos, *pos1;
- int match;
+ struct ucm_value *v;
+ struct list_head *pos;
+ int err;
- list_for_each(pos, source) {
- v = list_entry(pos, struct ucm_value, list);
- if (check_identifier(identifier, v->name)) {
- match = 0;
- list_for_each(pos1, list) {
- val = list_entry(pos1, struct myvalue, list);
- if (strcmp(val->value, v->data) == 0) {
- match = 1;
- break;
- }
- }
- if (!match) {
- val = malloc(sizeof(struct myvalue));
- if (val == NULL)
- return -ENOMEM;
- val->value = v->data;
- list_add_tail(&val->list, list);
- }
- }
- }
- return 0;
+ list_for_each(pos, source) {
+ v = list_entry(pos, struct ucm_value, list);
+ if (check_identifier(identifier, v->name)) {
+ err = merge_value(list, v->data);
+ if (err < 0)
+ return err;
+ }
+ }
+ return 0;
+}
+
+/**
+ * \brief compare two identifiers
+ */
+static int identifier_cmp(const void *_a, const void *_b)
+{
+ const char * const *a = _a;
+ const char * const *b = _b;
+ return strcmp(*a, *b);
+}
+
+/**
+ * \brief Get list of available identifiers
+ * \param list Returned list
+ * \param name Name of verb or modifier to query
+ * \return Number of list entries if success, otherwise a negative error code
+ */
+static int get_identifiers_list(snd_use_case_mgr_t *uc_mgr,
+ const char **list[], char *name)
+{
+ struct use_case_verb *verb;
+ struct use_case_modifier *modifier;
+ struct use_case_device *device;
+ struct list_head mylist;
+ struct list_head *value_list;
+ char *str, **res;
+ int err;
+
+ if (!name)
+ return -ENOENT;
+
+ str = strchr(name, '/');
+ if (str) {
+ *str = '\0';
+ verb = find_verb(uc_mgr, str + 1);
+ }
+ else {
+ verb = uc_mgr->active_verb;
+ }
+ if (!verb)
+ return -ENOENT;
+
+ value_list = NULL;
+ modifier = find_modifier(uc_mgr, verb, name, 0);
+ if (modifier) {
+ value_list = &modifier->value_list;
+ } else {
+ device = find_device(uc_mgr, verb, name, 0);
+ if (device)
+ value_list = &device->value_list;
+ }
+ if (value_list == NULL)
+ return -ENOENT;
+
+ INIT_LIST_HEAD(&mylist);
+ err = add_identifiers(&mylist, &uc_mgr->value_list);
+ if (err < 0)
+ goto __fail;
+ err = add_identifiers(&mylist, &verb->value_list);
+ if (err < 0)
+ goto __fail;
+ err = add_identifiers(&mylist, value_list);
+ if (err < 0)
+ goto __fail;
+ err = myvalue_to_str_list(&mylist, &res);
+ if (err > 0)
+ *list = (const char **)res;
+ else if (err == 0)
+ *list = NULL;
+__fail:
+ myvalue_list_free(&mylist);
+ if (err <= 0)
+ return err;
+ qsort(*list, err, sizeof(char *), identifier_cmp);
+ return err;
}
/**
@@ -1258,8 +1416,7 @@ static int get_value_list(snd_use_case_mgr_t *uc_mgr,
const char **list[],
char *verbname)
{
- struct list_head mylist, *pos, *npos;
- struct myvalue *val;
+ struct list_head mylist, *pos;
struct use_case_verb *verb;
struct use_case_device *dev;
struct use_case_modifier *mod;
@@ -1292,26 +1449,13 @@ static int get_value_list(snd_use_case_mgr_t *uc_mgr,
if (err < 0)
goto __fail;
}
- err = alloc_str_list(&mylist, 1, &res);
- if (err >= 0) {
+ err = myvalue_to_str_list(&mylist, &res);
+ if (err > 0)
*list = (const char **)res;
- list_for_each(pos, &mylist) {
- val = list_entry(pos, struct myvalue, list);
- *res = strdup(val->value);
- if (*res == NULL) {
- snd_use_case_free_list((const char **)res, err);
- err = -ENOMEM;
- goto __fail;
- }
- res++;
- }
- }
+ else if (err == 0)
+ *list = NULL;
__fail:
- list_for_each_safe(pos, npos, &mylist) {
- val = list_entry(pos, struct myvalue, list);
- list_del(&val->list);
- free(val);
- }
+ myvalue_list_free(&mylist);
return err;
}
@@ -1381,21 +1525,23 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
} else {
str = NULL;
}
- if (check_identifier(identifier, "_devices"))
- err = get_device_list(uc_mgr, list, str);
+ if (check_identifier(identifier, "_devices"))
+ err = get_device_list(uc_mgr, list, str);
else if (check_identifier(identifier, "_modifiers"))
- err = get_modifier_list(uc_mgr, list, str);
- else if (check_identifier(identifier, "_supporteddevs"))
- err = get_supported_device_list(uc_mgr, list, str);
- else if (check_identifier(identifier, "_conflictingdevs"))
- err = get_conflicting_device_list(uc_mgr, list, str);
+ err = get_modifier_list(uc_mgr, list, str);
+ else if (check_identifier(identifier, "_identifiers"))
+ err = get_identifiers_list(uc_mgr, list, str);
+ else if (check_identifier(identifier, "_supporteddevs"))
+ err = get_supported_device_list(uc_mgr, list, str);
+ else if (check_identifier(identifier, "_conflictingdevs"))
+ err = get_conflicting_device_list(uc_mgr, list, str);
else if (identifier[0] == '_')
err = -ENOENT;
- else
- err = get_value_list(uc_mgr, identifier, list, str);
- if (str)
- free(str);
- }
+ else
+ err = get_value_list(uc_mgr, identifier, list, str);
+ if (str)
+ free(str);
+ }
__end:
pthread_mutex_unlock(&uc_mgr->mutex);
return err;
--
2.24.1
From 5ee5ef31b5ff3fb7c904054cb9cac7478a727f7c Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 1 Dec 2019 14:26:40 +0100
Subject: [PATCH 04/69] namehint: correct the @args check
BugLink: https://github.com/alsa-project/alsa-plugins/issues/3
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/control/namehint.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/control/namehint.c b/src/control/namehint.c
index 808df6b5..4927ef97 100644
--- a/src/control/namehint.c
+++ b/src/control/namehint.c
@@ -348,6 +348,12 @@ static int try_config(snd_config_t *config,
goto __cleanup;
if (snd_config_search(res, "@args", &cfg) >= 0) {
snd_config_for_each(i, next, cfg) {
+ /* skip the argument list */
+ snd_config_get_id(snd_config_iterator_entry(i), &str);
+ while (*str && *str >= '0' && *str <= '9') str++;
+ if (*str == '\0')
+ continue;
+ /* the argument definition must have the default */
if (snd_config_search(snd_config_iterator_entry(i),
"default", NULL) < 0) {
err = -EINVAL;
--
2.24.1
From 6055f8a584296abfc0cec0439ceb708f0eddcc9d Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 1 Dec 2019 14:30:54 +0100
Subject: [PATCH 05/69] namehint: improve the previous patch (check the
returned value)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/control/namehint.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/control/namehint.c b/src/control/namehint.c
index 4927ef97..60c48ae3 100644
--- a/src/control/namehint.c
+++ b/src/control/namehint.c
@@ -349,7 +349,8 @@ static int try_config(snd_config_t *config,
if (snd_config_search(res, "@args", &cfg) >= 0) {
snd_config_for_each(i, next, cfg) {
/* skip the argument list */
- snd_config_get_id(snd_config_iterator_entry(i), &str);
+ if (snd_config_get_id(snd_config_iterator_entry(i), &str) < 0)
+ continue;
while (*str && *str >= '0' && *str <= '9') str++;
if (*str == '\0')
continue;
--
2.24.1
From 4dddcf733d56a13f4d042fefa1fb6230c09f1f65 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 2 Dec 2019 11:56:30 +0100
Subject: [PATCH 06/69] ucm: docs - allow spaces in device names for JackHWMute
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/include/use-case.h b/include/use-case.h
index 85c58ac0..e1f58027 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -326,7 +326,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* - Valid values: "soft" (software attenuation)
* - EDIDFile
* - Path to EDID file for HDMI devices
- * - JackControl, JackDev, JackHWMute
+ * - JackControl, JackDev
* - Jack information for a device. The jack status can be reported via
* a kcontrol and/or via an input device. **JackControl** is the
* kcontrol name of the jack, and **JackDev** is the input device id of
@@ -334,17 +334,18 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* JackDev value should be "foo"). UCM configuration files should
* contain both JackControl and JackDev when possible, because
* applications are likely to support only one or the other.
- *
- * If **JackHWMute** is set, it indicates that when the jack is plugged
- * in, the hardware automatically mutes some other device(s). The
- * JackHWMute value is a space-separated list of device names (this
- * isn't compatible with device names with spaces in them, so don't use
- * such device names!). Note that JackHWMute should be used only when
- * the hardware enforces the automatic muting. If the hardware doesn't
- * enforce any muting, it may still be tempting to set JackHWMute to
- * trick upper software layers to e.g. automatically mute speakers when
- * headphones are plugged in, but that's application policy
- * configuration that doesn't belong to UCM configuration files.
+ * - JackHWMute
+ * If this value is set, it indicates that when the jack is plugged
+ * in, the hardware automatically mutes some other device(s). The
+ * value is a space-separated list of device names. If the device
+ * name contains space, it must be enclosed to ' or ", e.g.:
+ * JackHWMute "'Dock Headphone' Headphone"
+ * Note that JackHWMute should be used only when the hardware enforces
+ * the automatic muting. If the hardware doesn't enforce any muting, it
+ * may still be tempting to set JackHWMute to trick upper software layers
+ * to e.g. automatically mute speakers when headphones are plugged in,
+ * but that's application policy configuration that doesn't belong
+ * to UCM configuration files.
* - MinBufferLevel
* - This is used on platform where reported buffer level is not accurate.
* E.g. "512", which holds 512 samples in device buffer. Note: this will
--
2.24.1
From 2a286ca9a8415571181ce58027686ec332a834e9 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 2 Dec 2019 11:57:18 +0100
Subject: [PATCH 07/69] use-case: docs - add PlaybackMixerCopy and
CaptureMixerCopy
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/include/use-case.h b/include/use-case.h
index e1f58027..71fcc949 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -309,8 +309,14 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* - PlaybackMixerElem
* - mixer element playback identifier
* - can be parsed using snd_use_case_parse_selem_id()
+ * - PlaybackMixerCopy
+ * - additional mixer element playback identifier
+ * - can be parsed using snd_use_case_parse_selem_id()
+ * - those elements should copy the volume and switch settings
+ * - element identifiers are separated using the | character
* - PlaybackMasterElem
* - mixer element playback identifier for the master control
+ * - can be parsed using snd_use_case_parse_selem_id()
* - PlaybackMasterType
* - type of the master volume control
* - Valid values: "soft" (software attenuation)
@@ -319,8 +325,14 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* - CaptureMixerElem
* - mixer element capture identifier
* - can be parsed using snd_use_case_parse_selem_id()
+ * - CaptureMixerCopy
+ * - additional mixer element capture identifier
+ * - can be parsed using snd_use_case_parse_selem_id()
+ * - those elements should copy the volume and switch settings
+ * - element identifiers are separated using the | character
* - CaptureMasterElem
* - mixer element playback identifier for the master control
+ * - can be parsed using snd_use_case_parse_selem_id()
* - CaptureMasterType
* - type of the master volume control
* - Valid values: "soft" (software attenuation)
--
2.24.1
From a0fc4447bb7c7f9a850a0a85f3a5a32c1509caf4 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 3 Dec 2019 15:01:04 +0100
Subject: [PATCH 08/69] ucm: docs - add JackCTL, rearrange JackControl and
JackDev
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/include/use-case.h b/include/use-case.h
index 71fcc949..25998cb9 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -338,14 +338,20 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* - Valid values: "soft" (software attenuation)
* - EDIDFile
* - Path to EDID file for HDMI devices
- * - JackControl, JackDev
- * - Jack information for a device. The jack status can be reported via
- * a kcontrol and/or via an input device. **JackControl** is the
- * kcontrol name of the jack, and **JackDev** is the input device id of
- * the jack (if the full input device path is /dev/input/by-id/foo, the
- * JackDev value should be "foo"). UCM configuration files should
- * contain both JackControl and JackDev when possible, because
- * applications are likely to support only one or the other.
+ * - JackCTL
+ * - jack control device name
+ * - JackControl
+ * - jack control identificator
+ * - can be parsed using snd_use_case_parse_ctl_elem_id()
+ * - UCM configuration files should contain both JackControl and JackDev
+ * when possible, because applications are likely to support only one
+ * or the other
+ * - JackDev
+ * - the input device id of the jack (if the full input device path is
+ * /dev/input/by-id/foo, the JackDev value should be "foo")
+ * - UCM configuration files should contain both JackControl and JackDev
+ * when possible, because applications are likely to support only one
+ * or the other
* - JackHWMute
* If this value is set, it indicates that when the jack is plugged
* in, the hardware automatically mutes some other device(s). The
--
2.24.1
From e59034a0bec257cc7422a1e9436d936be8696a6f Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 3 Dec 2019 18:27:39 +0100
Subject: [PATCH 09/69] ucm: Do not fail to parse configs on cards with an
empty CardComponents lists
Since the UCM profiles for all Bay- and Cherry-Trail SST cards have been
moved over to UCM2, parsing them fails with:
ALSA lib ucm_subs.c:220:(uc_mgr_get_substituted_value) variable '${CardComponents}' is not defined in this context!
This completely breaks audio support on all Bay- and Cherry-Trail devices.
This is caused by these non-SOF ASoC using cards having an empty
CardComponents list. Which in itself is fine, but is rejected by
the ucm_subs.c code. This commit changes the ucm_subs code to accept
an empty string as a valid value for CardComponents restoring audio
functionality on these boards.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/ucm_subs.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
index 00afa9e3..90e395f0 100644
--- a/src/ucm/ucm_subs.c
+++ b/src/ucm/ucm_subs.c
@@ -25,6 +25,7 @@
*/
#include "ucm_local.h"
+#include <stdbool.h>
#include <sys/stat.h>
#include <limits.h>
@@ -145,10 +146,11 @@ static char *rval_sysfs(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char
return strdup(path);
}
-#define MATCH_VARIABLE(name, id, fcn) \
+#define MATCH_VARIABLE(name, id, fcn, empty_ok) \
if (strncmp((name), (id), sizeof(id) - 1) == 0) { \
rval = fcn(uc_mgr); \
idsize = sizeof(id) - 1; \
+ allow_empty = (empty_ok); \
goto __rval; \
}
@@ -189,12 +191,14 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr,
while (*value) {
if (*value == '$' && *(value+1) == '{') {
- MATCH_VARIABLE(value, "${ConfName}", rval_conf_name);
- MATCH_VARIABLE(value, "${CardId}", rval_card_id);
- MATCH_VARIABLE(value, "${CardDriver}", rval_card_driver);
- MATCH_VARIABLE(value, "${CardName}", rval_card_name);
- MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname);
- MATCH_VARIABLE(value, "${CardComponents}", rval_card_components);
+ bool allow_empty = false;
+
+ MATCH_VARIABLE(value, "${ConfName}", rval_conf_name, false);
+ MATCH_VARIABLE(value, "${CardId}", rval_card_id, false);
+ MATCH_VARIABLE(value, "${CardDriver}", rval_card_driver, false);
+ MATCH_VARIABLE(value, "${CardName}", rval_card_name, false);
+ MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname, false);
+ MATCH_VARIABLE(value, "${CardComponents}", rval_card_components, true);
MATCH_VARIABLE2(value, "${env:", rval_env);
MATCH_VARIABLE2(value, "${sys:", rval_sysfs);
err = -EINVAL;
@@ -208,7 +212,7 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr,
}
goto __error;
__rval:
- if (rval == NULL || rval[0] == '\0') {
+ if (rval == NULL || (!allow_empty && rval[0] == '\0')) {
free(rval);
strncpy(r, value, idsize);
r[idsize] = '\0';
--
2.24.1
From 8e2c70add782f997f7c269ed3f722888e56ff024 Mon Sep 17 00:00:00 2001
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Date: Tue, 3 Dec 2019 18:56:40 +0100
Subject: [PATCH 10/69] src/ucm/main.c: fix build without mixer
Commit 4ce38a5ff466d18039b2606938f866ea3a6c9f3c breaks the build without
mixer on:
CCLD libasound.la
/home/buildroot/autobuild/instance-1/output-1/host/lib/gcc/xtensa-buildroot-linux-uclibc/8.3.0/../../../../xtensa-buildroot-linux-uclibc/bin/ld: ucm/.libs/libucm.a(main.o): in function `snd_use_case_set':
main.c:(.text+0x185c): undefined reference to `snd_mixer_selem_id_parse'
Fixes: http://autobuild.buildroot.org/results/4d91c9f82a2a61c50c457a851073b85cc09ea345
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/ucm/main.c b/src/ucm/main.c
index d2078a23..61922f10 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -2115,8 +2115,10 @@ int snd_use_case_parse_selem_id(snd_mixer_selem_id_t *dst,
const char *ucm_id,
const char *value)
{
+#ifdef BUILD_MIXER
if (strcmp(ucm_id, "PlaybackMixerId") == 0 ||
strcmp(ucm_id, "CaptureMixerId") == 0)
return snd_mixer_selem_id_parse(dst, value);
+#endif
return -EINVAL;
}
--
2.24.1
From ad8527d81b09c4d0edd054b5b1468ce1c50b23cb Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 4 Dec 2019 09:49:40 +0100
Subject: [PATCH 11/69] alsa.m4: another try to fix the libatopology detection
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
utils/alsa.m4 | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/utils/alsa.m4 b/utils/alsa.m4
index 4c457f0d..320e4336 100644
--- a/utils/alsa.m4
+++ b/utils/alsa.m4
@@ -22,6 +22,7 @@ alsa_save_CFLAGS="$CFLAGS"
alsa_save_LDFLAGS="$LDFLAGS"
alsa_save_LIBS="$LIBS"
alsa_found=yes
+alsa_topology_found=no
dnl
dnl Get the cflags and libraries for alsa
@@ -158,11 +159,17 @@ AC_CHECK_LIB([asound], [snd_ctl_open],,
alsa_found=no]
)
if test "x$enable_atopology" = "xyes"; then
+alsa_topology_found=yes
AC_CHECK_LIB([atopology], [snd_tplg_new],,
[ifelse([$3], , [AC_MSG_ERROR(No linkable libatopology was found.)])
- alsa_found=no]
+ alsa_topology_found=no,
+]
)
fi
+else
+if test "x$enable_atopology" = "xyes"; then
+ alsa_topology_found=yes
+fi
fi
if test "x$alsa_found" = "xyes" ; then
@@ -183,7 +190,7 @@ fi
dnl add the alsa topology library; must be at the end
AC_MSG_CHECKING(for ALSA topology LDFLAGS)
-if test "x$enable_atopology" = "xyes"; then
+if test "x$alsa_topology_found" = "xyes"; then
ALSA_TOPOLOGY_LIBS="$ALSA_TOPOLOGY_LIBS -latopology"
fi
AC_MSG_RESULT($ALSA_TOPOLOGY_LIBS)
--
2.24.1
From 555a5dbdabc5ed3be1ca81865abdb997bc3a6082 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 5 Dec 2019 16:59:05 +0100
Subject: [PATCH 12/69] ucm: docs - add Mic/DigitalMic and multiple devices
comments
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/include/use-case.h b/include/use-case.h
index 25998cb9..1736da25 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -114,10 +114,18 @@ extern "C" {
*
* Physical system devices the render and capture audio. Devices can be OR'ed
* together to support audio on simultaneous devices.
+ *
+ * If multiple devices with the same name exists, the number suffixes should
+ * be added to these names like HDMI1,HDMI2,HDMI3 etc. No number gaps are
+ * allowed. The names with numbers must be continuous.
+ *
+ * The preference of the devices is determined by the priority value.
*/
#define SND_USE_CASE_DEV_NONE "None" /**< None Device */
#define SND_USE_CASE_DEV_SPEAKER "Speaker" /**< Speaker Device */
#define SND_USE_CASE_DEV_LINE "Line" /**< Line Device */
+#define SND_USE_CASE_DEV_MIC "Mic" /**< Integrated Analog Microphone */
+#define SND_USE_CASE_DEV_DIGITAL_MIC "DigitalMic" /**< Integrated Digital Microphone */
#define SND_USE_CASE_DEV_HEADPHONES "Headphones" /**< Headphones Device */
#define SND_USE_CASE_DEV_HEADSET "Headset" /**< Headset Device */
#define SND_USE_CASE_DEV_HANDSET "Handset" /**< Handset Device */
--
2.24.1
From 1ad660ddeecb2a364f1ca62aa60f256f7029cfdc Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 5 Dec 2019 17:01:31 +0100
Subject: [PATCH 13/69] ucm: docs - remove DigitalMic, it does not have sense
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/use-case.h b/include/use-case.h
index 1736da25..214a2a4c 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -124,8 +124,7 @@ extern "C" {
#define SND_USE_CASE_DEV_NONE "None" /**< None Device */
#define SND_USE_CASE_DEV_SPEAKER "Speaker" /**< Speaker Device */
#define SND_USE_CASE_DEV_LINE "Line" /**< Line Device */
-#define SND_USE_CASE_DEV_MIC "Mic" /**< Integrated Analog Microphone */
-#define SND_USE_CASE_DEV_DIGITAL_MIC "DigitalMic" /**< Integrated Digital Microphone */
+#define SND_USE_CASE_DEV_MIC "Mic" /**< Integrated Microphone */
#define SND_USE_CASE_DEV_HEADPHONES "Headphones" /**< Headphones Device */
#define SND_USE_CASE_DEV_HEADSET "Headset" /**< Headset Device */
#define SND_USE_CASE_DEV_HANDSET "Handset" /**< Handset Device */
--
2.24.1
From 5473c5d677915b88d5c93d5bcc6cd16bb6a40342 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 5 Dec 2019 17:19:06 +0100
Subject: [PATCH 14/69] ucm: docs - change the Mic description to simple
Microphone Device
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/use-case.h b/include/use-case.h
index 214a2a4c..b04f7b9d 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -124,7 +124,7 @@ extern "C" {
#define SND_USE_CASE_DEV_NONE "None" /**< None Device */
#define SND_USE_CASE_DEV_SPEAKER "Speaker" /**< Speaker Device */
#define SND_USE_CASE_DEV_LINE "Line" /**< Line Device */
-#define SND_USE_CASE_DEV_MIC "Mic" /**< Integrated Microphone */
+#define SND_USE_CASE_DEV_MIC "Mic" /**< Microphone Device */
#define SND_USE_CASE_DEV_HEADPHONES "Headphones" /**< Headphones Device */
#define SND_USE_CASE_DEV_HEADSET "Headset" /**< Headset Device */
#define SND_USE_CASE_DEV_HANDSET "Handset" /**< Handset Device */
--
2.24.1
From ca67e823833213e140a09ce43b6399b7676616df Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 6 Dec 2019 11:11:54 +0100
Subject: [PATCH 15/69] ucm: docs - add note about the sequences and device
split
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/use-case.h b/include/use-case.h
index b04f7b9d..2efcb4d8 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -119,6 +119,11 @@ extern "C" {
* be added to these names like HDMI1,HDMI2,HDMI3 etc. No number gaps are
* allowed. The names with numbers must be continuous.
*
+ * If EnableSequence/DisableSequence controls independent paths in the hardware
+ * it is also recommended to split playback and capture UCM devices and use
+ * the number suffixes. Example use case: Use the integrated microphone
+ * in the laptop instead the microphone in headphones.
+ *
* The preference of the devices is determined by the priority value.
*/
#define SND_USE_CASE_DEV_NONE "None" /**< None Device */
--
2.24.1
From f828dfe549fbab0a920768c63ebd3478272954eb Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 10 Dec 2019 11:48:06 +0100
Subject: [PATCH 16/69] ucm: docs - remove MixerCopy values, add Priority for
verb, improve priority docs
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/use-case.h | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/include/use-case.h b/include/use-case.h
index 2efcb4d8..134303af 100644
--- a/include/use-case.h
+++ b/include/use-case.h
@@ -274,6 +274,10 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* Recommended names for values:
* - TQ
* - Tone Quality
+ * - Priority
+ * - priority value (1-10000), higher value means higher priority
+ * - valid only for verbs
+ * - for devices - PlaybackPriority and CapturePriority
* - PlaybackPCM
* - full PCM playback device name
* - PlaybackPCMIsDummy
@@ -301,7 +305,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* - playback control switch identifier string
* - can be parsed using snd_use_case_parse_ctl_elem_id()
* - PlaybackPriority
- * - priority value (1-10000), default value is 100, higher value means lower priority
+ * - priority value (1-10000), higher value means higher priority
* - CaptureRate
* - capture device sample rate
* - CaptureChannels
@@ -315,17 +319,12 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* - capture control switch identifier string
* - can be parsed using snd_use_case_parse_ctl_elem_id()
* - CapturePriority
- * - priority value (1-10000), default value is 100, higher value means lower priority
+ * - priority value (1-10000), higher value means higher priority
* - PlaybackMixer
* - name of playback mixer
* - PlaybackMixerElem
* - mixer element playback identifier
* - can be parsed using snd_use_case_parse_selem_id()
- * - PlaybackMixerCopy
- * - additional mixer element playback identifier
- * - can be parsed using snd_use_case_parse_selem_id()
- * - those elements should copy the volume and switch settings
- * - element identifiers are separated using the | character
* - PlaybackMasterElem
* - mixer element playback identifier for the master control
* - can be parsed using snd_use_case_parse_selem_id()
@@ -337,11 +336,6 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
* - CaptureMixerElem
* - mixer element capture identifier
* - can be parsed using snd_use_case_parse_selem_id()
- * - CaptureMixerCopy
- * - additional mixer element capture identifier
- * - can be parsed using snd_use_case_parse_selem_id()
- * - those elements should copy the volume and switch settings
- * - element identifiers are separated using the | character
* - CaptureMasterElem
* - mixer element playback identifier for the master control
* - can be parsed using snd_use_case_parse_selem_id()
--
2.24.1
From 1744159180ac94a72036d7232e674c58cedee70a Mon Sep 17 00:00:00 2001
From: Libin Yang <libin.yang@linux.intel.com>
Date: Wed, 11 Dec 2019 14:07:19 +0800
Subject: [PATCH 17/69] ucm: setup conf_format after getting
ALSA_CONFIG_UCM_VAR successfully
Set the conf_format to 1 after getting ALSA_CONFIG_UCM_VAR successfully.
Otherwise, the conf_format is not set in this scenario.
Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index ba500277..d61124a3 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -89,6 +89,8 @@ static void configuration_filename(snd_use_case_mgr_t *uc_mgr,
env = getenv(ALSA_CONFIG_UCM2_VAR);
if (env == NULL) {
env = getenv(ALSA_CONFIG_UCM_VAR);
+ if (env)
+ uc_mgr->conf_format = 1;
} else {
uc_mgr->conf_format = 2;
}
--
2.24.1
From 9980e18c3c99da42a90a98b140a0ffe7d0f92cd3 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Thu, 12 Dec 2019 18:42:33 +0100
Subject: [PATCH 18/69] alsa-lib: fix the array parser (unique compound keys)
The code from the old import may merge arrays wrongly and
the result is a compound with same keys like:
Input:
lines [
"SSP0.OUT, , BUF1.3"
]
lines [
"BUF2.0, , SSP0.IN"
]
Parsed contents:
lines {
0 'SSP0.OUT, , BUF1.3'
0 'BUF2.0, , SSP0.IN'
}
Proper parsed contents (create+merge mode):
lines {
0 'SSP0.OUT, , BUF1.3'
1 'BUF2.0, , SSP0.IN'
}
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/conf.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/conf.c b/src/conf.c
index e4306504..3e753b26 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -1226,7 +1226,7 @@ static int parse_value(snd_config_t **_n, snd_config_t *parent, input_t *input,
static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override);
static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override);
-static int parse_array_def(snd_config_t *parent, input_t *input, int idx, int skip, int override)
+static int parse_array_def(snd_config_t *parent, input_t *input, int *idx, int skip, int override)
{
char *id = NULL;
int c;
@@ -1234,8 +1234,21 @@ static int parse_array_def(snd_config_t *parent, input_t *input, int idx, int sk
snd_config_t *n = NULL;
if (!skip) {
+ snd_config_t *g;
char static_id[12];
- snprintf(static_id, sizeof(static_id), "%i", idx);
+ while (1) {
+ snprintf(static_id, sizeof(static_id), "%i", *idx);
+ if (_snd_config_search(parent, static_id, -1, &g) == 0) {
+ if (override) {
+ snd_config_delete(n);
+ } else {
+ /* merge */
+ (*idx)++;
+ continue;
+ }
+ }
+ break;
+ }
id = strdup(static_id);
if (id == NULL)
return -ENOMEM;
@@ -1306,9 +1319,10 @@ static int parse_array_defs(snd_config_t *parent, input_t *input, int skip, int
unget_char(c, input);
if (c == ']')
return 0;
- err = parse_array_def(parent, input, idx++, skip, override);
+ err = parse_array_def(parent, input, &idx, skip, override);
if (err < 0)
return err;
+ idx++;
}
return 0;
}
--
2.24.1
From 075ee165e647a6b434f63ca578f2f8faff2a55f6 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 16:09:35 +0100
Subject: [PATCH 19/69] topology: remove vendor_fd/name from snd_tplg structure
- not used
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/tplg_local.h | 5 -----
1 file changed, 5 deletions(-)
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index c32267d2..22648fa5 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -60,11 +60,6 @@ typedef enum _snd_pcm_rates {
} snd_pcm_rates_t;
struct snd_tplg {
-
- /* opaque vendor data */
- int vendor_fd;
- char *vendor_name;
-
/* out file */
int out_fd;
--
2.24.1
From ce74829db630a49569c79aea4aeb288fdd458dd8 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 17:01:03 +0100
Subject: [PATCH 20/69] topology: file position and size cleanups
- try to use size_t/ssize_t
- track the position in own variable, do not use lseek
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 121 ++++++++++++++++++--------------------
src/topology/tplg_local.h | 3 +-
2 files changed, 60 insertions(+), 64 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index 5ae3ae89..4e6cbbb0 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -23,28 +23,41 @@
/* verbose output detailing each object size and file position */
static void verbose(snd_tplg_t *tplg, const char *fmt, ...)
{
- int offset;
va_list va;
if (!tplg->verbose)
return;
- offset = lseek(tplg->out_fd, 0, SEEK_CUR);
-
va_start(va, fmt);
- fprintf(stdout, "0x%6.6x/%6.6d -", offset, offset);
+ fprintf(stdout, "0x%6.6zx/%6.6zd -", tplg->out_pos, tplg->out_pos);
vfprintf(stdout, fmt, va);
va_end(va);
}
+/* write a block, track the position */
+static ssize_t twrite(snd_tplg_t *tplg, void *data, size_t data_size)
+{
+ ssize_t r = write(tplg->out_fd, data, data_size);
+ if (r != (ssize_t)data_size) {
+ if (r < 0) {
+ SNDERR("error: unable to write: %s", strerror(errno));
+ return -errno;
+ }
+ tplg->out_pos += r;
+ SNDERR("error: unable to write (partial)");
+ return -EIO;
+ }
+ tplg->out_pos += r;
+ return r;
+}
+
/* write out block header to output file */
-static int write_block_header(snd_tplg_t *tplg, unsigned int type,
- unsigned int vendor_type, unsigned int version, unsigned int index,
- size_t payload_size, int count)
+static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type,
+ unsigned int vendor_type,
+ unsigned int version, unsigned int index,
+ size_t payload_size, int count)
{
struct snd_soc_tplg_hdr hdr;
- size_t bytes;
- int offset = lseek(tplg->out_fd, 0, SEEK_CUR);
memset(&hdr, 0, sizeof(hdr));
hdr.magic = SND_SOC_TPLG_MAGIC;
@@ -58,13 +71,13 @@ static int write_block_header(snd_tplg_t *tplg, unsigned int type,
hdr.count = count;
/* make sure file offset is aligned with the calculated HDR offset */
- if ((unsigned int)offset != tplg->next_hdr_pos) {
- SNDERR("error: New header is at offset 0x%x but file"
- " offset 0x%x is %s by %d bytes\n",
- tplg->next_hdr_pos, offset,
- (unsigned int)offset > tplg->next_hdr_pos ? "ahead" : "behind",
- abs(offset - tplg->next_hdr_pos));
- exit(-EINVAL);
+ if (tplg->out_pos != tplg->next_hdr_pos) {
+ SNDERR("error: New header is at offset 0x%zx but file"
+ " offset 0x%zx is %s by %ld bytes\n",
+ tplg->next_hdr_pos, tplg->out_pos,
+ tplg->out_pos > tplg->next_hdr_pos ? "ahead" : "behind",
+ labs(tplg->out_pos - tplg->next_hdr_pos));
+ return -EINVAL;
}
verbose(tplg, " header index %d type %d count %d size 0x%lx/%ld vendor %d "
@@ -74,22 +87,16 @@ static int write_block_header(snd_tplg_t *tplg, unsigned int type,
tplg->next_hdr_pos += hdr.payload_size + sizeof(hdr);
- bytes = write(tplg->out_fd, &hdr, sizeof(hdr));
- if (bytes != sizeof(hdr)) {
- SNDERR("error: can't write section header %lu\n",
- (long unsigned int)bytes);
- return bytes;
- }
-
- return bytes;
+ return twrite(tplg, &hdr, sizeof(hdr));
}
static int write_elem_block(snd_tplg_t *tplg,
- struct list_head *base, int size, int tplg_type, const char *obj_name)
+ struct list_head *base, size_t size, int tplg_type, const char *obj_name)
{
struct list_head *pos, *sub_pos, *sub_base;
struct tplg_elem *elem, *elem_next;
- int ret, wsize = 0, total_size = 0, count = 0, block_size = 0;
+ size_t total_size = 0, count = 0, block_size = 0;
+ ssize_t ret, wsize;
sub_base = base;
list_for_each(pos, base) {
@@ -129,12 +136,9 @@ static int write_elem_block(snd_tplg_t *tplg,
elem->route->control,
elem->route->sink, elem->size);
- wsize = write(tplg->out_fd, elem->obj, elem->size);
- if (wsize < 0) {
- SNDERR("error: failed to write %s %d\n",
- obj_name, ret);
- return ret;
- }
+ wsize = twrite(tplg, elem->obj, elem->size);
+ if (wsize < 0)
+ return size;
total_size += wsize;
/* get to the end of sub list */
@@ -151,7 +155,7 @@ static int write_elem_block(snd_tplg_t *tplg,
/* make sure we have written the correct size */
if (total_size != size) {
- SNDERR("error: size mismatch. Expected %d wrote %d\n",
+ SNDERR("error: size mismatch. Expected %zu wrote %zu\n",
size, total_size);
return -EIO;
}
@@ -179,8 +183,7 @@ static int calc_block_size(struct list_head *base)
return size;
}
-static int write_block(snd_tplg_t *tplg, struct list_head *base,
- int type)
+static int write_block(snd_tplg_t *tplg, struct list_head *base, int type)
{
int size;
@@ -231,44 +234,36 @@ static int write_block(snd_tplg_t *tplg, struct list_head *base,
}
/* write the manifest including its private data */
-static int write_manifest_data(snd_tplg_t *tplg)
+static ssize_t write_manifest_data(snd_tplg_t *tplg)
{
- int ret;
+ ssize_t ret;
/* write the header for this block */
ret = write_block_header(tplg, SND_SOC_TPLG_TYPE_MANIFEST, 0,
tplg->version, 0,
sizeof(tplg->manifest) + tplg->manifest.priv.size, 1);
if (ret < 0) {
- SNDERR("error: failed to write manifest block %d\n", ret);
+ SNDERR("error: failed to write manifest block\n");
return ret;
}
verbose(tplg, "manifest : write %d bytes\n", sizeof(tplg->manifest));
- ret = write(tplg->out_fd, &tplg->manifest, sizeof(tplg->manifest));
- if (ret < 0) {
- SNDERR("error: failed to write manifest %d\n", ret);
- return ret;
+ ret = twrite(tplg, &tplg->manifest, sizeof(tplg->manifest));
+ if (ret >= 0) {
+ verbose(tplg, "manifest : write %d priv bytes\n", tplg->manifest.priv.size);
+ ret = twrite(tplg, tplg->manifest_pdata, tplg->manifest.priv.size);
}
-
- verbose(tplg, "manifest : write %d priv bytes\n", tplg->manifest.priv.size);
- ret = write(tplg->out_fd, tplg->manifest_pdata, tplg->manifest.priv.size);
- if (ret < 0) {
- SNDERR("error: failed to write manifest priv data %d\n", ret);
- return ret;
- }
-
- return 0;
+ return ret;
}
int tplg_write_data(snd_tplg_t *tplg)
{
- int ret;
+ ssize_t ret;
/* write manifest */
ret = write_manifest_data(tplg);
if (ret < 0) {
- SNDERR("failed to write manifest %d\n", ret);
+ SNDERR("failed to write manifest %zd\n", ret);
return ret;
}
@@ -276,7 +271,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->mixer_list,
SND_TPLG_TYPE_MIXER);
if (ret < 0) {
- SNDERR("failed to write control elems %d\n", ret);
+ SNDERR("failed to write control elems %zd\n", ret);
return ret;
}
@@ -284,7 +279,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->enum_list,
SND_TPLG_TYPE_ENUM);
if (ret < 0) {
- SNDERR("failed to write control elems %d\n", ret);
+ SNDERR("failed to write control elems %zd\n", ret);
return ret;
}
@@ -292,7 +287,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->bytes_ext_list,
SND_TPLG_TYPE_BYTES);
if (ret < 0) {
- SNDERR("failed to write control elems %d\n", ret);
+ SNDERR("failed to write control elems %zd\n", ret);
return ret;
}
@@ -300,7 +295,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->widget_list,
SND_TPLG_TYPE_DAPM_WIDGET);
if (ret < 0) {
- SNDERR("failed to write widget elems %d\n", ret);
+ SNDERR("failed to write widget elems %zd\n", ret);
return ret;
}
@@ -308,7 +303,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->pcm_list,
SND_TPLG_TYPE_PCM);
if (ret < 0) {
- SNDERR("failed to write pcm elems %d\n", ret);
+ SNDERR("failed to write pcm elems %zd\n", ret);
return ret;
}
@@ -316,7 +311,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->dai_list,
SND_TPLG_TYPE_DAI);
if (ret < 0) {
- SNDERR("failed to write physical dai elems %d\n", ret);
+ SNDERR("failed to write physical dai elems %zd\n", ret);
return ret;
}
@@ -324,7 +319,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->be_list,
SND_TPLG_TYPE_BE);
if (ret < 0) {
- SNDERR("failed to write be elems %d\n", ret);
+ SNDERR("failed to write be elems %zd\n", ret);
return ret;
}
@@ -332,7 +327,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->cc_list,
SND_TPLG_TYPE_CC);
if (ret < 0) {
- SNDERR("failed to write cc elems %d\n", ret);
+ SNDERR("failed to write cc elems %zd\n", ret);
return ret;
}
@@ -340,7 +335,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->route_list,
SND_TPLG_TYPE_DAPM_GRAPH);
if (ret < 0) {
- SNDERR("failed to write graph elems %d\n", ret);
+ SNDERR("failed to write graph elems %zd\n", ret);
return ret;
}
@@ -348,7 +343,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_block(tplg, &tplg->pdata_list,
SND_TPLG_TYPE_DATA);
if (ret < 0) {
- SNDERR("failed to write private data %d\n", ret);
+ SNDERR("failed to write private data %zd\n", ret);
return ret;
}
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 22648fa5..7b8abcde 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -62,12 +62,13 @@ typedef enum _snd_pcm_rates {
struct snd_tplg {
/* out file */
int out_fd;
+ size_t out_pos;
int verbose;
unsigned int version;
/* runtime state */
- unsigned int next_hdr_pos;
+ size_t next_hdr_pos;
int index;
int channel_idx;
--
2.24.1
From 012bd3b28c0d2744db482caca630d5b0a19e4dab Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 18:24:55 +0100
Subject: [PATCH 21/69] topology: use an array describing blocks for the main
build loop
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 146 +++++++++++++++++++----------------------
1 file changed, 67 insertions(+), 79 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index 4e6cbbb0..ec1af42d 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -258,93 +258,81 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg)
int tplg_write_data(snd_tplg_t *tplg)
{
+ struct wtable {
+ const char *name;
+ struct list_head *list;
+ int type;
+ } *wptr, wtable[] = {
+ {
+ .name = "control mixer elements",
+ .list = &tplg->mixer_list,
+ .type = SND_TPLG_TYPE_MIXER,
+ },
+ {
+ .name = "control enum elements",
+ .list = &tplg->enum_list,
+ .type = SND_TPLG_TYPE_ENUM,
+ },
+ {
+ .name = "control extended (bytes) elements",
+ .list = &tplg->bytes_ext_list,
+ .type = SND_TPLG_TYPE_BYTES,
+ },
+ {
+ .name = "dapm widget elements",
+ .list = &tplg->widget_list,
+ .type = SND_TPLG_TYPE_DAPM_WIDGET,
+ },
+ {
+ .name = "pcm elements",
+ .list = &tplg->pcm_list,
+ .type = SND_TPLG_TYPE_PCM,
+ },
+ {
+ .name = "physical dai elements",
+ .list = &tplg->dai_list,
+ .type = SND_TPLG_TYPE_DAI,
+ },
+ {
+ .name = "be elements",
+ .list = &tplg->be_list,
+ .type = SND_TPLG_TYPE_BE,
+ },
+ {
+ .name = "cc elements",
+ .list = &tplg->cc_list,
+ .type = SND_TPLG_TYPE_CC,
+ },
+ {
+ .name = "route (dapm graph) elements",
+ .list = &tplg->route_list,
+ .type = SND_TPLG_TYPE_DAPM_GRAPH,
+ },
+ {
+ .name = "private data elements",
+ .list = &tplg->pdata_list,
+ .type = SND_TPLG_TYPE_DATA,
+ },
+ };
+
ssize_t ret;
+ unsigned int index;
/* write manifest */
ret = write_manifest_data(tplg);
if (ret < 0) {
- SNDERR("failed to write manifest %zd\n", ret);
- return ret;
- }
-
- /* write mixer elems. */
- ret = write_block(tplg, &tplg->mixer_list,
- SND_TPLG_TYPE_MIXER);
- if (ret < 0) {
- SNDERR("failed to write control elems %zd\n", ret);
- return ret;
- }
-
- /* write enum control elems. */
- ret = write_block(tplg, &tplg->enum_list,
- SND_TPLG_TYPE_ENUM);
- if (ret < 0) {
- SNDERR("failed to write control elems %zd\n", ret);
- return ret;
- }
-
- /* write bytes extended control elems. */
- ret = write_block(tplg, &tplg->bytes_ext_list,
- SND_TPLG_TYPE_BYTES);
- if (ret < 0) {
- SNDERR("failed to write control elems %zd\n", ret);
- return ret;
- }
-
- /* write widget elems */
- ret = write_block(tplg, &tplg->widget_list,
- SND_TPLG_TYPE_DAPM_WIDGET);
- if (ret < 0) {
- SNDERR("failed to write widget elems %zd\n", ret);
- return ret;
- }
-
- /* write pcm elems */
- ret = write_block(tplg, &tplg->pcm_list,
- SND_TPLG_TYPE_PCM);
- if (ret < 0) {
- SNDERR("failed to write pcm elems %zd\n", ret);
- return ret;
- }
-
- /* write physical dai elems */
- ret = write_block(tplg, &tplg->dai_list,
- SND_TPLG_TYPE_DAI);
- if (ret < 0) {
- SNDERR("failed to write physical dai elems %zd\n", ret);
- return ret;
- }
-
- /* write be elems */
- ret = write_block(tplg, &tplg->be_list,
- SND_TPLG_TYPE_BE);
- if (ret < 0) {
- SNDERR("failed to write be elems %zd\n", ret);
- return ret;
- }
-
- /* write cc elems */
- ret = write_block(tplg, &tplg->cc_list,
- SND_TPLG_TYPE_CC);
- if (ret < 0) {
- SNDERR("failed to write cc elems %zd\n", ret);
- return ret;
- }
-
- /* write route elems */
- ret = write_block(tplg, &tplg->route_list,
- SND_TPLG_TYPE_DAPM_GRAPH);
- if (ret < 0) {
- SNDERR("failed to write graph elems %zd\n", ret);
+ SNDERR("failed to write manifest %d\n", ret);
return ret;
}
- /* write private data */
- ret = write_block(tplg, &tplg->pdata_list,
- SND_TPLG_TYPE_DATA);
- if (ret < 0) {
- SNDERR("failed to write private data %zd\n", ret);
- return ret;
+ /* write all blocks */
+ for (index = 0; index < ARRAY_SIZE(wtable); index++) {
+ wptr = &wtable[index];
+ ret = write_block(tplg, wptr->list, wptr->type);
+ if (ret < 0) {
+ SNDERR("failed to write %s: %s\n", wptr->name, snd_strerror(-ret));
+ return ret;
+ }
}
return 0;
--
2.24.1
From f1f5b48d0cfbce0cc6400daba0020d9385d6645e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 18:26:20 +0100
Subject: [PATCH 22/69] topology: use size_t for calc_block_size()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index ec1af42d..bbee71d6 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -163,11 +163,11 @@ static int write_elem_block(snd_tplg_t *tplg,
return 0;
}
-static int calc_block_size(struct list_head *base)
+static size_t calc_block_size(struct list_head *base)
{
struct list_head *pos;
struct tplg_elem *elem;
- int size = 0;
+ size_t size = 0;
list_for_each(pos, base) {
@@ -185,14 +185,14 @@ static int calc_block_size(struct list_head *base)
static int write_block(snd_tplg_t *tplg, struct list_head *base, int type)
{
- int size;
+ size_t size;
/* calculate the block size in bytes for all elems in this list */
size = calc_block_size(base);
- if (size <= 0)
+ if (size == 0)
return size;
- verbose(tplg, " block size for type %d is %d\n", type, size);
+ verbose(tplg, " block size for type %d is %zd\n", type, size);
/* write each elem for this block */
switch (type) {
--
2.24.1
From 4dcceb5f866deda09e971b1c31d46403c3bd8e9e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 18:49:29 +0100
Subject: [PATCH 23/69] topology: merge write_block to tplg_write_data
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 95 +++++++++++++++---------------------------
1 file changed, 33 insertions(+), 62 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index bbee71d6..f530fcd8 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -183,56 +183,6 @@ static size_t calc_block_size(struct list_head *base)
return size;
}
-static int write_block(snd_tplg_t *tplg, struct list_head *base, int type)
-{
- size_t size;
-
- /* calculate the block size in bytes for all elems in this list */
- size = calc_block_size(base);
- if (size == 0)
- return size;
-
- verbose(tplg, " block size for type %d is %zd\n", type, size);
-
- /* write each elem for this block */
- switch (type) {
- case SND_TPLG_TYPE_MIXER:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_MIXER, "mixer");
- case SND_TPLG_TYPE_BYTES:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_BYTES, "bytes");
- case SND_TPLG_TYPE_ENUM:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_ENUM, "enum");
- case SND_TPLG_TYPE_DAPM_GRAPH:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_DAPM_GRAPH, "route");
- case SND_TPLG_TYPE_DAPM_WIDGET:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_DAPM_WIDGET, "widget");
- case SND_TPLG_TYPE_PCM:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_PCM, "pcm");
- case SND_TPLG_TYPE_BE:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_BACKEND_LINK, "be");
- case SND_TPLG_TYPE_CC:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_CODEC_LINK, "cc");
- case SND_TPLG_TYPE_DATA:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_PDATA, "data");
- case SND_TPLG_TYPE_DAI:
- return write_elem_block(tplg, base, size,
- SND_SOC_TPLG_TYPE_DAI, "dai");
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
/* write the manifest including its private data */
static ssize_t write_manifest_data(snd_tplg_t *tplg)
{
@@ -262,60 +212,72 @@ int tplg_write_data(snd_tplg_t *tplg)
const char *name;
struct list_head *list;
int type;
+ int tsoc;
} *wptr, wtable[] = {
{
- .name = "control mixer elements",
+ .name = "control mixer",
.list = &tplg->mixer_list,
.type = SND_TPLG_TYPE_MIXER,
+ .tsoc = SND_SOC_TPLG_TYPE_MIXER,
},
{
- .name = "control enum elements",
+ .name = "control enum",
.list = &tplg->enum_list,
.type = SND_TPLG_TYPE_ENUM,
+ .tsoc = SND_SOC_TPLG_TYPE_ENUM,
},
{
- .name = "control extended (bytes) elements",
+ .name = "control extended (bytes)",
.list = &tplg->bytes_ext_list,
.type = SND_TPLG_TYPE_BYTES,
+ .tsoc = SND_SOC_TPLG_TYPE_BYTES,
},
{
- .name = "dapm widget elements",
+ .name = "dapm widget",
.list = &tplg->widget_list,
.type = SND_TPLG_TYPE_DAPM_WIDGET,
+ .tsoc = SND_SOC_TPLG_TYPE_DAPM_WIDGET,
},
{
- .name = "pcm elements",
+ .name = "pcm",
.list = &tplg->pcm_list,
.type = SND_TPLG_TYPE_PCM,
+ .tsoc = SND_SOC_TPLG_TYPE_PCM,
},
{
- .name = "physical dai elements",
+ .name = "physical dai",
.list = &tplg->dai_list,
.type = SND_TPLG_TYPE_DAI,
+ .tsoc = SND_SOC_TPLG_TYPE_DAI,
},
{
- .name = "be elements",
+ .name = "be",
.list = &tplg->be_list,
.type = SND_TPLG_TYPE_BE,
+ .tsoc = SND_SOC_TPLG_TYPE_BACKEND_LINK,
},
{
- .name = "cc elements",
+ .name = "cc",
.list = &tplg->cc_list,
.type = SND_TPLG_TYPE_CC,
+ .tsoc = SND_SOC_TPLG_TYPE_CODEC_LINK,
},
{
- .name = "route (dapm graph) elements",
+ .name = "route (dapm graph)",
.list = &tplg->route_list,
.type = SND_TPLG_TYPE_DAPM_GRAPH,
+ .tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH,
},
{
- .name = "private data elements",
+ .name = "private data",
.list = &tplg->pdata_list,
.type = SND_TPLG_TYPE_DATA,
+ .tsoc = SND_SOC_TPLG_TYPE_PDATA,
},
};
ssize_t ret;
+ size_t size;
unsigned int index;
/* write manifest */
@@ -328,9 +290,18 @@ int tplg_write_data(snd_tplg_t *tplg)
/* write all blocks */
for (index = 0; index < ARRAY_SIZE(wtable); index++) {
wptr = &wtable[index];
- ret = write_block(tplg, wptr->list, wptr->type);
+ /* calculate the block size in bytes for all elems in this list */
+ size = calc_block_size(wptr->list);
+ if (size == 0)
+ continue;
+ verbose(tplg, " block size for type %s (%d:%d) is %zd\n",
+ wptr->name, wptr->type,
+ wptr->tsoc, size);
+ ret = write_elem_block(tplg, wptr->list, size,
+ wptr->tsoc, wptr->name);
if (ret < 0) {
- SNDERR("failed to write %s: %s\n", wptr->name, snd_strerror(-ret));
+ SNDERR("failed to write %s elements: %s\n",
+ wptr->name, snd_strerror(-ret));
return ret;
}
}
--
2.24.1
From c9e9ee3c40e9f50889f2bb4065c4556184998e8f Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 18:53:41 +0100
Subject: [PATCH 24/69] topology: make vebose output more nice
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index f530fcd8..1a22a453 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -29,7 +29,7 @@ static void verbose(snd_tplg_t *tplg, const char *fmt, ...)
return;
va_start(va, fmt);
- fprintf(stdout, "0x%6.6zx/%6.6zd -", tplg->out_pos, tplg->out_pos);
+ fprintf(stdout, "0x%6.6zx/%6.6zd - ", tplg->out_pos, tplg->out_pos);
vfprintf(stdout, fmt, va);
va_end(va);
}
@@ -80,7 +80,7 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type,
return -EINVAL;
}
- verbose(tplg, " header index %d type %d count %d size 0x%lx/%ld vendor %d "
+ verbose(tplg, "header index %d type %d count %d size 0x%lx/%ld vendor %d "
"version %d\n", index, type, count,
(long unsigned int)payload_size, (long int)payload_size,
vendor_type, version);
@@ -128,10 +128,10 @@ static int write_elem_block(snd_tplg_t *tplg,
continue;
if (elem->type != SND_TPLG_TYPE_DAPM_GRAPH)
- verbose(tplg, " %s '%s': write %d bytes\n",
+ verbose(tplg, "%s '%s': write %d bytes\n",
obj_name, elem->id, elem->size);
else
- verbose(tplg, " %s '%s -> %s -> %s': write %d bytes\n",
+ verbose(tplg, "%s '%s -> %s -> %s': write %d bytes\n",
obj_name, elem->route->source,
elem->route->control,
elem->route->sink, elem->size);
@@ -197,10 +197,10 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg)
return ret;
}
- verbose(tplg, "manifest : write %d bytes\n", sizeof(tplg->manifest));
+ verbose(tplg, "manifest: write %d bytes\n", sizeof(tplg->manifest));
ret = twrite(tplg, &tplg->manifest, sizeof(tplg->manifest));
if (ret >= 0) {
- verbose(tplg, "manifest : write %d priv bytes\n", tplg->manifest.priv.size);
+ verbose(tplg, "manifest: write %d priv bytes\n", tplg->manifest.priv.size);
ret = twrite(tplg, tplg->manifest_pdata, tplg->manifest.priv.size);
}
return ret;
@@ -294,9 +294,9 @@ int tplg_write_data(snd_tplg_t *tplg)
size = calc_block_size(wptr->list);
if (size == 0)
continue;
- verbose(tplg, " block size for type %s (%d:%d) is %zd\n",
+ verbose(tplg, "block size for type %s (%d:%d) is 0x%zx/%zd\n",
wptr->name, wptr->type,
- wptr->tsoc, size);
+ wptr->tsoc, size, size);
ret = write_elem_block(tplg, wptr->list, size,
wptr->tsoc, wptr->name);
if (ret < 0) {
@@ -306,5 +306,7 @@ int tplg_write_data(snd_tplg_t *tplg)
}
}
+ verbose(tplg, "total size is 0x%zx/%zd\n", tplg->out_pos, tplg->out_pos);
+
return 0;
}
--
2.24.1
From 3b9e39dab5ebfb525b4437a644fe54569e419874 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 21:23:52 +0100
Subject: [PATCH 25/69] topology: use list_insert() macro in tplg_elem_insert()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/elem.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/topology/elem.c b/src/topology/elem.c
index a9d1d854..2066fad8 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -131,7 +131,7 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
return NULL;
}
-/* insert a new element into list in the ascending order of index value*/
+/* insert a new element into list in the ascending order of index value */
static void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
{
struct list_head *pos, *p = &(elem_p->list);
@@ -142,10 +142,8 @@ static void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
if (elem_p->index < elem->index)
break;
}
- p->prev = pos->prev;
- pos->prev->next = p;
- pos->prev = p;
- p->next = pos;
+ /* insert item before pos */
+ list_insert(p, pos->prev, pos);
}
/* create a new common element and object */
--
2.24.1
From 0d6949b7f1f99bf3fcd5cce78483c10f9ca35264 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 21:52:13 +0100
Subject: [PATCH 26/69] topology: dapm - coding fixes
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/dapm.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index 97c9695b..cd80a4c0 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -152,8 +152,7 @@ static int copy_dapm_control(struct tplg_elem *elem, struct tplg_elem *ref)
}
/* check referenced controls for a widget */
-static int tplg_build_widget(snd_tplg_t *tplg,
- struct tplg_elem *elem)
+static int tplg_build_widget(snd_tplg_t *tplg, struct tplg_elem *elem)
{
struct tplg_ref *ref;
struct list_head *base, *pos;
@@ -164,7 +163,7 @@ static int tplg_build_widget(snd_tplg_t *tplg,
/* A widget's private data sits before the embedded controls.
* So merge the private data blocks at first
*/
- list_for_each(pos, base) {
+ list_for_each(pos, base) {
ref = list_entry(pos, struct tplg_ref, list);
if (ref->type != SND_TPLG_TYPE_DATA)
@@ -314,7 +313,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
return 0;
}
-struct tplg_elem* tplg_elem_new_route(snd_tplg_t *tplg)
+struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg)
{
struct tplg_elem *elem;
struct snd_soc_tplg_dapm_graph_elem *line;
@@ -342,7 +341,7 @@ struct tplg_elem* tplg_elem_new_route(snd_tplg_t *tplg)
/* line is defined as '"source, control, sink"' */
static int tplg_parse_line(const char *text,
- struct snd_soc_tplg_dapm_graph_elem *line)
+ struct snd_soc_tplg_dapm_graph_elem *line)
{
char buf[LINE_SIZE];
unsigned int len, i;
@@ -422,7 +421,7 @@ static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t *cfg, int index)
}
int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED)
+ void *private ATTRIBUTE_UNUSED)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -472,7 +471,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
/* DAPM Widget */
int tplg_parse_dapm_widget(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+ snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_dapm_widget *widget;
struct tplg_elem *elem;
@@ -645,7 +644,7 @@ int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t)
snd_strlcpy(line->source, t->src, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
if (t->ctl)
snd_strlcpy(line->control, t->ctl,
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
snd_strlcpy(line->sink, t->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
return 0;
--
2.24.1
From 2b50b594dcbf69f8dcc6e8cf673748f7063c3c17 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 21:56:58 +0100
Subject: [PATCH 27/69] topology: dapm - merge identical index blocks like for
other elems
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/dapm.c | 14 +++++++-------
src/topology/elem.c | 2 +-
src/topology/tplg_local.h | 1 +
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index cd80a4c0..ce469131 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -313,7 +313,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
return 0;
}
-struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg)
+struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg, int index)
{
struct tplg_elem *elem;
struct snd_soc_tplg_dapm_graph_elem *line;
@@ -322,7 +322,8 @@ struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg)
if (!elem)
return NULL;
- list_add_tail(&elem->list, &tplg->route_list);
+ elem->index = index;
+ tplg_elem_insert(elem, &tplg->route_list);
strcpy(elem->id, "line");
elem->type = SND_TPLG_TYPE_DAPM_GRAPH;
elem->size = sizeof(*line);
@@ -403,10 +404,9 @@ static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t *cfg, int index)
if (snd_config_get_string(n, &val) < 0)
continue;
- elem = tplg_elem_new_route(tplg);
+ elem = tplg_elem_new_route(tplg, index);
if (!elem)
return -ENOMEM;
- elem->index = index;
line = elem->route;
err = tplg_parse_line(val, line);
@@ -628,7 +628,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
return 0;
}
-int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t)
+int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t, int index)
{
struct tplg_elem *elem;
struct snd_soc_tplg_dapm_graph_elem *line;
@@ -636,7 +636,7 @@ int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t)
if (!t->src || !t->sink)
return -EINVAL;
- elem = tplg_elem_new_route(tplg);
+ elem = tplg_elem_new_route(tplg, index);
if (!elem)
return -ENOMEM;
@@ -656,7 +656,7 @@ int tplg_add_graph_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
int i, ret;
for (i = 0; i < gt->count; i++) {
- ret = tplg_add_route(tplg, gt->elem + i);
+ ret = tplg_add_route(tplg, gt->elem + i, t->index);
if (ret < 0)
return ret;
}
diff --git a/src/topology/elem.c b/src/topology/elem.c
index 2066fad8..140cdd32 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -132,7 +132,7 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
}
/* insert a new element into list in the ascending order of index value */
-static void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
+void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
{
struct list_head *pos, *p = &(elem_p->list);
struct tplg_elem *elem;
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 7b8abcde..11efce6d 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -273,6 +273,7 @@ int tplg_ref_add_elem(struct tplg_elem *elem, struct tplg_elem *elem_ref);
struct tplg_elem *tplg_elem_new(void);
void tplg_elem_free(struct tplg_elem *elem);
void tplg_elem_free_list(struct list_head *base);
+void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list);
struct tplg_elem *tplg_elem_lookup(struct list_head *base,
const char* id,
unsigned int type,
--
2.24.1
From 780f17126aa8d54fc09694cbf652d4135eb731c0 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 13 Dec 2019 22:07:46 +0100
Subject: [PATCH 28/69] topology: more coding fixes
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/channel.c | 4 ++--
src/topology/ctl.c | 15 ++++++++-------
src/topology/elem.c | 6 ++++--
src/topology/ops.c | 6 +++---
src/topology/pcm.c | 20 ++++++++++++--------
src/topology/text.c | 2 +-
6 files changed, 30 insertions(+), 23 deletions(-)
diff --git a/src/topology/channel.c b/src/topology/channel.c
index 8516b23f..60f7e219 100644
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -74,8 +74,8 @@ static int lookup_channel(const char *c)
}
/* Parse a channel mapping. */
-int tplg_parse_channel(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private)
+int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
+ void *private)
{
snd_config_iterator_t i, next;
snd_config_t *n;
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index a0962522..1db0b16e 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -46,7 +46,7 @@ static const struct ctl_access_elem ctl_access[] = {
/* find CTL access strings and conver to values */
static int parse_access_values(snd_config_t *cfg,
- struct snd_soc_tplg_ctl_hdr *hdr)
+ struct snd_soc_tplg_ctl_hdr *hdr)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -77,7 +77,7 @@ static int parse_access_values(snd_config_t *cfg,
/* Parse Access */
int parse_access(snd_config_t *cfg,
- struct snd_soc_tplg_ctl_hdr *hdr)
+ struct snd_soc_tplg_ctl_hdr *hdr)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -118,7 +118,7 @@ static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
/* check referenced TLV for a mixer control */
static int tplg_build_mixer_control(snd_tplg_t *tplg,
- struct tplg_elem *elem)
+ struct tplg_elem *elem)
{
struct tplg_ref *ref;
struct list_head *base, *pos;
@@ -157,7 +157,7 @@ static int tplg_build_mixer_control(snd_tplg_t *tplg,
}
static void copy_enum_texts(struct tplg_elem *enum_elem,
- struct tplg_elem *ref_elem)
+ struct tplg_elem *ref_elem)
{
struct snd_soc_tplg_enum_control *ec = enum_elem->enum_ctrl;
struct tplg_texts *texts = ref_elem->texts;
@@ -169,7 +169,7 @@ static void copy_enum_texts(struct tplg_elem *enum_elem,
/* check referenced text for a enum control */
static int tplg_build_enum_control(snd_tplg_t *tplg,
- struct tplg_elem *elem)
+ struct tplg_elem *elem)
{
struct tplg_ref *ref;
struct list_head *base, *pos;
@@ -331,7 +331,7 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
/* Parse TLV */
int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED)
+ void *private ATTRIBUTE_UNUSED)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -364,7 +364,8 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
/* Parse Control Bytes */
int tplg_parse_control_bytes(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+ snd_config_t *cfg,
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_bytes_control *be;
struct tplg_elem *elem;
diff --git a/src/topology/elem.c b/src/topology/elem.c
index 140cdd32..d8618cc9 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -107,7 +107,7 @@ void tplg_elem_free_list(struct list_head *base)
}
struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
- unsigned int type, int index)
+ unsigned int type, int index)
{
struct list_head *pos;
struct tplg_elem *elem;
@@ -148,7 +148,9 @@ void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
/* create a new common element and object */
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
- snd_config_t *cfg, const char *name, enum snd_tplg_type type)
+ snd_config_t *cfg,
+ const char *name,
+ enum snd_tplg_type type)
{
struct tplg_elem *elem;
const char *id, *val = NULL;
diff --git a/src/topology/ops.c b/src/topology/ops.c
index 6f8dc1ff..0f4295a2 100644
--- a/src/topology/ops.c
+++ b/src/topology/ops.c
@@ -48,8 +48,8 @@ static int lookup_ops(const char *c)
/* Parse Control operations. Ops can come from standard names above or
* bespoke driver controls with numbers >= 256
*/
-int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
- snd_config_t *cfg, void *private)
+int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
+ void *private)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -88,7 +88,7 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
* bespoke driver controls with numbers >= 256
*/
int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
- snd_config_t *cfg, void *private)
+ snd_config_t *cfg, void *private)
{
snd_config_iterator_t i, next;
snd_config_t *n;
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 553fd822..98a8df97 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -63,7 +63,8 @@ struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base, const char* id)
/* copy referenced caps to the parent (pcm or be dai) */
static void copy_stream_caps(const char *id ATTRIBUTE_UNUSED,
- struct snd_soc_tplg_stream_caps *caps, struct tplg_elem *ref_elem)
+ struct snd_soc_tplg_stream_caps *caps,
+ struct tplg_elem *ref_elem)
{
struct snd_soc_tplg_stream_caps *ref_caps = ref_elem->stream_caps;
@@ -75,7 +76,8 @@ static void copy_stream_caps(const char *id ATTRIBUTE_UNUSED,
/* find and copy the referenced stream caps */
static int tplg_build_stream_caps(snd_tplg_t *tplg,
- const char *id, int index, struct snd_soc_tplg_stream_caps *caps)
+ const char *id, int index,
+ struct snd_soc_tplg_stream_caps *caps)
{
struct tplg_elem *ref_elem = NULL;
unsigned int i;
@@ -207,7 +209,8 @@ int tplg_build_dais(snd_tplg_t *tplg, unsigned int type)
}
static int tplg_build_stream_cfg(snd_tplg_t *tplg,
- struct snd_soc_tplg_stream *stream, int num_streams, int index)
+ struct snd_soc_tplg_stream *stream,
+ int num_streams, int index)
{
struct snd_soc_tplg_stream *strm;
struct tplg_elem *ref_elem;
@@ -367,7 +370,8 @@ static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str)
/* Parse pcm stream capabilities */
int tplg_parse_stream_caps(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+ snd_config_t *cfg,
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_stream_caps *sc;
struct tplg_elem *elem;
@@ -637,8 +641,8 @@ static int parse_flag(snd_config_t *n, unsigned int mask_in,
}
/* Parse PCM (for front end DAI & DAI link) in text conf file */
-int tplg_parse_pcm(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_pcm *pcm;
struct tplg_elem *elem;
@@ -746,8 +750,8 @@ int tplg_parse_pcm(snd_tplg_t *tplg,
}
/* Parse physical DAI */
-int tplg_parse_dai(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_dai *dai;
struct tplg_elem *elem;
diff --git a/src/topology/text.c b/src/topology/text.c
index 72647fe0..f301a4de 100644
--- a/src/topology/text.c
+++ b/src/topology/text.c
@@ -59,7 +59,7 @@ static int parse_text_values(snd_config_t *cfg, struct tplg_elem *elem)
/* Parse Text data */
int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED)
+ void *private ATTRIBUTE_UNUSED)
{
snd_config_iterator_t i, next;
snd_config_t *n;
--
2.24.1
From ae564665ec261cf104de499b1cdda3564070fc65 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 20 Dec 2019 15:46:48 +0100
Subject: [PATCH 29/69] Fix alsa/sound/*.h for external programs
The recent update of sound/*.h to sync with the latest Linus uapi
files broke the build of alsa-tools programs. These files used to be
a modified version of Linux sound/* header files, so that they could
be built without Linux headers. The special prefix like __user and
other things were worked around there.
We may do that again, but a better approach is to fix those things in
Linux kernel uapi side, while we keep the minimal workaround in
alsa-lib such as the __u16 and co type definitions.
This patch is such an attempt, namely:
- Keep the original $LINUX/uapi/sound/*.h in include/sound/uapi
directory
- The "fixes" are applied to some uapi headers, so that they don't
contain Linux-specific prefix and use of opaque struct like
snd_ctl_elem_id
- The uapi headers are included indirectly from include/sound/*.h
- Some headers have inclusion of type_compat.h for the Linux variable
types and prefixes
- type_compat.h tries to use <linux/types.h> when __linux__ is
defined, instead of the own conflicting definitions
The last type might need a bit more adjustment depending on the
compiler, but it can be fixed locally without disturbing else.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
configure.ac | 3 +-
include/sound/Makefile.am | 6 +-
include/sound/asequencer.h | 613 +----------------
include/sound/asoc.h | 634 +-----------------
include/sound/asound.h | 1039 +----------------------------
include/sound/asound_fm.h | 136 +---
include/sound/emu10k1.h | 383 +----------
include/sound/hdsp.h | 113 +---
include/sound/hdspm.h | 234 +------
include/sound/sb16_csp.h | 124 +---
include/sound/sscape_ioctl.h | 22 +-
include/sound/tlv.h | 118 +---
include/sound/type_compat.h | 13 +
include/sound/uapi/Makefile.am | 6 +
include/sound/uapi/asequencer.h | 612 +++++++++++++++++
include/sound/uapi/asoc.h | 633 ++++++++++++++++++
include/sound/uapi/asound.h | 1038 ++++++++++++++++++++++++++++
include/sound/uapi/asound_fm.h | 135 ++++
include/sound/uapi/emu10k1.h | 395 +++++++++++
include/sound/uapi/hdsp.h | 109 +++
include/sound/uapi/hdspm.h | 230 +++++++
include/sound/uapi/sb16_csp.h | 123 ++++
include/sound/uapi/sscape_ioctl.h | 21 +
include/sound/uapi/tlv.h | 117 ++++
src/topology/tplg_local.h | 3 +-
25 files changed, 3452 insertions(+), 3408 deletions(-)
create mode 100644 include/sound/uapi/Makefile.am
create mode 100644 include/sound/uapi/asequencer.h
create mode 100644 include/sound/uapi/asoc.h
create mode 100644 include/sound/uapi/asound.h
create mode 100644 include/sound/uapi/asound_fm.h
create mode 100644 include/sound/uapi/emu10k1.h
create mode 100644 include/sound/uapi/hdsp.h
create mode 100644 include/sound/uapi/hdspm.h
create mode 100644 include/sound/uapi/sb16_csp.h
create mode 100644 include/sound/uapi/sscape_ioctl.h
create mode 100644 include/sound/uapi/tlv.h
diff --git a/configure.ac b/configure.ac
index 119ef600..886f87bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -707,7 +707,8 @@ if test ! -L "$srcdir"/include/alsa ; then
fi
AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \
- include/Makefile include/sound/Makefile src/Versions src/Makefile \
+ include/Makefile include/sound/Makefile include/sound/uapi/Makefile \
+ src/Versions src/Makefile \
src/control/Makefile src/mixer/Makefile \
src/pcm/Makefile src/pcm/scopes/Makefile \
src/rawmidi/Makefile src/timer/Makefile \
diff --git a/include/sound/Makefile.am b/include/sound/Makefile.am
index 99c42211..ccc7d273 100644
--- a/include/sound/Makefile.am
+++ b/include/sound/Makefile.am
@@ -1,7 +1,9 @@
+SUBDIRS = uapi
+
alsasoundincludedir = ${includedir}/alsa/sound
alsasoundinclude_HEADERS = asound_fm.h hdsp.h hdspm.h sb16_csp.h \
- sscape_ioctl.h emu10k1.h type_compat.h \
- asoc.h tlv.h
+ sscape_ioctl.h emu10k1.h asoc.h tlv.h \
+ type_compat.h
noinst_HEADERS = asound.h asequencer.h
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h
index a75e14ed..e539a77e 100644
--- a/include/sound/asequencer.h
+++ b/include/sound/asequencer.h
@@ -1,612 +1 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/*
- * Main header file for the ALSA sequencer
- * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
- * (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef _UAPI__SOUND_ASEQUENCER_H
-#define _UAPI__SOUND_ASEQUENCER_H
-
-#include <sound/asound.h>
-
-/** version of the sequencer */
-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 2)
-
-/**
- * definition of sequencer event types
- */
-
-/** system messages
- * event data type = #snd_seq_result
- */
-#define SNDRV_SEQ_EVENT_SYSTEM 0
-#define SNDRV_SEQ_EVENT_RESULT 1
-
-/** note messages (channel specific)
- * event data type = #snd_seq_ev_note
- */
-#define SNDRV_SEQ_EVENT_NOTE 5
-#define SNDRV_SEQ_EVENT_NOTEON 6
-#define SNDRV_SEQ_EVENT_NOTEOFF 7
-#define SNDRV_SEQ_EVENT_KEYPRESS 8
-
-/** control messages (channel specific)
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_CONTROLLER 10
-#define SNDRV_SEQ_EVENT_PGMCHANGE 11
-#define SNDRV_SEQ_EVENT_CHANPRESS 12
-#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */
-#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */
-#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */
-#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */
-
-/** synchronisation messages
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */
-#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */
-#define SNDRV_SEQ_EVENT_QFRAME 22 /* midi time code quarter frame */
-#define SNDRV_SEQ_EVENT_TIMESIGN 23 /* SMF Time Signature event */
-#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */
-
-/** timer messages
- * event data type = snd_seq_ev_queue_control
- */
-#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */
-#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */
-#define SNDRV_SEQ_EVENT_STOP 32 /* midi Real Time Stop message */
-#define SNDRV_SEQ_EVENT_SETPOS_TICK 33 /* set tick queue position */
-#define SNDRV_SEQ_EVENT_SETPOS_TIME 34 /* set realtime queue position */
-#define SNDRV_SEQ_EVENT_TEMPO 35 /* (SMF) Tempo event */
-#define SNDRV_SEQ_EVENT_CLOCK 36 /* midi Real Time Clock message */
-#define SNDRV_SEQ_EVENT_TICK 37 /* midi Real Time Tick message */
-#define SNDRV_SEQ_EVENT_QUEUE_SKEW 38 /* skew queue tempo */
-
-/** others
- * event data type = none
- */
-#define SNDRV_SEQ_EVENT_TUNE_REQUEST 40 /* tune request */
-#define SNDRV_SEQ_EVENT_RESET 41 /* reset to power-on state */
-#define SNDRV_SEQ_EVENT_SENSING 42 /* "active sensing" event */
-
-/** echo back, kernel private messages
- * event data type = any type
- */
-#define SNDRV_SEQ_EVENT_ECHO 50 /* echo event */
-#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */
-
-/** system status messages (broadcast for subscribers)
- * event data type = snd_seq_addr
- */
-#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */
-#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */
-#define SNDRV_SEQ_EVENT_CLIENT_CHANGE 62 /* client status/info has changed */
-#define SNDRV_SEQ_EVENT_PORT_START 63 /* new port was created */
-#define SNDRV_SEQ_EVENT_PORT_EXIT 64 /* port was deleted from system */
-#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */
-
-/** port connection changes
- * event data type = snd_seq_connect
- */
-#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */
-#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */
-
-/* 70-89: synthesizer events - obsoleted */
-
-/** user-defined events with fixed length
- * event data type = any
- */
-#define SNDRV_SEQ_EVENT_USR0 90
-#define SNDRV_SEQ_EVENT_USR1 91
-#define SNDRV_SEQ_EVENT_USR2 92
-#define SNDRV_SEQ_EVENT_USR3 93
-#define SNDRV_SEQ_EVENT_USR4 94
-#define SNDRV_SEQ_EVENT_USR5 95
-#define SNDRV_SEQ_EVENT_USR6 96
-#define SNDRV_SEQ_EVENT_USR7 97
-#define SNDRV_SEQ_EVENT_USR8 98
-#define SNDRV_SEQ_EVENT_USR9 99
-
-/* 100-118: instrument layer - obsoleted */
-/* 119-129: reserved */
-
-/* 130-139: variable length events
- * event data type = snd_seq_ev_ext
- * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
- */
-#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */
-#define SNDRV_SEQ_EVENT_BOUNCE 131 /* error event */
-/* 132-134: reserved */
-#define SNDRV_SEQ_EVENT_USR_VAR0 135
-#define SNDRV_SEQ_EVENT_USR_VAR1 136
-#define SNDRV_SEQ_EVENT_USR_VAR2 137
-#define SNDRV_SEQ_EVENT_USR_VAR3 138
-#define SNDRV_SEQ_EVENT_USR_VAR4 139
-
-/* 150-151: kernel events with quote - DO NOT use in user clients */
-#define SNDRV_SEQ_EVENT_KERNEL_ERROR 150
-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE 151 /* obsolete */
-
-/* 152-191: reserved */
-
-/* 192-254: hardware specific events */
-
-/* 255: special event */
-#define SNDRV_SEQ_EVENT_NONE 255
-
-
-typedef unsigned char snd_seq_event_type_t;
-
-/** event address */
-struct snd_seq_addr {
- unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */
- unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */
-};
-
-/** port connection */
-struct snd_seq_connect {
- struct snd_seq_addr sender;
- struct snd_seq_addr dest;
-};
-
-
-#define SNDRV_SEQ_ADDRESS_UNKNOWN 253 /* unknown source */
-#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS 254 /* send event to all subscribed ports */
-#define SNDRV_SEQ_ADDRESS_BROADCAST 255 /* send event to all queues/clients/ports/channels */
-#define SNDRV_SEQ_QUEUE_DIRECT 253 /* direct dispatch */
-
- /* event mode flag - NOTE: only 8 bits available! */
-#define SNDRV_SEQ_TIME_STAMP_TICK (0<<0) /* timestamp in clock ticks */
-#define SNDRV_SEQ_TIME_STAMP_REAL (1<<0) /* timestamp in real time */
-#define SNDRV_SEQ_TIME_STAMP_MASK (1<<0)
-
-#define SNDRV_SEQ_TIME_MODE_ABS (0<<1) /* absolute timestamp */
-#define SNDRV_SEQ_TIME_MODE_REL (1<<1) /* relative to current time */
-#define SNDRV_SEQ_TIME_MODE_MASK (1<<1)
-
-#define SNDRV_SEQ_EVENT_LENGTH_FIXED (0<<2) /* fixed event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /* variable event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARUSR (2<<2) /* variable event size - user memory space */
-#define SNDRV_SEQ_EVENT_LENGTH_MASK (3<<2)
-
-#define SNDRV_SEQ_PRIORITY_NORMAL (0<<4) /* normal priority */
-#define SNDRV_SEQ_PRIORITY_HIGH (1<<4) /* event should be processed before others */
-#define SNDRV_SEQ_PRIORITY_MASK (1<<4)
-
-
- /* note event */
-struct snd_seq_ev_note {
- unsigned char channel;
- unsigned char note;
- unsigned char velocity;
- unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */
- unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */
-};
-
- /* controller event */
-struct snd_seq_ev_ctrl {
- unsigned char channel;
- unsigned char unused1, unused2, unused3; /* pad */
- unsigned int param;
- signed int value;
-};
-
- /* generic set of bytes (12x8 bit) */
-struct snd_seq_ev_raw8 {
- unsigned char d[12]; /* 8 bit value */
-};
-
- /* generic set of integers (3x32 bit) */
-struct snd_seq_ev_raw32 {
- unsigned int d[3]; /* 32 bit value */
-};
-
- /* external stored data */
-struct snd_seq_ev_ext {
- unsigned int len; /* length of data */
- void *ptr; /* pointer to data (note: maybe 64-bit) */
-} __attribute__((packed));
-
-struct snd_seq_result {
- int event; /* processed event type */
- int result;
-};
-
-
-struct snd_seq_real_time {
- unsigned int tv_sec; /* seconds */
- unsigned int tv_nsec; /* nanoseconds */
-};
-
-typedef unsigned int snd_seq_tick_time_t; /* midi ticks */
-
-union snd_seq_timestamp {
- snd_seq_tick_time_t tick;
- struct snd_seq_real_time time;
-};
-
-struct snd_seq_queue_skew {
- unsigned int value;
- unsigned int base;
-};
-
- /* queue timer control */
-struct snd_seq_ev_queue_control {
- unsigned char queue; /* affected queue */
- unsigned char pad[3]; /* reserved */
- union {
- signed int value; /* affected value (e.g. tempo) */
- union snd_seq_timestamp time; /* time */
- unsigned int position; /* sync position */
- struct snd_seq_queue_skew skew;
- unsigned int d32[2];
- unsigned char d8[8];
- } param;
-};
-
- /* quoted event - inside the kernel only */
-struct snd_seq_ev_quote {
- struct snd_seq_addr origin; /* original sender */
- unsigned short value; /* optional data */
- struct snd_seq_event *event; /* quoted event */
-} __attribute__((packed));
-
-
- /* sequencer event */
-struct snd_seq_event {
- snd_seq_event_type_t type; /* event type */
- unsigned char flags; /* event flags */
- char tag;
-
- unsigned char queue; /* schedule queue */
- union snd_seq_timestamp time; /* schedule time */
-
-
- struct snd_seq_addr source; /* source address */
- struct snd_seq_addr dest; /* destination address */
-
- union { /* event data... */
- struct snd_seq_ev_note note;
- struct snd_seq_ev_ctrl control;
- struct snd_seq_ev_raw8 raw8;
- struct snd_seq_ev_raw32 raw32;
- struct snd_seq_ev_ext ext;
- struct snd_seq_ev_queue_control queue;
- union snd_seq_timestamp time;
- struct snd_seq_addr addr;
- struct snd_seq_connect connect;
- struct snd_seq_result result;
- struct snd_seq_ev_quote quote;
- } data;
-};
-
-
-/*
- * bounce event - stored as variable size data
- */
-struct snd_seq_event_bounce {
- int err;
- struct snd_seq_event event;
- /* external data follows here. */
-};
-
-
- /* system information */
-struct snd_seq_system_info {
- int queues; /* maximum queues count */
- int clients; /* maximum clients count */
- int ports; /* maximum ports per client */
- int channels; /* maximum channels per port */
- int cur_clients; /* current clients */
- int cur_queues; /* current queues */
- char reserved[24];
-};
-
-
- /* system running information */
-struct snd_seq_running_info {
- unsigned char client; /* client id */
- unsigned char big_endian; /* 1 = big-endian */
- unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */
- unsigned char pad; /* reserved */
- unsigned char reserved[12];
-};
-
-
- /* known client numbers */
-#define SNDRV_SEQ_CLIENT_SYSTEM 0
- /* internal client numbers */
-#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */
-#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */
-
-
- /* client types */
-typedef int __bitwise snd_seq_client_type_t;
-#define NO_CLIENT ((__force snd_seq_client_type_t) 0)
-#define USER_CLIENT ((__force snd_seq_client_type_t) 1)
-#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2)
-
- /* event filter flags */
-#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */
-#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */
-#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */
-#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */
-
-struct snd_seq_client_info {
- int client; /* client number to inquire */
- snd_seq_client_type_t type; /* client type */
- char name[64]; /* client name */
- unsigned int filter; /* filter flags */
- unsigned char multicast_filter[8]; /* multicast filter bitmap */
- unsigned char event_filter[32]; /* event filter bitmap */
- int num_ports; /* RO: number of ports */
- int event_lost; /* number of lost events */
- int card; /* RO: card number[kernel] */
- int pid; /* RO: pid[user] */
- char reserved[56]; /* for future use */
-};
-
-
-/* client pool size */
-struct snd_seq_client_pool {
- int client; /* client number to inquire */
- int output_pool; /* outgoing (write) pool size */
- int input_pool; /* incoming (read) pool size */
- int output_room; /* minimum free pool size for select/blocking mode */
- int output_free; /* unused size */
- int input_free; /* unused size */
- char reserved[64];
-};
-
-
-/* Remove events by specified criteria */
-
-#define SNDRV_SEQ_REMOVE_INPUT (1<<0) /* Flush input queues */
-#define SNDRV_SEQ_REMOVE_OUTPUT (1<<1) /* Flush output queues */
-#define SNDRV_SEQ_REMOVE_DEST (1<<2) /* Restrict by destination q:client:port */
-#define SNDRV_SEQ_REMOVE_DEST_CHANNEL (1<<3) /* Restrict by channel */
-#define SNDRV_SEQ_REMOVE_TIME_BEFORE (1<<4) /* Restrict to before time */
-#define SNDRV_SEQ_REMOVE_TIME_AFTER (1<<5) /* Restrict to time or after */
-#define SNDRV_SEQ_REMOVE_TIME_TICK (1<<6) /* Time is in ticks */
-#define SNDRV_SEQ_REMOVE_EVENT_TYPE (1<<7) /* Restrict to event type */
-#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */
-#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */
-
-struct snd_seq_remove_events {
- unsigned int remove_mode; /* Flags that determine what gets removed */
-
- union snd_seq_timestamp time;
-
- unsigned char queue; /* Queue for REMOVE_DEST */
- struct snd_seq_addr dest; /* Address for REMOVE_DEST */
- unsigned char channel; /* Channel for REMOVE_DEST */
-
- int type; /* For REMOVE_EVENT_TYPE */
- char tag; /* Tag for REMOVE_TAG */
-
- int reserved[10]; /* To allow for future binary compatibility */
-
-};
-
-
- /* known port numbers */
-#define SNDRV_SEQ_PORT_SYSTEM_TIMER 0
-#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1
-
- /* port capabilities (32 bits) */
-#define SNDRV_SEQ_PORT_CAP_READ (1<<0) /* readable from this port */
-#define SNDRV_SEQ_PORT_CAP_WRITE (1<<1) /* writable to this port */
-
-#define SNDRV_SEQ_PORT_CAP_SYNC_READ (1<<2)
-#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE (1<<3)
-
-#define SNDRV_SEQ_PORT_CAP_DUPLEX (1<<4)
-
-#define SNDRV_SEQ_PORT_CAP_SUBS_READ (1<<5) /* allow read subscription */
-#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */
-#define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */
-
- /* port type */
-#define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /* generic MIDI device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM (1<<2) /* General MIDI compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GS (1<<3) /* GS compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */
-
-/* other standards...*/
-#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
-#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */
-#define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */
-/*...*/
-#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */
-#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */
-#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */
-#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */
-#define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */
-
-/* misc. conditioning flags */
-#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0)
-#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1)
-#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2)
-
-struct snd_seq_port_info {
- struct snd_seq_addr addr; /* client/port numbers */
- char name[64]; /* port name */
-
- unsigned int capability; /* port capability bits */
- unsigned int type; /* port type bits */
- int midi_channels; /* channels per MIDI port */
- int midi_voices; /* voices per MIDI port */
- int synth_voices; /* voices per SYNTH port */
-
- int read_use; /* R/O: subscribers for output (from this port) */
- int write_use; /* R/O: subscribers for input (to this port) */
-
- void *kernel; /* reserved for kernel use (must be NULL) */
- unsigned int flags; /* misc. conditioning */
- unsigned char time_queue; /* queue # for timestamping */
- char reserved[59]; /* for future use */
-};
-
-
-/* queue flags */
-#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */
-
-/* queue information */
-struct snd_seq_queue_info {
- int queue; /* queue id */
-
- /*
- * security settings, only owner of this queue can start/stop timer
- * etc. if the queue is locked for other clients
- */
- int owner; /* client id for owner of the queue */
- unsigned locked:1; /* timing queue locked for other queues */
- char name[64]; /* name of this queue */
- unsigned int flags; /* flags */
- char reserved[60]; /* for future use */
-
-};
-
-/* queue info/status */
-struct snd_seq_queue_status {
- int queue; /* queue id */
- int events; /* read-only - queue size */
- snd_seq_tick_time_t tick; /* current tick */
- struct snd_seq_real_time time; /* current time */
- int running; /* running state of queue */
- int flags; /* various flags */
- char reserved[64]; /* for the future */
-};
-
-
-/* queue tempo */
-struct snd_seq_queue_tempo {
- int queue; /* sequencer queue */
- unsigned int tempo; /* current tempo, us/tick */
- int ppq; /* time resolution, ticks/quarter */
- unsigned int skew_value; /* queue skew */
- unsigned int skew_base; /* queue skew base */
- char reserved[24]; /* for the future */
-};
-
-
-/* sequencer timer sources */
-#define SNDRV_SEQ_TIMER_ALSA 0 /* ALSA timer */
-#define SNDRV_SEQ_TIMER_MIDI_CLOCK 1 /* Midi Clock (CLOCK event) */
-#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */
-
-/* queue timer info */
-struct snd_seq_queue_timer {
- int queue; /* sequencer queue */
- int type; /* source timer type */
- union {
- struct {
- struct snd_timer_id id; /* ALSA's timer ID */
- unsigned int resolution; /* resolution in Hz */
- } alsa;
- } u;
- char reserved[64]; /* for the future use */
-};
-
-
-struct snd_seq_queue_client {
- int queue; /* sequencer queue */
- int client; /* sequencer client */
- int used; /* queue is used with this client
- (must be set for accepting events) */
- /* per client watermarks */
- char reserved[64]; /* for future use */
-};
-
-
-#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE (1<<0) /* exclusive connection */
-#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1)
-#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2)
-
-struct snd_seq_port_subscribe {
- struct snd_seq_addr sender; /* sender address */
- struct snd_seq_addr dest; /* destination address */
- unsigned int voices; /* number of voices to be allocated (0 = don't care) */
- unsigned int flags; /* modes */
- unsigned char queue; /* input time-stamp queue (optional) */
- unsigned char pad[3]; /* reserved */
- char reserved[64];
-};
-
-/* type of query subscription */
-#define SNDRV_SEQ_QUERY_SUBS_READ 0
-#define SNDRV_SEQ_QUERY_SUBS_WRITE 1
-
-struct snd_seq_query_subs {
- struct snd_seq_addr root; /* client/port id to be searched */
- int type; /* READ or WRITE */
- int index; /* 0..N-1 */
- int num_subs; /* R/O: number of subscriptions on this port */
- struct snd_seq_addr addr; /* R/O: result */
- unsigned char queue; /* R/O: result */
- unsigned int flags; /* R/O: result */
- char reserved[64]; /* for future use */
-};
-
-
-/*
- * IOCTL commands
- */
-
-#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int)
-#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int)
-#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info)
-#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info)
-
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info)
-
-#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info)
-
-#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
-
-#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events)
-#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs)
-#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info)
-
-#endif /* _UAPI__SOUND_ASEQUENCER_H */
+#include <alsa/sound/uapi/asequencer.h>
diff --git a/include/sound/asoc.h b/include/sound/asoc.h
index a74ca232..185bba81 100644
--- a/include/sound/asoc.h
+++ b/include/sound/asoc.h
@@ -1,633 +1 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * uapi/sound/asoc.h -- ALSA SoC Firmware Controls and DAPM
- *
- * Copyright (C) 2012 Texas Instruments Inc.
- * Copyright (C) 2015 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Simple file API to load FW that includes mixers, coefficients, DAPM graphs,
- * algorithms, equalisers, DAIs, widgets etc.
-*/
-
-#ifndef __LINUX_UAPI_SND_ASOC_H
-#define __LINUX_UAPI_SND_ASOC_H
-
-#include <linux/types.h>
-#include <sound/asound.h>
-
-/*
- * Maximum number of channels topology kcontrol can represent.
- */
-#define SND_SOC_TPLG_MAX_CHAN 8
-
-/*
- * Maximum number of PCM formats capability
- */
-#define SND_SOC_TPLG_MAX_FORMATS 16
-
-/*
- * Maximum number of PCM stream configs
- */
-#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8
-
-/*
- * Maximum number of physical link's hardware configs
- */
-#define SND_SOC_TPLG_HW_CONFIG_MAX 8
-
-/* individual kcontrol info types - can be mixed with other types */
-#define SND_SOC_TPLG_CTL_VOLSW 1
-#define SND_SOC_TPLG_CTL_VOLSW_SX 2
-#define SND_SOC_TPLG_CTL_VOLSW_XR_SX 3
-#define SND_SOC_TPLG_CTL_ENUM 4
-#define SND_SOC_TPLG_CTL_BYTES 5
-#define SND_SOC_TPLG_CTL_ENUM_VALUE 6
-#define SND_SOC_TPLG_CTL_RANGE 7
-#define SND_SOC_TPLG_CTL_STROBE 8
-
-
-/* individual widget kcontrol info types - can be mixed with other types */
-#define SND_SOC_TPLG_DAPM_CTL_VOLSW 64
-#define SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE 65
-#define SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT 66
-#define SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE 67
-#define SND_SOC_TPLG_DAPM_CTL_PIN 68
-
-/* DAPM widget types - add new items to the end */
-#define SND_SOC_TPLG_DAPM_INPUT 0
-#define SND_SOC_TPLG_DAPM_OUTPUT 1
-#define SND_SOC_TPLG_DAPM_MUX 2
-#define SND_SOC_TPLG_DAPM_MIXER 3
-#define SND_SOC_TPLG_DAPM_PGA 4
-#define SND_SOC_TPLG_DAPM_OUT_DRV 5
-#define SND_SOC_TPLG_DAPM_ADC 6
-#define SND_SOC_TPLG_DAPM_DAC 7
-#define SND_SOC_TPLG_DAPM_SWITCH 8
-#define SND_SOC_TPLG_DAPM_PRE 9
-#define SND_SOC_TPLG_DAPM_POST 10
-#define SND_SOC_TPLG_DAPM_AIF_IN 11
-#define SND_SOC_TPLG_DAPM_AIF_OUT 12
-#define SND_SOC_TPLG_DAPM_DAI_IN 13
-#define SND_SOC_TPLG_DAPM_DAI_OUT 14
-#define SND_SOC_TPLG_DAPM_DAI_LINK 15
-#define SND_SOC_TPLG_DAPM_BUFFER 16
-#define SND_SOC_TPLG_DAPM_SCHEDULER 17
-#define SND_SOC_TPLG_DAPM_EFFECT 18
-#define SND_SOC_TPLG_DAPM_SIGGEN 19
-#define SND_SOC_TPLG_DAPM_SRC 20
-#define SND_SOC_TPLG_DAPM_ASRC 21
-#define SND_SOC_TPLG_DAPM_ENCODER 22
-#define SND_SOC_TPLG_DAPM_DECODER 23
-#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DECODER
-
-/* Header magic number and string sizes */
-#define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */
-
-/* string sizes */
-#define SND_SOC_TPLG_NUM_TEXTS 16
-
-/* ABI version */
-#define SND_SOC_TPLG_ABI_VERSION 0x5 /* current version */
-#define SND_SOC_TPLG_ABI_VERSION_MIN 0x4 /* oldest version supported */
-
-/* Max size of TLV data */
-#define SND_SOC_TPLG_TLV_SIZE 32
-
-/*
- * File and Block header data types.
- * Add new generic and vendor types to end of list.
- * Generic types are handled by the core whilst vendors types are passed
- * to the component drivers for handling.
- */
-#define SND_SOC_TPLG_TYPE_MIXER 1
-#define SND_SOC_TPLG_TYPE_BYTES 2
-#define SND_SOC_TPLG_TYPE_ENUM 3
-#define SND_SOC_TPLG_TYPE_DAPM_GRAPH 4
-#define SND_SOC_TPLG_TYPE_DAPM_WIDGET 5
-#define SND_SOC_TPLG_TYPE_DAI_LINK 6
-#define SND_SOC_TPLG_TYPE_PCM 7
-#define SND_SOC_TPLG_TYPE_MANIFEST 8
-#define SND_SOC_TPLG_TYPE_CODEC_LINK 9
-#define SND_SOC_TPLG_TYPE_BACKEND_LINK 10
-#define SND_SOC_TPLG_TYPE_PDATA 11
-#define SND_SOC_TPLG_TYPE_DAI 12
-#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_DAI
-
-/* vendor block IDs - please add new vendor types to end */
-#define SND_SOC_TPLG_TYPE_VENDOR_FW 1000
-#define SND_SOC_TPLG_TYPE_VENDOR_CONFIG 1001
-#define SND_SOC_TPLG_TYPE_VENDOR_COEFF 1002
-#define SND_SOC_TPLG_TYPEVENDOR_CODEC 1003
-
-#define SND_SOC_TPLG_STREAM_PLAYBACK 0
-#define SND_SOC_TPLG_STREAM_CAPTURE 1
-
-/* vendor tuple types */
-#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0
-#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1
-#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2
-#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3
-#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4
-#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5
-
-/* DAI flags */
-#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0)
-#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
-#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
-
-/* DAI clock gating */
-#define SND_SOC_TPLG_DAI_CLK_GATE_UNDEFINED 0
-#define SND_SOC_TPLG_DAI_CLK_GATE_GATED 1
-#define SND_SOC_TPLG_DAI_CLK_GATE_CONT 2
-
-/* DAI mclk_direction */
-#define SND_SOC_TPLG_MCLK_CO 0 /* for codec, mclk is output */
-#define SND_SOC_TPLG_MCLK_CI 1 /* for codec, mclk is input */
-
-/* DAI physical PCM data formats.
- * Add new formats to the end of the list.
- */
-#define SND_SOC_DAI_FORMAT_I2S 1 /* I2S mode */
-#define SND_SOC_DAI_FORMAT_RIGHT_J 2 /* Right Justified mode */
-#define SND_SOC_DAI_FORMAT_LEFT_J 3 /* Left Justified mode */
-#define SND_SOC_DAI_FORMAT_DSP_A 4 /* L data MSB after FRM LRC */
-#define SND_SOC_DAI_FORMAT_DSP_B 5 /* L data MSB during FRM LRC */
-#define SND_SOC_DAI_FORMAT_AC97 6 /* AC97 */
-#define SND_SOC_DAI_FORMAT_PDM 7 /* Pulse density modulation */
-
-/* left and right justified also known as MSB and LSB respectively */
-#define SND_SOC_DAI_FORMAT_MSB SND_SOC_DAI_FORMAT_LEFT_J
-#define SND_SOC_DAI_FORMAT_LSB SND_SOC_DAI_FORMAT_RIGHT_J
-
-/* DAI link flags */
-#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES (1 << 0)
-#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
-#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
-#define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP (1 << 3)
-
-/* DAI topology BCLK parameter
- * For the backwards capability, by default codec is bclk master
- */
-#define SND_SOC_TPLG_BCLK_CM 0 /* codec is bclk master */
-#define SND_SOC_TPLG_BCLK_CS 1 /* codec is bclk slave */
-
-/* DAI topology FSYNC parameter
- * For the backwards capability, by default codec is fsync master
- */
-#define SND_SOC_TPLG_FSYNC_CM 0 /* codec is fsync master */
-#define SND_SOC_TPLG_FSYNC_CS 1 /* codec is fsync slave */
-
-/*
- * Block Header.
- * This header precedes all object and object arrays below.
- */
-struct snd_soc_tplg_hdr {
- __le32 magic; /* magic number */
- __le32 abi; /* ABI version */
- __le32 version; /* optional vendor specific version details */
- __le32 type; /* SND_SOC_TPLG_TYPE_ */
- __le32 size; /* size of this structure */
- __le32 vendor_type; /* optional vendor specific type info */
- __le32 payload_size; /* data bytes, excluding this header */
- __le32 index; /* identifier for block */
- __le32 count; /* number of elements in block */
-} __attribute__((packed));
-
-/* vendor tuple for uuid */
-struct snd_soc_tplg_vendor_uuid_elem {
- __le32 token;
- char uuid[16];
-} __attribute__((packed));
-
-/* vendor tuple for a bool/byte/short/word value */
-struct snd_soc_tplg_vendor_value_elem {
- __le32 token;
- __le32 value;
-} __attribute__((packed));
-
-/* vendor tuple for string */
-struct snd_soc_tplg_vendor_string_elem {
- __le32 token;
- char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-} __attribute__((packed));
-
-struct snd_soc_tplg_vendor_array {
- __le32 size; /* size in bytes of the array, including all elements */
- __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */
- __le32 num_elems; /* number of elements in array */
- union {
- struct snd_soc_tplg_vendor_uuid_elem uuid[0];
- struct snd_soc_tplg_vendor_value_elem value[0];
- struct snd_soc_tplg_vendor_string_elem string[0];
- };
-} __attribute__((packed));
-
-/*
- * Private data.
- * All topology objects may have private data that can be used by the driver or
- * firmware. Core will ignore this data.
- */
-struct snd_soc_tplg_private {
- __le32 size; /* in bytes of private data */
- union {
- char data[0];
- struct snd_soc_tplg_vendor_array array[0];
- };
-} __attribute__((packed));
-
-/*
- * Kcontrol TLV data.
- */
-struct snd_soc_tplg_tlv_dbscale {
- __le32 min;
- __le32 step;
- __le32 mute;
-} __attribute__((packed));
-
-struct snd_soc_tplg_ctl_tlv {
- __le32 size; /* in bytes of this structure */
- __le32 type; /* SNDRV_CTL_TLVT_*, type of TLV */
- union {
- __le32 data[SND_SOC_TPLG_TLV_SIZE];
- struct snd_soc_tplg_tlv_dbscale scale;
- };
-} __attribute__((packed));
-
-/*
- * Kcontrol channel data
- */
-struct snd_soc_tplg_channel {
- __le32 size; /* in bytes of this structure */
- __le32 reg;
- __le32 shift;
- __le32 id; /* ID maps to Left, Right, LFE etc */
-} __attribute__((packed));
-
-/*
- * Genericl Operations IDs, for binding Kcontrol or Bytes ext ops
- * Kcontrol ops need get/put/info.
- * Bytes ext ops need get/put.
- */
-struct snd_soc_tplg_io_ops {
- __le32 get;
- __le32 put;
- __le32 info;
-} __attribute__((packed));
-
-/*
- * kcontrol header
- */
-struct snd_soc_tplg_ctl_hdr {
- __le32 size; /* in bytes of this structure */
- __le32 type;
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- __le32 access;
- struct snd_soc_tplg_io_ops ops;
- struct snd_soc_tplg_ctl_tlv tlv;
-} __attribute__((packed));
-
-/*
- * Stream Capabilities
- */
-struct snd_soc_tplg_stream_caps {
- __le32 size; /* in bytes of this structure */
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */
- __le32 rates; /* supported rates SNDRV_PCM_RATE_* */
- __le32 rate_min; /* min rate */
- __le32 rate_max; /* max rate */
- __le32 channels_min; /* min channels */
- __le32 channels_max; /* max channels */
- __le32 periods_min; /* min number of periods */
- __le32 periods_max; /* max number of periods */
- __le32 period_size_min; /* min period size bytes */
- __le32 period_size_max; /* max period size bytes */
- __le32 buffer_size_min; /* min buffer size bytes */
- __le32 buffer_size_max; /* max buffer size bytes */
- __le32 sig_bits; /* number of bits of content */
-} __attribute__((packed));
-
-/*
- * FE or BE Stream configuration supported by SW/FW
- */
-struct snd_soc_tplg_stream {
- __le32 size; /* in bytes of this structure */
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* Name of the stream */
- __le64 format; /* SNDRV_PCM_FMTBIT_* */
- __le32 rate; /* SNDRV_PCM_RATE_* */
- __le32 period_bytes; /* size of period in bytes */
- __le32 buffer_bytes; /* size of buffer in bytes */
- __le32 channels; /* channels */
-} __attribute__((packed));
-
-
-/*
- * Describes a physical link's runtime supported hardware config,
- * i.e. hardware audio formats.
- */
-struct snd_soc_tplg_hw_config {
- __le32 size; /* in bytes of this structure */
- __le32 id; /* unique ID - - used to match */
- __le32 fmt; /* SND_SOC_DAI_FORMAT_ format value */
- __u8 clock_gated; /* SND_SOC_TPLG_DAI_CLK_GATE_ value */
- __u8 invert_bclk; /* 1 for inverted BCLK, 0 for normal */
- __u8 invert_fsync; /* 1 for inverted frame clock, 0 for normal */
- __u8 bclk_master; /* SND_SOC_TPLG_BCLK_ value */
- __u8 fsync_master; /* SND_SOC_TPLG_FSYNC_ value */
- __u8 mclk_direction; /* SND_SOC_TPLG_MCLK_ value */
- __le16 reserved; /* for 32bit alignment */
- __le32 mclk_rate; /* MCLK or SYSCLK freqency in Hz */
- __le32 bclk_rate; /* BCLK freqency in Hz */
- __le32 fsync_rate; /* frame clock in Hz */
- __le32 tdm_slots; /* number of TDM slots in use */
- __le32 tdm_slot_width; /* width in bits for each slot */
- __le32 tx_slots; /* bit mask for active Tx slots */
- __le32 rx_slots; /* bit mask for active Rx slots */
- __le32 tx_channels; /* number of Tx channels */
- __le32 tx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */
- __le32 rx_channels; /* number of Rx channels */
- __le32 rx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */
-} __attribute__((packed));
-
-/*
- * Manifest. List totals for each payload type. Not used in parsing, but will
- * be passed to the component driver before any other objects in order for any
- * global component resource allocations.
- *
- * File block representation for manifest :-
- * +-----------------------------------+----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-----------------------------------+----+
- * | struct snd_soc_tplg_manifest | 1 |
- * +-----------------------------------+----+
- */
-struct snd_soc_tplg_manifest {
- __le32 size; /* in bytes of this structure */
- __le32 control_elems; /* number of control elements */
- __le32 widget_elems; /* number of widget elements */
- __le32 graph_elems; /* number of graph elements */
- __le32 pcm_elems; /* number of PCM elements */
- __le32 dai_link_elems; /* number of DAI link elements */
- __le32 dai_elems; /* number of physical DAI elements */
- __le32 reserved[20]; /* reserved for new ABI element types */
- struct snd_soc_tplg_private priv;
-} __attribute__((packed));
-
-/*
- * Mixer kcontrol.
- *
- * File block representation for mixer kcontrol :-
- * +-----------------------------------+----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-----------------------------------+----+
- * | struct snd_soc_tplg_mixer_control | N |
- * +-----------------------------------+----+
- */
-struct snd_soc_tplg_mixer_control {
- struct snd_soc_tplg_ctl_hdr hdr;
- __le32 size; /* in bytes of this structure */
- __le32 min;
- __le32 max;
- __le32 platform_max;
- __le32 invert;
- __le32 num_channels;
- struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
- struct snd_soc_tplg_private priv;
-} __attribute__((packed));
-
-/*
- * Enumerated kcontrol
- *
- * File block representation for enum kcontrol :-
- * +-----------------------------------+----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-----------------------------------+----+
- * | struct snd_soc_tplg_enum_control | N |
- * +-----------------------------------+----+
- */
-struct snd_soc_tplg_enum_control {
- struct snd_soc_tplg_ctl_hdr hdr;
- __le32 size; /* in bytes of this structure */
- __le32 num_channels;
- struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
- __le32 items;
- __le32 mask;
- __le32 count;
- char texts[SND_SOC_TPLG_NUM_TEXTS][SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- __le32 values[SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN / 4];
- struct snd_soc_tplg_private priv;
-} __attribute__((packed));
-
-/*
- * Bytes kcontrol
- *
- * File block representation for bytes kcontrol :-
- * +-----------------------------------+----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-----------------------------------+----+
- * | struct snd_soc_tplg_bytes_control | N |
- * +-----------------------------------+----+
- */
-struct snd_soc_tplg_bytes_control {
- struct snd_soc_tplg_ctl_hdr hdr;
- __le32 size; /* in bytes of this structure */
- __le32 max;
- __le32 mask;
- __le32 base;
- __le32 num_regs;
- struct snd_soc_tplg_io_ops ext_ops;
- struct snd_soc_tplg_private priv;
-} __attribute__((packed));
-
-/*
- * DAPM Graph Element
- *
- * File block representation for DAPM graph elements :-
- * +-------------------------------------+----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-------------------------------------+----+
- * | struct snd_soc_tplg_dapm_graph_elem | N |
- * +-------------------------------------+----+
- */
-struct snd_soc_tplg_dapm_graph_elem {
- char sink[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- char control[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- char source[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-} __attribute__((packed));
-
-/*
- * DAPM Widget.
- *
- * File block representation for DAPM widget :-
- * +-------------------------------------+-----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-------------------------------------+-----+
- * | struct snd_soc_tplg_dapm_widget | N |
- * +-------------------------------------+-----+
- * | struct snd_soc_tplg_enum_control | 0|1 |
- * | struct snd_soc_tplg_mixer_control | 0|N |
- * +-------------------------------------+-----+
- *
- * Optional enum or mixer control can be appended to the end of each widget
- * in the block.
- */
-struct snd_soc_tplg_dapm_widget {
- __le32 size; /* in bytes of this structure */
- __le32 id; /* SND_SOC_DAPM_CTL */
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- char sname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-
- __le32 reg; /* negative reg = no direct dapm */
- __le32 shift; /* bits to shift */
- __le32 mask; /* non-shifted mask */
- __le32 subseq; /* sort within widget type */
- __le32 invert; /* invert the power bit */
- __le32 ignore_suspend; /* kept enabled over suspend */
- __le16 event_flags;
- __le16 event_type;
- __le32 num_kcontrols;
- struct snd_soc_tplg_private priv;
- /*
- * kcontrols that relate to this widget
- * follow here after widget private data
- */
-} __attribute__((packed));
-
-
-/*
- * Describes SW/FW specific features of PCM (FE DAI & DAI link).
- *
- * File block representation for PCM :-
- * +-----------------------------------+-----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-----------------------------------+-----+
- * | struct snd_soc_tplg_pcm | N |
- * +-----------------------------------+-----+
- */
-struct snd_soc_tplg_pcm {
- __le32 size; /* in bytes of this structure */
- char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- __le32 pcm_id; /* unique ID - used to match with DAI link */
- __le32 dai_id; /* unique ID - used to match */
- __le32 playback; /* supports playback mode */
- __le32 capture; /* supports capture mode */
- __le32 compress; /* 1 = compressed; 0 = PCM */
- struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */
- __le32 num_streams; /* number of streams */
- struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */
- __le32 flag_mask; /* bitmask of flags to configure */
- __le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */
- struct snd_soc_tplg_private priv;
-} __attribute__((packed));
-
-
-/*
- * Describes the physical link runtime supported configs or params
- *
- * File block representation for physical link config :-
- * +-----------------------------------+-----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-----------------------------------+-----+
- * | struct snd_soc_tplg_link_config | N |
- * +-----------------------------------+-----+
- */
-struct snd_soc_tplg_link_config {
- __le32 size; /* in bytes of this structure */
- __le32 id; /* unique ID - used to match */
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */
- char stream_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* stream name - used to match */
- struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
- __le32 num_streams; /* number of streams */
- struct snd_soc_tplg_hw_config hw_config[SND_SOC_TPLG_HW_CONFIG_MAX]; /* hw configs */
- __le32 num_hw_configs; /* number of hw configs */
- __le32 default_hw_config_id; /* default hw config ID for init */
- __le32 flag_mask; /* bitmask of flags to configure */
- __le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */
- struct snd_soc_tplg_private priv;
-} __attribute__((packed));
-
-/*
- * Describes SW/FW specific features of physical DAI.
- * It can be used to configure backend DAIs for DPCM.
- *
- * File block representation for physical DAI :-
- * +-----------------------------------+-----+
- * | struct snd_soc_tplg_hdr | 1 |
- * +-----------------------------------+-----+
- * | struct snd_soc_tplg_dai | N |
- * +-----------------------------------+-----+
- */
-struct snd_soc_tplg_dai {
- __le32 size; /* in bytes of this structure */
- char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */
- __le32 dai_id; /* unique ID - used to match */
- __le32 playback; /* supports playback mode */
- __le32 capture; /* supports capture mode */
- struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */
- __le32 flag_mask; /* bitmask of flags to configure */
- __le32 flags; /* SND_SOC_TPLG_DAI_FLGBIT_* */
- struct snd_soc_tplg_private priv;
-} __attribute__((packed));
-
-/*
- * Old version of ABI structs, supported for backward compatibility.
- */
-
-/* Manifest v4 */
-struct snd_soc_tplg_manifest_v4 {
- __le32 size; /* in bytes of this structure */
- __le32 control_elems; /* number of control elements */
- __le32 widget_elems; /* number of widget elements */
- __le32 graph_elems; /* number of graph elements */
- __le32 pcm_elems; /* number of PCM elements */
- __le32 dai_link_elems; /* number of DAI link elements */
- struct snd_soc_tplg_private priv;
-} __packed;
-
-/* Stream Capabilities v4 */
-struct snd_soc_tplg_stream_caps_v4 {
- __le32 size; /* in bytes of this structure */
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */
- __le32 rates; /* supported rates SNDRV_PCM_RATE_* */
- __le32 rate_min; /* min rate */
- __le32 rate_max; /* max rate */
- __le32 channels_min; /* min channels */
- __le32 channels_max; /* max channels */
- __le32 periods_min; /* min number of periods */
- __le32 periods_max; /* max number of periods */
- __le32 period_size_min; /* min period size bytes */
- __le32 period_size_max; /* max period size bytes */
- __le32 buffer_size_min; /* min buffer size bytes */
- __le32 buffer_size_max; /* max buffer size bytes */
-} __packed;
-
-/* PCM v4 */
-struct snd_soc_tplg_pcm_v4 {
- __le32 size; /* in bytes of this structure */
- char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- __le32 pcm_id; /* unique ID - used to match with DAI link */
- __le32 dai_id; /* unique ID - used to match */
- __le32 playback; /* supports playback mode */
- __le32 capture; /* supports capture mode */
- __le32 compress; /* 1 = compressed; 0 = PCM */
- struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */
- __le32 num_streams; /* number of streams */
- struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */
-} __packed;
-
-/* Physical link config v4 */
-struct snd_soc_tplg_link_config_v4 {
- __le32 size; /* in bytes of this structure */
- __le32 id; /* unique ID - used to match */
- struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
- __le32 num_streams; /* number of streams */
-} __packed;
-
-#endif
+#include <alsa/sound/uapi/asoc.h>
diff --git a/include/sound/asound.h b/include/sound/asound.h
index df1153ce..3be4d850 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -1,1038 +1 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/*
- * Advanced Linux Sound Architecture - ALSA - Driver
- * Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
- * Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef _UAPI__SOUND_ASOUND_H
-#define _UAPI__SOUND_ASOUND_H
-
-#if defined(__KERNEL__) || defined(__linux__)
-#include <linux/types.h>
-#else
-#include <sys/ioctl.h>
-#endif
-
-#ifndef __KERNEL__
-#include <stdlib.h>
-#include <time.h>
-#endif
-
-/*
- * protocol version
- */
-
-#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
-#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
-#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
-#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
-#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
- (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
- (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
- SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
-
-/****************************************************************************
- * *
- * Digital audio interface *
- * *
- ****************************************************************************/
-
-struct snd_aes_iec958 {
- unsigned char status[24]; /* AES/IEC958 channel status bits */
- unsigned char subcode[147]; /* AES/IEC958 subcode bits */
- unsigned char pad; /* nothing */
- unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
-};
-
-/****************************************************************************
- * *
- * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
- * *
- ****************************************************************************/
-
-struct snd_cea_861_aud_if {
- unsigned char db1_ct_cc; /* coding type and channel count */
- unsigned char db2_sf_ss; /* sample frequency and size */
- unsigned char db3; /* not used, all zeros */
- unsigned char db4_ca; /* channel allocation code */
- unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
-};
-
-/****************************************************************************
- * *
- * Section for driver hardware dependent interface - /dev/snd/hw? *
- * *
- ****************************************************************************/
-
-#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-enum {
- SNDRV_HWDEP_IFACE_OPL2 = 0,
- SNDRV_HWDEP_IFACE_OPL3,
- SNDRV_HWDEP_IFACE_OPL4,
- SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */
- SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */
- SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */
- SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */
- SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
- SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
- SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
- SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */
- SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */
- SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */
- SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
- SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
- SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
- SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
- SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
- SNDRV_HWDEP_IFACE_FW_DICE, /* TC DICE FireWire device */
- SNDRV_HWDEP_IFACE_FW_FIREWORKS, /* Echo Audio Fireworks based device */
- SNDRV_HWDEP_IFACE_FW_BEBOB, /* BridgeCo BeBoB based device */
- SNDRV_HWDEP_IFACE_FW_OXFW, /* Oxford OXFW970/971 based device */
- SNDRV_HWDEP_IFACE_FW_DIGI00X, /* Digidesign Digi 002/003 family */
- SNDRV_HWDEP_IFACE_FW_TASCAM, /* TASCAM FireWire series */
- SNDRV_HWDEP_IFACE_LINE6, /* Line6 USB processors */
- SNDRV_HWDEP_IFACE_FW_MOTU, /* MOTU FireWire series */
- SNDRV_HWDEP_IFACE_FW_FIREFACE, /* RME Fireface series */
-
- /* Don't forget to change the following: */
- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE
-};
-
-struct snd_hwdep_info {
- unsigned int device; /* WR: device number */
- int card; /* R: card number */
- unsigned char id[64]; /* ID (user selectable) */
- unsigned char name[80]; /* hwdep name */
- int iface; /* hwdep interface */
- unsigned char reserved[64]; /* reserved for future */
-};
-
-/* generic DSP loader */
-struct snd_hwdep_dsp_status {
- unsigned int version; /* R: driver-specific version */
- unsigned char id[32]; /* R: driver-specific ID string */
- unsigned int num_dsps; /* R: number of DSP images to transfer */
- unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */
- unsigned int chip_ready; /* R: 1 = initialization finished */
- unsigned char reserved[16]; /* reserved for future use */
-};
-
-struct snd_hwdep_dsp_image {
- unsigned int index; /* W: DSP index */
- unsigned char name[64]; /* W: ID (e.g. file name) */
- unsigned char __user *image; /* W: binary image */
- size_t length; /* W: size of image in bytes */
- unsigned long driver_data; /* W: driver-specific data */
-};
-
-#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
-#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
-#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
-#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-
-/*****************************************************************************
- * *
- * Digital Audio (PCM) interface - /dev/snd/pcm?? *
- * *
- *****************************************************************************/
-
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14)
-
-typedef unsigned long snd_pcm_uframes_t;
-typedef signed long snd_pcm_sframes_t;
-
-enum {
- SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */
- SNDRV_PCM_CLASS_MULTI, /* multichannel device */
- SNDRV_PCM_CLASS_MODEM, /* software modem class */
- SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */
- /* Don't forget to change the following: */
- SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
-};
-
-enum {
- SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
- SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */
- /* Don't forget to change the following: */
- SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
-};
-
-enum {
- SNDRV_PCM_STREAM_PLAYBACK = 0,
- SNDRV_PCM_STREAM_CAPTURE,
- SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
-};
-
-typedef int __bitwise snd_pcm_access_t;
-#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */
-#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
-#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */
-#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */
-#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */
-#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
-
-typedef int __bitwise snd_pcm_format_t;
-#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
-#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
-#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
-#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
-#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
-#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
-#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
-#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
-#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
-#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
-#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
-#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
-#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
-#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
-#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
-#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
-#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
-#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
-#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
-#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
-#define SNDRV_PCM_FORMAT_S20_LE ((__force snd_pcm_format_t) 25) /* in four bytes, LSB justified */
-#define SNDRV_PCM_FORMAT_S20_BE ((__force snd_pcm_format_t) 26) /* in four bytes, LSB justified */
-#define SNDRV_PCM_FORMAT_U20_LE ((__force snd_pcm_format_t) 27) /* in four bytes, LSB justified */
-#define SNDRV_PCM_FORMAT_U20_BE ((__force snd_pcm_format_t) 28) /* in four bytes, LSB justified */
-/* gap in the numbering for a future standard linear format */
-#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
-#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */
-#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
-#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
-#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
-#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
-#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
-#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
-#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
-#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
-#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */
-#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */
-#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */
-#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE
-#define SNDRV_PCM_FORMAT_FIRST SNDRV_PCM_FORMAT_S8
-
-#ifdef SNDRV_LITTLE_ENDIAN
-#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
-#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
-#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
-#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
-#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
-#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
-#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
-#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
-#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_LE
-#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_LE
-#endif
-#ifdef SNDRV_BIG_ENDIAN
-#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
-#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
-#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
-#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
-#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
-#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
-#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
-#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
-#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_BE
-#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_BE
-#endif
-
-typedef int __bitwise snd_pcm_subformat_t;
-#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
-#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
-
-#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
-#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
-#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
-#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
-#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */
-#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
-#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
-#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
-#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */
-#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */
-#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */
-#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */
-#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */
-#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
-#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
-#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
-#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */
-#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */
-#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */
-#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */
-#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */
-
-#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
-#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
-
-
-
-typedef int __bitwise snd_pcm_state_t;
-#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
-#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
-#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */
-#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */
-#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
-#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */
-#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
-#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
-#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
-#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
-
-enum {
- SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
- SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
- SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
-};
-
-union snd_pcm_sync_id {
- unsigned char id[16];
- unsigned short id16[8];
- unsigned int id32[4];
-};
-
-struct snd_pcm_info {
- unsigned int device; /* RO/WR (control): device number */
- unsigned int subdevice; /* RO/WR (control): subdevice number */
- int stream; /* RO/WR (control): stream direction */
- int card; /* R: card number */
- unsigned char id[64]; /* ID (user selectable) */
- unsigned char name[80]; /* name of this device */
- unsigned char subname[32]; /* subdevice name */
- int dev_class; /* SNDRV_PCM_CLASS_* */
- int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */
- unsigned int subdevices_count;
- unsigned int subdevices_avail;
- union snd_pcm_sync_id sync; /* hardware synchronization ID */
- unsigned char reserved[64]; /* reserved for future... */
-};
-
-typedef int snd_pcm_hw_param_t;
-#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */
-#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */
-#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */
-#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
-#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
-
-#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */
-#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */
-#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */
-#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */
-#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between
- * interrupts in us
- */
-#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between
- * interrupts
- */
-#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between
- * interrupts
- */
-#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per
- * buffer
- */
-#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer
- * in us
- */
-#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */
-#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */
-#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */
-#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
-#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
-
-#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
-#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */
-#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */
-
-struct snd_interval {
- unsigned int min, max;
- unsigned int openmin:1,
- openmax:1,
- integer:1,
- empty:1;
-};
-
-#define SNDRV_MASK_MAX 256
-
-struct snd_mask {
- __u32 bits[(SNDRV_MASK_MAX+31)/32];
-};
-
-struct snd_pcm_hw_params {
- unsigned int flags;
- struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
- SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
- struct snd_mask mres[5]; /* reserved masks */
- struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
- SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
- struct snd_interval ires[9]; /* reserved intervals */
- unsigned int rmask; /* W: requested masks */
- unsigned int cmask; /* R: changed masks */
- unsigned int info; /* R: Info flags for returned setup */
- unsigned int msbits; /* R: used most significant bits */
- unsigned int rate_num; /* R: rate numerator */
- unsigned int rate_den; /* R: rate denominator */
- snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
- unsigned char reserved[64]; /* reserved for future */
-};
-
-enum {
- SNDRV_PCM_TSTAMP_NONE = 0,
- SNDRV_PCM_TSTAMP_ENABLE,
- SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
-};
-
-struct snd_pcm_sw_params {
- int tstamp_mode; /* timestamp mode */
- unsigned int period_step;
- unsigned int sleep_min; /* min ticks to sleep */
- snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
- snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */
- snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
- snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
- snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
- snd_pcm_uframes_t silence_size; /* silence block size */
- snd_pcm_uframes_t boundary; /* pointers wrap point */
- unsigned int proto; /* protocol version */
- unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */
- unsigned char reserved[56]; /* reserved for future */
-};
-
-struct snd_pcm_channel_info {
- unsigned int channel;
- __kernel_off_t offset; /* mmap offset */
- unsigned int first; /* offset to first sample in bits */
- unsigned int step; /* samples distance in bits */
-};
-
-enum {
- /*
- * first definition for backwards compatibility only,
- * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else
- */
- SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0,
-
- /* timestamp definitions */
- SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */
- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */
- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */
- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */
- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */
- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
-};
-
-struct snd_pcm_status {
- snd_pcm_state_t state; /* stream state */
- struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
- struct timespec tstamp; /* reference timestamp */
- snd_pcm_uframes_t appl_ptr; /* appl ptr */
- snd_pcm_uframes_t hw_ptr; /* hw ptr */
- snd_pcm_sframes_t delay; /* current delay in frames */
- snd_pcm_uframes_t avail; /* number of frames available */
- snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
- snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
- snd_pcm_state_t suspended_state; /* suspended stream state */
- __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
- struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */
- struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */
- __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
- unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
-};
-
-struct snd_pcm_mmap_status {
- snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
- int pad1; /* Needed for 64 bit alignment */
- snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
- struct timespec tstamp; /* Timestamp */
- snd_pcm_state_t suspended_state; /* RO: suspended stream state */
- struct timespec audio_tstamp; /* from sample counter or wall clock */
-};
-
-struct snd_pcm_mmap_control {
- snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
- snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
-};
-
-#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */
-#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
-#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
-
-struct snd_pcm_sync_ptr {
- unsigned int flags;
- union {
- struct snd_pcm_mmap_status status;
- unsigned char reserved[64];
- } s;
- union {
- struct snd_pcm_mmap_control control;
- unsigned char reserved[64];
- } c;
-};
-
-struct snd_xferi {
- snd_pcm_sframes_t result;
- void __user *buf;
- snd_pcm_uframes_t frames;
-};
-
-struct snd_xfern {
- snd_pcm_sframes_t result;
- void __user * __user *bufs;
- snd_pcm_uframes_t frames;
-};
-
-enum {
- SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
- SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
- SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */
- SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
-};
-
-/* channel positions */
-enum {
- SNDRV_CHMAP_UNKNOWN = 0,
- SNDRV_CHMAP_NA, /* N/A, silent */
- SNDRV_CHMAP_MONO, /* mono stream */
- /* this follows the alsa-lib mixer channel value + 3 */
- SNDRV_CHMAP_FL, /* front left */
- SNDRV_CHMAP_FR, /* front right */
- SNDRV_CHMAP_RL, /* rear left */
- SNDRV_CHMAP_RR, /* rear right */
- SNDRV_CHMAP_FC, /* front center */
- SNDRV_CHMAP_LFE, /* LFE */
- SNDRV_CHMAP_SL, /* side left */
- SNDRV_CHMAP_SR, /* side right */
- SNDRV_CHMAP_RC, /* rear center */
- /* new definitions */
- SNDRV_CHMAP_FLC, /* front left center */
- SNDRV_CHMAP_FRC, /* front right center */
- SNDRV_CHMAP_RLC, /* rear left center */
- SNDRV_CHMAP_RRC, /* rear right center */
- SNDRV_CHMAP_FLW, /* front left wide */
- SNDRV_CHMAP_FRW, /* front right wide */
- SNDRV_CHMAP_FLH, /* front left high */
- SNDRV_CHMAP_FCH, /* front center high */
- SNDRV_CHMAP_FRH, /* front right high */
- SNDRV_CHMAP_TC, /* top center */
- SNDRV_CHMAP_TFL, /* top front left */
- SNDRV_CHMAP_TFR, /* top front right */
- SNDRV_CHMAP_TFC, /* top front center */
- SNDRV_CHMAP_TRL, /* top rear left */
- SNDRV_CHMAP_TRR, /* top rear right */
- SNDRV_CHMAP_TRC, /* top rear center */
- /* new definitions for UAC2 */
- SNDRV_CHMAP_TFLC, /* top front left center */
- SNDRV_CHMAP_TFRC, /* top front right center */
- SNDRV_CHMAP_TSL, /* top side left */
- SNDRV_CHMAP_TSR, /* top side right */
- SNDRV_CHMAP_LLFE, /* left LFE */
- SNDRV_CHMAP_RLFE, /* right LFE */
- SNDRV_CHMAP_BC, /* bottom center */
- SNDRV_CHMAP_BLC, /* bottom left center */
- SNDRV_CHMAP_BRC, /* bottom right center */
- SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
-};
-
-#define SNDRV_CHMAP_POSITION_MASK 0xffff
-#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
-#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
-
-#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
-#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
-#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
-#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
-#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int)
-#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
-#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
-#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
-#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
-#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
-#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
-#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status)
-#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
-#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
-#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
-#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
-#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
-#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
-#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
-#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
-#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
-#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
-#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
-
-/*****************************************************************************
- * *
- * MIDI v1.0 interface *
- * *
- *****************************************************************************/
-
-/*
- * Raw MIDI section - /dev/snd/midi??
- */
-
-#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
-
-enum {
- SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
- SNDRV_RAWMIDI_STREAM_INPUT,
- SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
-};
-
-#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
-#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
-#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
-
-struct snd_rawmidi_info {
- unsigned int device; /* RO/WR (control): device number */
- unsigned int subdevice; /* RO/WR (control): subdevice number */
- int stream; /* WR: stream */
- int card; /* R: card number */
- unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */
- unsigned char id[64]; /* ID (user selectable) */
- unsigned char name[80]; /* name of device */
- unsigned char subname[32]; /* name of active or selected subdevice */
- unsigned int subdevices_count;
- unsigned int subdevices_avail;
- unsigned char reserved[64]; /* reserved for future use */
-};
-
-struct snd_rawmidi_params {
- int stream;
- size_t buffer_size; /* queue size in bytes */
- size_t avail_min; /* minimum avail bytes for wakeup */
- unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
- unsigned char reserved[16]; /* reserved for future use */
-};
-
-struct snd_rawmidi_status {
- int stream;
- struct timespec tstamp; /* Timestamp */
- size_t avail; /* available bytes */
- size_t xruns; /* count of overruns since last status (in bytes) */
- unsigned char reserved[16]; /* reserved for future use */
-};
-
-#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
-#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
-#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
-#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
-#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
-#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
-
-/*
- * Timer section - /dev/snd/timer
- */
-
-#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
-
-enum {
- SNDRV_TIMER_CLASS_NONE = -1,
- SNDRV_TIMER_CLASS_SLAVE = 0,
- SNDRV_TIMER_CLASS_GLOBAL,
- SNDRV_TIMER_CLASS_CARD,
- SNDRV_TIMER_CLASS_PCM,
- SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
-};
-
-/* slave timer classes */
-enum {
- SNDRV_TIMER_SCLASS_NONE = 0,
- SNDRV_TIMER_SCLASS_APPLICATION,
- SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */
- SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */
- SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
-};
-
-/* global timers (device member) */
-#define SNDRV_TIMER_GLOBAL_SYSTEM 0
-#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */
-#define SNDRV_TIMER_GLOBAL_HPET 2
-#define SNDRV_TIMER_GLOBAL_HRTIMER 3
-
-/* info flags */
-#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
-
-struct snd_timer_id {
- int dev_class;
- int dev_sclass;
- int card;
- int device;
- int subdevice;
-};
-
-struct snd_timer_ginfo {
- struct snd_timer_id tid; /* requested timer ID */
- unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
- int card; /* card number */
- unsigned char id[64]; /* timer identification */
- unsigned char name[80]; /* timer name */
- unsigned long reserved0; /* reserved for future use */
- unsigned long resolution; /* average period resolution in ns */
- unsigned long resolution_min; /* minimal period resolution in ns */
- unsigned long resolution_max; /* maximal period resolution in ns */
- unsigned int clients; /* active timer clients */
- unsigned char reserved[32];
-};
-
-struct snd_timer_gparams {
- struct snd_timer_id tid; /* requested timer ID */
- unsigned long period_num; /* requested precise period duration (in seconds) - numerator */
- unsigned long period_den; /* requested precise period duration (in seconds) - denominator */
- unsigned char reserved[32];
-};
-
-struct snd_timer_gstatus {
- struct snd_timer_id tid; /* requested timer ID */
- unsigned long resolution; /* current period resolution in ns */
- unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */
- unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */
- unsigned char reserved[32];
-};
-
-struct snd_timer_select {
- struct snd_timer_id id; /* bind to timer ID */
- unsigned char reserved[32]; /* reserved */
-};
-
-struct snd_timer_info {
- unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
- int card; /* card number */
- unsigned char id[64]; /* timer identificator */
- unsigned char name[80]; /* timer name */
- unsigned long reserved0; /* reserved for future use */
- unsigned long resolution; /* average period resolution in ns */
- unsigned char reserved[64]; /* reserved */
-};
-
-#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */
-#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */
-#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
-
-struct snd_timer_params {
- unsigned int flags; /* flags - SNDRV_TIMER_PSFLG_* */
- unsigned int ticks; /* requested resolution in ticks */
- unsigned int queue_size; /* total size of queue (32-1024) */
- unsigned int reserved0; /* reserved, was: failure locations */
- unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
- unsigned char reserved[60]; /* reserved */
-};
-
-struct snd_timer_status {
- struct timespec tstamp; /* Timestamp - last update */
- unsigned int resolution; /* current period resolution in ns */
- unsigned int lost; /* counter of master tick lost */
- unsigned int overrun; /* count of read queue overruns */
- unsigned int queue; /* used queue size */
- unsigned char reserved[64]; /* reserved */
-};
-
-#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
-#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
-#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
-#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
-#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
-#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
-#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
-#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
-#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
-#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
-/* The following four ioctls are changed since 1.0.9 due to confliction */
-#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
-#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
-#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
-#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
-
-struct snd_timer_read {
- unsigned int resolution;
- unsigned int ticks;
-};
-
-enum {
- SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */
- SNDRV_TIMER_EVENT_TICK, /* val = ticks */
- SNDRV_TIMER_EVENT_START, /* val = resolution in ns */
- SNDRV_TIMER_EVENT_STOP, /* val = 0 */
- SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */
- SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */
- SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */
- SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */
- SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */
- /* master timer events for slave timer instances */
- SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
- SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
- SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
- SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
- SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
- SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
-};
-
-struct snd_timer_tread {
- int event;
- struct timespec tstamp;
- unsigned int val;
-};
-
-/****************************************************************************
- * *
- * Section for driver control interface - /dev/snd/control? *
- * *
- ****************************************************************************/
-
-#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
-
-struct snd_ctl_card_info {
- int card; /* card number */
- int pad; /* reserved for future (was type) */
- unsigned char id[16]; /* ID of card (user selectable) */
- unsigned char driver[16]; /* Driver name */
- unsigned char name[32]; /* Short name of soundcard */
- unsigned char longname[80]; /* name + info text about soundcard */
- unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
- unsigned char mixername[80]; /* visual mixer identification */
- unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
-};
-
-typedef int __bitwise snd_ctl_elem_type_t;
-#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */
-#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */
-#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */
-#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
-#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */
-#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
-#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
-#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
-
-typedef int __bitwise snd_ctl_elem_iface_t;
-#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */
-#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
-#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
-#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
-#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
-#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */
-#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
-#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
-
-#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
-#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
-#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */
-#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */
-#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */
-#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */
-#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */
-#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */
-/* bits 30 and 31 are obsoleted (for indirect access) */
-
-/* for further details see the ACPI and PCI power management specification */
-#define SNDRV_CTL_POWER_D0 0x0000 /* full On */
-#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */
-#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */
-#define SNDRV_CTL_POWER_D3 0x0300 /* Off */
-#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */
-#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */
-
-#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44
-
-struct snd_ctl_elem_id {
- unsigned int numid; /* numeric identifier, zero = invalid */
- snd_ctl_elem_iface_t iface; /* interface identifier */
- unsigned int device; /* device/client number */
- unsigned int subdevice; /* subdevice (substream) number */
- unsigned char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* ASCII name of item */
- unsigned int index; /* index of item */
-};
-
-struct snd_ctl_elem_list {
- unsigned int offset; /* W: first element ID to get */
- unsigned int space; /* W: count of element IDs to get */
- unsigned int used; /* R: count of element IDs set */
- unsigned int count; /* R: count of all elements */
- struct snd_ctl_elem_id __user *pids; /* R: IDs */
- unsigned char reserved[50];
-};
-
-struct snd_ctl_elem_info {
- struct snd_ctl_elem_id id; /* W: element ID */
- snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
- unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
- unsigned int count; /* count of values */
- __kernel_pid_t owner; /* owner's PID of this control */
- union {
- struct {
- long min; /* R: minimum value */
- long max; /* R: maximum value */
- long step; /* R: step (0 variable) */
- } integer;
- struct {
- long long min; /* R: minimum value */
- long long max; /* R: maximum value */
- long long step; /* R: step (0 variable) */
- } integer64;
- struct {
- unsigned int items; /* R: number of items */
- unsigned int item; /* W: item number */
- char name[64]; /* R: value name */
- __u64 names_ptr; /* W: names list (ELEM_ADD only) */
- unsigned int names_length;
- } enumerated;
- unsigned char reserved[128];
- } value;
- union {
- unsigned short d[4]; /* dimensions */
- unsigned short *d_ptr; /* indirect - obsoleted */
- } dimen;
- unsigned char reserved[64-4*sizeof(unsigned short)];
-};
-
-struct snd_ctl_elem_value {
- struct snd_ctl_elem_id id; /* W: element ID */
- unsigned int indirect: 1; /* W: indirect access - obsoleted */
- union {
- union {
- long value[128];
- long *value_ptr; /* obsoleted */
- } integer;
- union {
- long long value[64];
- long long *value_ptr; /* obsoleted */
- } integer64;
- union {
- unsigned int item[128];
- unsigned int *item_ptr; /* obsoleted */
- } enumerated;
- union {
- unsigned char data[512];
- unsigned char *data_ptr; /* obsoleted */
- } bytes;
- struct snd_aes_iec958 iec958;
- } value; /* RO */
- struct timespec tstamp;
- unsigned char reserved[128-sizeof(struct timespec)];
-};
-
-struct snd_ctl_tlv {
- unsigned int numid; /* control element numeric identification */
- unsigned int length; /* in bytes aligned to 4 */
- unsigned int tlv[0]; /* first TLV */
-};
-
-#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
-#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
-#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
-#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
-#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
-#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
-#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
-#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
-#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
-#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
-#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
-#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
-
-/*
- * Read interface.
- */
-
-enum sndrv_ctl_event_type {
- SNDRV_CTL_EVENT_ELEM = 0,
- SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
-};
-
-#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */
-#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */
-#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */
-#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */
-#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */
-
-struct snd_ctl_event {
- int type; /* event type - SNDRV_CTL_EVENT_* */
- union {
- struct {
- unsigned int mask;
- struct snd_ctl_elem_id id;
- } elem;
- unsigned char data8[60];
- } data;
-};
-
-/*
- * Control names
- */
-
-#define SNDRV_CTL_NAME_NONE ""
-#define SNDRV_CTL_NAME_PLAYBACK "Playback "
-#define SNDRV_CTL_NAME_CAPTURE "Capture "
-
-#define SNDRV_CTL_NAME_IEC958_NONE ""
-#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
-#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
-#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
-#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
-#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
-#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
-#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
-#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
-
-#endif /* _UAPI__SOUND_ASOUND_H */
+#include <alsa/sound/uapi/asound.h>
diff --git a/include/sound/asound_fm.h b/include/sound/asound_fm.h
index 8471f404..3e5da4d0 100644
--- a/include/sound/asound_fm.h
+++ b/include/sound/asound_fm.h
@@ -1,135 +1 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-#ifndef __SOUND_ASOUND_FM_H
-#define __SOUND_ASOUND_FM_H
-
-/*
- * Advanced Linux Sound Architecture - ALSA
- *
- * Interface file between ALSA driver & user space
- * Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>,
- * 4Front Technologies
- *
- * Direct FM control
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#define SNDRV_DM_FM_MODE_OPL2 0x00
-#define SNDRV_DM_FM_MODE_OPL3 0x01
-
-struct snd_dm_fm_info {
- unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
- unsigned char rhythm; /* percussion mode flag */
-};
-
-/*
- * Data structure composing an FM "note" or sound event.
- */
-
-struct snd_dm_fm_voice {
- unsigned char op; /* operator cell (0 or 1) */
- unsigned char voice; /* FM voice (0 to 17) */
-
- unsigned char am; /* amplitude modulation */
- unsigned char vibrato; /* vibrato effect */
- unsigned char do_sustain; /* sustain phase */
- unsigned char kbd_scale; /* keyboard scaling */
- unsigned char harmonic; /* 4 bits: harmonic and multiplier */
- unsigned char scale_level; /* 2 bits: decrease output freq rises */
- unsigned char volume; /* 6 bits: volume */
-
- unsigned char attack; /* 4 bits: attack rate */
- unsigned char decay; /* 4 bits: decay rate */
- unsigned char sustain; /* 4 bits: sustain level */
- unsigned char release; /* 4 bits: release rate */
-
- unsigned char feedback; /* 3 bits: feedback for op0 */
- unsigned char connection; /* 0 for serial, 1 for parallel */
- unsigned char left; /* stereo left */
- unsigned char right; /* stereo right */
- unsigned char waveform; /* 3 bits: waveform shape */
-};
-
-/*
- * This describes an FM note by its voice, octave, frequency number (10bit)
- * and key on/off.
- */
-
-struct snd_dm_fm_note {
- unsigned char voice; /* 0-17 voice channel */
- unsigned char octave; /* 3 bits: what octave to play */
- unsigned int fnum; /* 10 bits: frequency number */
- unsigned char key_on; /* set for active, clear for silent */
-};
-
-/*
- * FM parameters that apply globally to all voices, and thus are not "notes"
- */
-
-struct snd_dm_fm_params {
- unsigned char am_depth; /* amplitude modulation depth (1=hi) */
- unsigned char vib_depth; /* vibrato depth (1=hi) */
- unsigned char kbd_split; /* keyboard split */
- unsigned char rhythm; /* percussion mode select */
-
- /* This block is the percussion instrument data */
- unsigned char bass;
- unsigned char snare;
- unsigned char tomtom;
- unsigned char cymbal;
- unsigned char hihat;
-};
-
-/*
- * FM mode ioctl settings
- */
-
-#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, struct snd_dm_fm_info)
-#define SNDRV_DM_FM_IOCTL_RESET _IO ('H', 0x21)
-#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, struct snd_dm_fm_note)
-#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, struct snd_dm_fm_voice)
-#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, struct snd_dm_fm_params)
-#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int)
-/* for OPL3 only */
-#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int)
-/* SBI patch management */
-#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES _IO ('H', 0x40)
-
-#define SNDRV_DM_FM_OSS_IOCTL_RESET 0x20
-#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21
-#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22
-#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23
-#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24
-#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25
-
-/*
- * Patch Record - fixed size for write
- */
-
-#define FM_KEY_SBI "SBI\032"
-#define FM_KEY_2OP "2OP\032"
-#define FM_KEY_4OP "4OP\032"
-
-struct sbi_patch {
- unsigned char prog;
- unsigned char bank;
- char key[4];
- char name[25];
- char extension[7];
- unsigned char data[32];
-};
-
-#endif /* __SOUND_ASOUND_FM_H */
+#include <alsa/sound/uapi/asound_fm.h>
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 042c5a6f..f06ecee5 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1,381 +1,2 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/*
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
- * Creative Labs, Inc.
- * Definitions for EMU10K1 (SB Live!) chips
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef _UAPI__SOUND_EMU10K1_H
-#define _UAPI__SOUND_EMU10K1_H
-
-#include <linux/types.h>
-#include <sound/asound.h>
-
-/*
- * ---- FX8010 ----
- */
-
-#define EMU10K1_CARD_CREATIVE 0x00000000
-#define EMU10K1_CARD_EMUAPS 0x00000001
-
-#define EMU10K1_FX8010_PCM_COUNT 8
-
-/*
- * Following definition is copied from linux/types.h to support compiling
- * this header file in userspace since they are not generally available for
- * uapi headers.
- */
-#define __EMU10K1_DECLARE_BITMAP(name,bits) \
- unsigned long name[(bits) / (sizeof(unsigned long) * 8)]
-
-/* instruction set */
-#define iMAC0 0x00 /* R = A + (X * Y >> 31) ; saturation */
-#define iMAC1 0x01 /* R = A + (-X * Y >> 31) ; saturation */
-#define iMAC2 0x02 /* R = A + (X * Y >> 31) ; wraparound */
-#define iMAC3 0x03 /* R = A + (-X * Y >> 31) ; wraparound */
-#define iMACINT0 0x04 /* R = A + X * Y ; saturation */
-#define iMACINT1 0x05 /* R = A + X * Y ; wraparound (31-bit) */
-#define iACC3 0x06 /* R = A + X + Y ; saturation */
-#define iMACMV 0x07 /* R = A, acc += X * Y >> 31 */
-#define iANDXOR 0x08 /* R = (A & X) ^ Y */
-#define iTSTNEG 0x09 /* R = (A >= Y) ? X : ~X */
-#define iLIMITGE 0x0a /* R = (A >= Y) ? X : Y */
-#define iLIMITLT 0x0b /* R = (A < Y) ? X : Y */
-#define iLOG 0x0c /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
-#define iEXP 0x0d /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
-#define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */
-#define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */
-
-/* GPRs */
-#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */
-#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */
-#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
-#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
- /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
-
-#define C_00000000 0x40
-#define C_00000001 0x41
-#define C_00000002 0x42
-#define C_00000003 0x43
-#define C_00000004 0x44
-#define C_00000008 0x45
-#define C_00000010 0x46
-#define C_00000020 0x47
-#define C_00000100 0x48
-#define C_00010000 0x49
-#define C_00080000 0x4a
-#define C_10000000 0x4b
-#define C_20000000 0x4c
-#define C_40000000 0x4d
-#define C_80000000 0x4e
-#define C_7fffffff 0x4f
-#define C_ffffffff 0x50
-#define C_fffffffe 0x51
-#define C_c0000000 0x52
-#define C_4f1bbcdc 0x53
-#define C_5a7ef9db 0x54
-#define C_00100000 0x55 /* ?? */
-#define GPR_ACCU 0x56 /* ACCUM, accumulator */
-#define GPR_COND 0x57 /* CCR, condition register */
-#define GPR_NOISE0 0x58 /* noise source */
-#define GPR_NOISE1 0x59 /* noise source */
-#define GPR_IRQ 0x5a /* IRQ register */
-#define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */
-#define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
-#define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-#define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-
-#define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-
-#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */
-#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */
-#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
-#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */
-#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
-#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
-#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
-#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
-#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
-#define A_GPR(x) (A_FXGPREGBASE + (x))
-
-/* cc_reg constants */
-#define CC_REG_NORMALIZED C_00000001
-#define CC_REG_BORROW C_00000002
-#define CC_REG_MINUS C_00000004
-#define CC_REG_ZERO C_00000008
-#define CC_REG_SATURATE C_00000010
-#define CC_REG_NONZERO C_00000100
-
-/* FX buses */
-#define FXBUS_PCM_LEFT 0x00
-#define FXBUS_PCM_RIGHT 0x01
-#define FXBUS_PCM_LEFT_REAR 0x02
-#define FXBUS_PCM_RIGHT_REAR 0x03
-#define FXBUS_MIDI_LEFT 0x04
-#define FXBUS_MIDI_RIGHT 0x05
-#define FXBUS_PCM_CENTER 0x06
-#define FXBUS_PCM_LFE 0x07
-#define FXBUS_PCM_LEFT_FRONT 0x08
-#define FXBUS_PCM_RIGHT_FRONT 0x09
-#define FXBUS_MIDI_REVERB 0x0c
-#define FXBUS_MIDI_CHORUS 0x0d
-#define FXBUS_PCM_LEFT_SIDE 0x0e
-#define FXBUS_PCM_RIGHT_SIDE 0x0f
-#define FXBUS_PT_LEFT 0x14
-#define FXBUS_PT_RIGHT 0x15
-
-/* Inputs */
-#define EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */
-#define EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */
-#define EXTIN_SPDIF_CD_L 0x02 /* internal S/PDIF CD - onboard - left */
-#define EXTIN_SPDIF_CD_R 0x03 /* internal S/PDIF CD - onboard - right */
-#define EXTIN_ZOOM_L 0x04 /* Zoom Video I2S - left */
-#define EXTIN_ZOOM_R 0x05 /* Zoom Video I2S - right */
-#define EXTIN_TOSLINK_L 0x06 /* LiveDrive - TOSLink Optical - left */
-#define EXTIN_TOSLINK_R 0x07 /* LiveDrive - TOSLink Optical - right */
-#define EXTIN_LINE1_L 0x08 /* LiveDrive - Line/Mic 1 - left */
-#define EXTIN_LINE1_R 0x09 /* LiveDrive - Line/Mic 1 - right */
-#define EXTIN_COAX_SPDIF_L 0x0a /* LiveDrive - Coaxial S/PDIF - left */
-#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
-#define EXTIN_LINE2_L 0x0c /* LiveDrive - Line/Mic 2 - left */
-#define EXTIN_LINE2_R 0x0d /* LiveDrive - Line/Mic 2 - right */
-
-/* Outputs */
-#define EXTOUT_AC97_L 0x00 /* AC'97 playback channel - left */
-#define EXTOUT_AC97_R 0x01 /* AC'97 playback channel - right */
-#define EXTOUT_TOSLINK_L 0x02 /* LiveDrive - TOSLink Optical - left */
-#define EXTOUT_TOSLINK_R 0x03 /* LiveDrive - TOSLink Optical - right */
-#define EXTOUT_AC97_CENTER 0x04 /* SB Live 5.1 - center */
-#define EXTOUT_AC97_LFE 0x05 /* SB Live 5.1 - LFE */
-#define EXTOUT_HEADPHONE_L 0x06 /* LiveDrive - Headphone - left */
-#define EXTOUT_HEADPHONE_R 0x07 /* LiveDrive - Headphone - right */
-#define EXTOUT_REAR_L 0x08 /* Rear channel - left */
-#define EXTOUT_REAR_R 0x09 /* Rear channel - right */
-#define EXTOUT_ADC_CAP_L 0x0a /* ADC Capture buffer - left */
-#define EXTOUT_ADC_CAP_R 0x0b /* ADC Capture buffer - right */
-#define EXTOUT_MIC_CAP 0x0c /* MIC Capture buffer */
-#define EXTOUT_AC97_REAR_L 0x0d /* SB Live 5.1 (c) 2003 - Rear Left */
-#define EXTOUT_AC97_REAR_R 0x0e /* SB Live 5.1 (c) 2003 - Rear Right */
-#define EXTOUT_ACENTER 0x11 /* Analog Center */
-#define EXTOUT_ALFE 0x12 /* Analog LFE */
-
-/* Audigy Inputs */
-#define A_EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */
-#define A_EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */
-#define A_EXTIN_SPDIF_CD_L 0x02 /* digital CD left */
-#define A_EXTIN_SPDIF_CD_R 0x03 /* digital CD left */
-#define A_EXTIN_OPT_SPDIF_L 0x04 /* audigy drive Optical SPDIF - left */
-#define A_EXTIN_OPT_SPDIF_R 0x05 /* right */
-#define A_EXTIN_LINE2_L 0x08 /* audigy drive line2/mic2 - left */
-#define A_EXTIN_LINE2_R 0x09 /* right */
-#define A_EXTIN_ADC_L 0x0a /* Philips ADC - left */
-#define A_EXTIN_ADC_R 0x0b /* right */
-#define A_EXTIN_AUX2_L 0x0c /* audigy drive aux2 - left */
-#define A_EXTIN_AUX2_R 0x0d /* - right */
-
-/* Audigiy Outputs */
-#define A_EXTOUT_FRONT_L 0x00 /* digital front left */
-#define A_EXTOUT_FRONT_R 0x01 /* right */
-#define A_EXTOUT_CENTER 0x02 /* digital front center */
-#define A_EXTOUT_LFE 0x03 /* digital front lfe */
-#define A_EXTOUT_HEADPHONE_L 0x04 /* headphone audigy drive left */
-#define A_EXTOUT_HEADPHONE_R 0x05 /* right */
-#define A_EXTOUT_REAR_L 0x06 /* digital rear left */
-#define A_EXTOUT_REAR_R 0x07 /* right */
-#define A_EXTOUT_AFRONT_L 0x08 /* analog front left */
-#define A_EXTOUT_AFRONT_R 0x09 /* right */
-#define A_EXTOUT_ACENTER 0x0a /* analog center */
-#define A_EXTOUT_ALFE 0x0b /* analog LFE */
-#define A_EXTOUT_ASIDE_L 0x0c /* analog side left - Audigy 2 ZS */
-#define A_EXTOUT_ASIDE_R 0x0d /* right - Audigy 2 ZS */
-#define A_EXTOUT_AREAR_L 0x0e /* analog rear left */
-#define A_EXTOUT_AREAR_R 0x0f /* right */
-#define A_EXTOUT_AC97_L 0x10 /* AC97 left (front) */
-#define A_EXTOUT_AC97_R 0x11 /* right */
-#define A_EXTOUT_ADC_CAP_L 0x16 /* ADC capture buffer left */
-#define A_EXTOUT_ADC_CAP_R 0x17 /* right */
-#define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */
-
-/* Audigy constants */
-#define A_C_00000000 0xc0
-#define A_C_00000001 0xc1
-#define A_C_00000002 0xc2
-#define A_C_00000003 0xc3
-#define A_C_00000004 0xc4
-#define A_C_00000008 0xc5
-#define A_C_00000010 0xc6
-#define A_C_00000020 0xc7
-#define A_C_00000100 0xc8
-#define A_C_00010000 0xc9
-#define A_C_00000800 0xca
-#define A_C_10000000 0xcb
-#define A_C_20000000 0xcc
-#define A_C_40000000 0xcd
-#define A_C_80000000 0xce
-#define A_C_7fffffff 0xcf
-#define A_C_ffffffff 0xd0
-#define A_C_fffffffe 0xd1
-#define A_C_c0000000 0xd2
-#define A_C_4f1bbcdc 0xd3
-#define A_C_5a7ef9db 0xd4
-#define A_C_00100000 0xd5
-#define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */
-#define A_GPR_COND 0xd7 /* CCR, condition register */
-#define A_GPR_NOISE0 0xd8 /* noise source */
-#define A_GPR_NOISE1 0xd9 /* noise source */
-#define A_GPR_IRQ 0xda /* IRQ register */
-#define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */
-#define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */
-
-/* definitions for debug register */
-#define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */
-#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */
-#define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */
-#define EMU10K1_DBG_SINGLE_STEP 0x00008000 /* single step mode */
-#define EMU10K1_DBG_STEP 0x00004000 /* start single step */
-#define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */
-#define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */
-
-/* tank memory address line */
-#ifndef __KERNEL__
-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */
-#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */
-#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */
-#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */
-#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */
-#endif
-
-struct snd_emu10k1_fx8010_info {
- unsigned int internal_tram_size; /* in samples */
- unsigned int external_tram_size; /* in samples */
- char fxbus_names[16][32]; /* names of FXBUSes */
- char extin_names[16][32]; /* names of external inputs */
- char extout_names[32][32]; /* names of external outputs */
- unsigned int gpr_controls; /* count of GPR controls */
-};
-
-#define EMU10K1_GPR_TRANSLATION_NONE 0
-#define EMU10K1_GPR_TRANSLATION_TABLE100 1
-#define EMU10K1_GPR_TRANSLATION_BASS 2
-#define EMU10K1_GPR_TRANSLATION_TREBLE 3
-#define EMU10K1_GPR_TRANSLATION_ONOFF 4
-
-struct snd_emu10k1_fx8010_control_gpr {
- struct snd_ctl_elem_id id; /* full control ID definition */
- unsigned int vcount; /* visible count */
- unsigned int count; /* count of GPR (1..16) */
- unsigned short gpr[32]; /* GPR number(s) */
- unsigned int value[32]; /* initial values */
- unsigned int min; /* minimum range */
- unsigned int max; /* maximum range */
- unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */
- const unsigned int *tlv;
-};
-
-/* old ABI without TLV support */
-struct snd_emu10k1_fx8010_control_old_gpr {
- struct snd_ctl_elem_id id;
- unsigned int vcount;
- unsigned int count;
- unsigned short gpr[32];
- unsigned int value[32];
- unsigned int min;
- unsigned int max;
- unsigned int translation;
-};
-
-struct snd_emu10k1_fx8010_code {
- char name[128];
-
- __EMU10K1_DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
- __u32 __user *gpr_map; /* initializers */
-
- unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
- struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
-
- unsigned int gpr_del_control_count; /* count of GPR controls to remove */
- struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
-
- unsigned int gpr_list_control_count; /* count of GPR controls to list */
- unsigned int gpr_list_control_total; /* total count of GPR controls */
- struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
-
- __EMU10K1_DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
- __u32 __user *tram_data_map; /* data initializers */
- __u32 __user *tram_addr_map; /* map initializers */
-
- __EMU10K1_DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
- __u32 __user *code; /* one instruction - 64 bits */
-};
-
-struct snd_emu10k1_fx8010_tram {
- unsigned int address; /* 31.bit == 1 -> external TRAM */
- unsigned int size; /* size in samples (4 bytes) */
- unsigned int *samples; /* pointer to samples (20-bit) */
- /* NULL->clear memory */
-};
-
-struct snd_emu10k1_fx8010_pcm_rec {
- unsigned int substream; /* substream number */
- unsigned int res1; /* reserved */
- unsigned int channels; /* 16-bit channels count, zero = remove this substream */
- unsigned int tram_start; /* ring buffer position in TRAM (in samples) */
- unsigned int buffer_size; /* count of buffered samples */
- unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */
- unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
- unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */
- unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */
- unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */
- unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */
- unsigned char pad; /* reserved */
- unsigned char etram[32]; /* external TRAM address & data (one per channel) */
- unsigned int res2; /* reserved */
-};
-
-#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
-#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
-#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int)
-#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80)
-#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81)
-#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
-#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int)
-#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int)
-
-/* typedefs for compatibility to user-space */
-typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
-typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
-typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
-typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
-typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
-
-#endif /* _UAPI__SOUND_EMU10K1_H */
+#include <alsa/sound/type_compat.h>
+#include <alsa/sound/uapi/emu10k1.h>
diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h
index 5dc0c3db..78fb745b 100644
--- a/include/sound/hdsp.h
+++ b/include/sound/hdsp.h
@@ -1,111 +1,2 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-#ifndef __SOUND_HDSP_H
-#define __SOUND_HDSP_H
-
-/*
- * Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-
-#define HDSP_MATRIX_MIXER_SIZE 2048
-
-enum HDSP_IO_Type {
- Digiface,
- Multiface,
- H9652,
- H9632,
- RPM,
- Undefined,
-};
-
-struct hdsp_peak_rms {
- __u32 input_peaks[26];
- __u32 playback_peaks[26];
- __u32 output_peaks[28];
- __u64 input_rms[26];
- __u64 playback_rms[26];
- /* These are only used for H96xx cards */
- __u64 output_rms[26];
-};
-
-#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
-
-struct hdsp_config_info {
- unsigned char pref_sync_ref;
- unsigned char wordclock_sync_check;
- unsigned char spdif_sync_check;
- unsigned char adatsync_sync_check;
- unsigned char adat_sync_check[3];
- unsigned char spdif_in;
- unsigned char spdif_out;
- unsigned char spdif_professional;
- unsigned char spdif_emphasis;
- unsigned char spdif_nonaudio;
- unsigned int spdif_sample_rate;
- unsigned int system_sample_rate;
- unsigned int autosync_sample_rate;
- unsigned char system_clock_mode;
- unsigned char clock_source;
- unsigned char autosync_ref;
- unsigned char line_out;
- unsigned char passthru;
- unsigned char da_gain;
- unsigned char ad_gain;
- unsigned char phone_gain;
- unsigned char xlr_breakout_cable;
- unsigned char analog_extension_board;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
-
-struct hdsp_firmware {
- void __user *firmware_data; /* 24413 x 4 bytes */
-};
-
-#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
-
-struct hdsp_version {
- enum HDSP_IO_Type io_type;
- unsigned short firmware_rev;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version)
-
-struct hdsp_mixer {
- unsigned short matrix[HDSP_MATRIX_MIXER_SIZE];
-};
-
-#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer)
-
-struct hdsp_9632_aeb {
- int aebi;
- int aebo;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
-
-/* typedefs for compatibility to user-space */
-typedef enum HDSP_IO_Type HDSP_IO_Type;
-typedef struct hdsp_peak_rms hdsp_peak_rms_t;
-typedef struct hdsp_config_info hdsp_config_info_t;
-typedef struct hdsp_firmware hdsp_firmware_t;
-typedef struct hdsp_version hdsp_version_t;
-typedef struct hdsp_mixer hdsp_mixer_t;
-typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
-
-#endif /* __SOUND_HDSP_H */
+#include <alsa/sound/type_compat.h>
+#include <alsa/sound/uapi/hdsp.h>
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
index a38f3f79..af6d19ed 100644
--- a/include/sound/hdspm.h
+++ b/include/sound/hdspm.h
@@ -1,232 +1,2 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-#ifndef __SOUND_HDSPM_H
-#define __SOUND_HDSPM_H
-/*
- * Copyright (C) 2003 Winfried Ritsch (IEM)
- * based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-
-/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
-#define HDSPM_MAX_CHANNELS 64
-
-enum hdspm_io_type {
- MADI,
- MADIface,
- AIO,
- AES32,
- RayDAT
-};
-
-enum hdspm_speed {
- ss,
- ds,
- qs
-};
-
-/* -------------------- IOCTL Peak/RMS Meters -------------------- */
-
-struct hdspm_peak_rms {
- __u32 input_peaks[64];
- __u32 playback_peaks[64];
- __u32 output_peaks[64];
-
- __u64 input_rms[64];
- __u64 playback_rms[64];
- __u64 output_rms[64];
-
- __u8 speed; /* enum {ss, ds, qs} */
- int status2;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
- _IOR('H', 0x42, struct hdspm_peak_rms)
-
-/* ------------ CONFIG block IOCTL ---------------------- */
-
-struct hdspm_config {
- unsigned char pref_sync_ref;
- unsigned char wordclock_sync_check;
- unsigned char madi_sync_check;
- unsigned int system_sample_rate;
- unsigned int autosync_sample_rate;
- unsigned char system_clock_mode;
- unsigned char clock_source;
- unsigned char autosync_ref;
- unsigned char line_out;
- unsigned int passthru;
- unsigned int analog_out;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_CONFIG \
- _IOR('H', 0x41, struct hdspm_config)
-
-/*
- * If there's a TCO (TimeCode Option) board installed,
- * there are further options and status data available.
- * The hdspm_ltc structure contains the current SMPTE
- * timecode and some status information and can be
- * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the
- * hdspm_status struct.
- */
-
-enum hdspm_ltc_format {
- format_invalid,
- fps_24,
- fps_25,
- fps_2997,
- fps_30
-};
-
-enum hdspm_ltc_frame {
- frame_invalid,
- drop_frame,
- full_frame
-};
-
-enum hdspm_ltc_input_format {
- ntsc,
- pal,
- no_video
-};
-
-struct hdspm_ltc {
- unsigned int ltc;
-
- enum hdspm_ltc_format format;
- enum hdspm_ltc_frame frame;
- enum hdspm_ltc_input_format input_format;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_ltc)
-
-/*
- * The status data reflects the device's current state
- * as determined by the card's configuration and
- * connection status.
- */
-
-enum hdspm_sync {
- hdspm_sync_no_lock = 0,
- hdspm_sync_lock = 1,
- hdspm_sync_sync = 2
-};
-
-enum hdspm_madi_input {
- hdspm_input_optical = 0,
- hdspm_input_coax = 1
-};
-
-enum hdspm_madi_channel_format {
- hdspm_format_ch_64 = 0,
- hdspm_format_ch_56 = 1
-};
-
-enum hdspm_madi_frame_format {
- hdspm_frame_48 = 0,
- hdspm_frame_96 = 1
-};
-
-enum hdspm_syncsource {
- syncsource_wc = 0,
- syncsource_madi = 1,
- syncsource_tco = 2,
- syncsource_sync = 3,
- syncsource_none = 4
-};
-
-struct hdspm_status {
- __u8 card_type; /* enum hdspm_io_type */
- enum hdspm_syncsource autosync_source;
-
- __u64 card_clock;
- __u32 master_period;
-
- union {
- struct {
- __u8 sync_wc; /* enum hdspm_sync */
- __u8 sync_madi; /* enum hdspm_sync */
- __u8 sync_tco; /* enum hdspm_sync */
- __u8 sync_in; /* enum hdspm_sync */
- __u8 madi_input; /* enum hdspm_madi_input */
- __u8 channel_format; /* enum hdspm_madi_channel_format */
- __u8 frame_format; /* enum hdspm_madi_frame_format */
- } madi;
- } card_specific;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_STATUS \
- _IOR('H', 0x47, struct hdspm_status)
-
-/*
- * Get information about the card and its add-ons.
- */
-
-#define HDSPM_ADDON_TCO 1
-
-struct hdspm_version {
- __u8 card_type; /* enum hdspm_io_type */
- char cardname[20];
- unsigned int serial;
- unsigned short firmware_rev;
- int addons;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version)
-
-/* ------------- get Matrix Mixer IOCTL --------------- */
-
-/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte =
- * 32768 Bytes
- */
-
-/* organisation is 64 channelfader in a continuous memory block */
-/* equivalent to hardware definition, maybe for future feature of mmap of
- * them
- */
-/* each of 64 outputs has 64 infader and 64 outfader:
- Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
-
-#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
-
-struct hdspm_channelfader {
- unsigned int in[HDSPM_MIXER_CHANNELS];
- unsigned int pb[HDSPM_MIXER_CHANNELS];
-};
-
-struct hdspm_mixer {
- struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS];
-};
-
-struct hdspm_mixer_ioctl {
- struct hdspm_mixer *mixer;
-};
-
-/* use indirect access due to the limit of ioctl bit size */
-#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
-
-/* typedefs for compatibility to user-space */
-typedef struct hdspm_peak_rms hdspm_peak_rms_t;
-typedef struct hdspm_config_info hdspm_config_info_t;
-typedef struct hdspm_version hdspm_version_t;
-typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
-typedef struct hdspm_mixer hdspm_mixer_t;
-
-
-#endif
+#include <alsa/sound/type_compat.h>
+#include <alsa/sound/uapi/hdspm.h>
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
index e6485148..24121fcb 100644
--- a/include/sound/sb16_csp.h
+++ b/include/sound/sb16_csp.h
@@ -1,123 +1 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/*
- * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
- * Takashi Iwai <tiwai@suse.de>
- *
- * SB16ASP/AWE32 CSP control
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef _UAPI__SOUND_SB16_CSP_H
-#define _UAPI__SOUND_SB16_CSP_H
-
-
-/* CSP modes */
-#define SNDRV_SB_CSP_MODE_NONE 0x00
-#define SNDRV_SB_CSP_MODE_DSP_READ 0x01 /* Record from DSP */
-#define SNDRV_SB_CSP_MODE_DSP_WRITE 0x02 /* Play to DSP */
-#define SNDRV_SB_CSP_MODE_QSOUND 0x04 /* QSound */
-
-/* CSP load flags */
-#define SNDRV_SB_CSP_LOAD_FROMUSER 0x01
-#define SNDRV_SB_CSP_LOAD_INITBLOCK 0x02
-
-/* CSP sample width */
-#define SNDRV_SB_CSP_SAMPLE_8BIT 0x01
-#define SNDRV_SB_CSP_SAMPLE_16BIT 0x02
-
-/* CSP channels */
-#define SNDRV_SB_CSP_MONO 0x01
-#define SNDRV_SB_CSP_STEREO 0x02
-
-/* CSP rates */
-#define SNDRV_SB_CSP_RATE_8000 0x01
-#define SNDRV_SB_CSP_RATE_11025 0x02
-#define SNDRV_SB_CSP_RATE_22050 0x04
-#define SNDRV_SB_CSP_RATE_44100 0x08
-#define SNDRV_SB_CSP_RATE_ALL 0x0f
-
-/* CSP running state */
-#define SNDRV_SB_CSP_ST_IDLE 0x00
-#define SNDRV_SB_CSP_ST_LOADED 0x01
-#define SNDRV_SB_CSP_ST_RUNNING 0x02
-#define SNDRV_SB_CSP_ST_PAUSED 0x04
-#define SNDRV_SB_CSP_ST_AUTO 0x08
-#define SNDRV_SB_CSP_ST_QSOUND 0x10
-
-/* maximum QSound value (180 degrees right) */
-#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT 0x20
-
-/* maximum microcode RIFF file size */
-#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000
-
-/* microcode header */
-struct snd_sb_csp_mc_header {
- char codec_name[16]; /* id name of codec */
- unsigned short func_req; /* requested function */
-};
-
-/* microcode to be loaded */
-struct snd_sb_csp_microcode {
- struct snd_sb_csp_mc_header info;
- unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
-};
-
-/* start CSP with sample_width in mono/stereo */
-struct snd_sb_csp_start {
- int sample_width; /* sample width, look above */
- int channels; /* channels, look above */
-};
-
-/* CSP information */
-struct snd_sb_csp_info {
- char codec_name[16]; /* id name of codec */
- unsigned short func_nr; /* function number */
- unsigned int acc_format; /* accepted PCM formats */
- unsigned short acc_channels; /* accepted channels */
- unsigned short acc_width; /* accepted sample width */
- unsigned short acc_rates; /* accepted sample rates */
- unsigned short csp_mode; /* CSP mode, see above */
- unsigned short run_channels; /* current channels */
- unsigned short run_width; /* current sample width */
- unsigned short version; /* version id: 0x10 - 0x1f */
- unsigned short state; /* state bits */
-};
-
-/* HWDEP controls */
-/* get CSP information */
-#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info)
-/* load microcode to CSP */
-/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
- * defined for some architectures like MIPS, and it leads to build errors.
- * (x86 and co have 14-bit size, thus it's valid, though.)
- * As a workaround for skipping the size-limit check, here we don't use the
- * normal _IOW() macro but _IOC() with the manual argument.
- */
-#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \
- _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
-/* unload microcode from CSP */
-#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
-/* start CSP */
-#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start)
-/* stop CSP */
-#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14)
-/* pause CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15)
-/* restart CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16)
-
-
-#endif /* _UAPI__SOUND_SB16_CSP_H */
+#include <alsa/sound/uapi/sb16_csp.h>
diff --git a/include/sound/sscape_ioctl.h b/include/sound/sscape_ioctl.h
index c6653ebf..23b48d33 100644
--- a/include/sound/sscape_ioctl.h
+++ b/include/sound/sscape_ioctl.h
@@ -1,21 +1 @@
-#ifndef SSCAPE_IOCTL_H
-#define SSCAPE_IOCTL_H
-
-
-struct sscape_bootblock
-{
- unsigned char code[256];
- unsigned version;
-};
-
-#define SSCAPE_MICROCODE_SIZE 65536
-
-struct sscape_microcode
-{
- unsigned char *code;
-};
-
-#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock)
-#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode)
-
-#endif
+#include <alsa/sound/uapi/sscape_ioctl.h>
diff --git a/include/sound/tlv.h b/include/sound/tlv.h
index 7d6d65f6..e435a5fc 100644
--- a/include/sound/tlv.h
+++ b/include/sound/tlv.h
@@ -1,117 +1 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __UAPI_SOUND_TLV_H
-#define __UAPI_SOUND_TLV_H
-
-#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */
-#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
-#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */
-#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */
-#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */
-#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */
-
-/*
- * channel-mapping TLV items
- * TLV length must match with num_channels
- */
-#define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */
-#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */
-#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */
-
-/*
- * TLV structure is right behind the struct snd_ctl_tlv:
- * unsigned int type - see SNDRV_CTL_TLVT_*
- * unsigned int length
- * .... data aligned to sizeof(unsigned int), use
- * block_length = (length + (sizeof(unsigned int) - 1)) &
- * ~(sizeof(unsigned int) - 1)) ....
- */
-#define SNDRV_CTL_TLVD_ITEM(type, ...) \
- (type), SNDRV_CTL_TLVD_LENGTH(__VA_ARGS__), __VA_ARGS__
-#define SNDRV_CTL_TLVD_LENGTH(...) \
- ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
-
-/* Accessor offsets for TLV data items */
-#define SNDRV_CTL_TLVO_TYPE 0
-#define SNDRV_CTL_TLVO_LEN 1
-
-#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \
- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)
-#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \
- unsigned int name[] = { \
- SNDRV_CTL_TLVD_CONTAINER_ITEM(__VA_ARGS__) \
- }
-
-#define SNDRV_CTL_TLVD_DB_SCALE_MASK 0xffff
-#define SNDRV_CTL_TLVD_DB_SCALE_MUTE 0x10000
-#define SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \
- (min), \
- ((step) & SNDRV_CTL_TLVD_DB_SCALE_MASK) | \
- ((mute) ? SNDRV_CTL_TLVD_DB_SCALE_MUTE : 0))
-#define SNDRV_CTL_TLVD_DECLARE_DB_SCALE(name, min, step, mute) \
- unsigned int name[] = { \
- SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
- }
-
-/* Accessor offsets for min, mute and step items in dB scale type TLV */
-#define SNDRV_CTL_TLVO_DB_SCALE_MIN 2
-#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 3
-
-/* dB scale specified with min/max values instead of step */
-#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))
-#define SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB))
-#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(name, min_dB, max_dB) \
- unsigned int name[] = { \
- SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
- }
-#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE(name, min_dB, max_dB) \
- unsigned int name[] = { \
- SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
- }
-
-/* Accessor offsets for min, max items in db-minmax types of TLV. */
-#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 2
-#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 3
-
-/* linear volume between min_dB and max_dB (.01dB unit) */
-#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))
-#define SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(name, min_dB, max_dB) \
- unsigned int name[] = { \
- SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
- }
-
-/* Accessor offsets for min, max items in db-linear type of TLV. */
-#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 2
-#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 3
-
-/* dB range container:
- * Items in dB range container must be ordered by their values and by their
- * dB values. This implies that larger values must correspond with larger
- * dB values (which is also required for all other mixer controls).
- */
-/* Each item is: <min> <max> <TLV> */
-#define SNDRV_CTL_TLVD_DB_RANGE_ITEM(...) \
- SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__)
-#define SNDRV_CTL_TLVD_DECLARE_DB_RANGE(name, ...) \
- unsigned int name[] = { \
- SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) \
- }
-
-#define SNDRV_CTL_TLVD_DB_GAIN_MUTE -9999999
-
-#endif
+#include <alsa/sound/uapi/tlv.h>
diff --git a/include/sound/type_compat.h b/include/sound/type_compat.h
index e973ff31..d4790c1f 100644
--- a/include/sound/type_compat.h
+++ b/include/sound/type_compat.h
@@ -3,6 +3,9 @@
#ifndef DOC_HIDDEN
#include <stdint.h>
+#ifdef __linux__
+#include <linux/types.h>
+#else
typedef uint8_t __u8;
typedef uint16_t __u16;
typedef uint32_t __u32;
@@ -37,6 +40,16 @@ typedef int32_t __s32;
#define __be32 __u32
#define __be16 __u16
#define __be8 __u8
+#endif
+
+#ifndef __user
+#define __user
+#endif
+
+#ifndef __packed
+#define __packed __attribute__((__packed__))
+#endif
+
#endif /* DOC_HIDDEN */
#endif /* __TYPE_COMPAT_H */
diff --git a/include/sound/uapi/Makefile.am b/include/sound/uapi/Makefile.am
new file mode 100644
index 00000000..99197108
--- /dev/null
+++ b/include/sound/uapi/Makefile.am
@@ -0,0 +1,6 @@
+alsasounduapiincludedir = ${includedir}/alsa/sound/uapi
+
+alsasounduapiinclude_HEADERS = asound_fm.h hdsp.h hdspm.h sb16_csp.h \
+ sscape_ioctl.h emu10k1.h asoc.h tlv.h
+
+noinst_HEADERS = asound.h asequencer.h
diff --git a/include/sound/uapi/asequencer.h b/include/sound/uapi/asequencer.h
new file mode 100644
index 00000000..a75e14ed
--- /dev/null
+++ b/include/sound/uapi/asequencer.h
@@ -0,0 +1,612 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Main header file for the ALSA sequencer
+ * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
+ * (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_ASEQUENCER_H
+#define _UAPI__SOUND_ASEQUENCER_H
+
+#include <sound/asound.h>
+
+/** version of the sequencer */
+#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 2)
+
+/**
+ * definition of sequencer event types
+ */
+
+/** system messages
+ * event data type = #snd_seq_result
+ */
+#define SNDRV_SEQ_EVENT_SYSTEM 0
+#define SNDRV_SEQ_EVENT_RESULT 1
+
+/** note messages (channel specific)
+ * event data type = #snd_seq_ev_note
+ */
+#define SNDRV_SEQ_EVENT_NOTE 5
+#define SNDRV_SEQ_EVENT_NOTEON 6
+#define SNDRV_SEQ_EVENT_NOTEOFF 7
+#define SNDRV_SEQ_EVENT_KEYPRESS 8
+
+/** control messages (channel specific)
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_CONTROLLER 10
+#define SNDRV_SEQ_EVENT_PGMCHANGE 11
+#define SNDRV_SEQ_EVENT_CHANPRESS 12
+#define SNDRV_SEQ_EVENT_PITCHBEND 13 /**< from -8192 to 8191 */
+#define SNDRV_SEQ_EVENT_CONTROL14 14 /**< 14 bit controller value */
+#define SNDRV_SEQ_EVENT_NONREGPARAM 15 /**< 14 bit NRPN address + 14 bit unsigned value */
+#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */
+
+/** synchronisation messages
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */
+#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */
+#define SNDRV_SEQ_EVENT_QFRAME 22 /* midi time code quarter frame */
+#define SNDRV_SEQ_EVENT_TIMESIGN 23 /* SMF Time Signature event */
+#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */
+
+/** timer messages
+ * event data type = snd_seq_ev_queue_control
+ */
+#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */
+#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */
+#define SNDRV_SEQ_EVENT_STOP 32 /* midi Real Time Stop message */
+#define SNDRV_SEQ_EVENT_SETPOS_TICK 33 /* set tick queue position */
+#define SNDRV_SEQ_EVENT_SETPOS_TIME 34 /* set realtime queue position */
+#define SNDRV_SEQ_EVENT_TEMPO 35 /* (SMF) Tempo event */
+#define SNDRV_SEQ_EVENT_CLOCK 36 /* midi Real Time Clock message */
+#define SNDRV_SEQ_EVENT_TICK 37 /* midi Real Time Tick message */
+#define SNDRV_SEQ_EVENT_QUEUE_SKEW 38 /* skew queue tempo */
+
+/** others
+ * event data type = none
+ */
+#define SNDRV_SEQ_EVENT_TUNE_REQUEST 40 /* tune request */
+#define SNDRV_SEQ_EVENT_RESET 41 /* reset to power-on state */
+#define SNDRV_SEQ_EVENT_SENSING 42 /* "active sensing" event */
+
+/** echo back, kernel private messages
+ * event data type = any type
+ */
+#define SNDRV_SEQ_EVENT_ECHO 50 /* echo event */
+#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */
+
+/** system status messages (broadcast for subscribers)
+ * event data type = snd_seq_addr
+ */
+#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */
+#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */
+#define SNDRV_SEQ_EVENT_CLIENT_CHANGE 62 /* client status/info has changed */
+#define SNDRV_SEQ_EVENT_PORT_START 63 /* new port was created */
+#define SNDRV_SEQ_EVENT_PORT_EXIT 64 /* port was deleted from system */
+#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */
+
+/** port connection changes
+ * event data type = snd_seq_connect
+ */
+#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */
+#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */
+
+/* 70-89: synthesizer events - obsoleted */
+
+/** user-defined events with fixed length
+ * event data type = any
+ */
+#define SNDRV_SEQ_EVENT_USR0 90
+#define SNDRV_SEQ_EVENT_USR1 91
+#define SNDRV_SEQ_EVENT_USR2 92
+#define SNDRV_SEQ_EVENT_USR3 93
+#define SNDRV_SEQ_EVENT_USR4 94
+#define SNDRV_SEQ_EVENT_USR5 95
+#define SNDRV_SEQ_EVENT_USR6 96
+#define SNDRV_SEQ_EVENT_USR7 97
+#define SNDRV_SEQ_EVENT_USR8 98
+#define SNDRV_SEQ_EVENT_USR9 99
+
+/* 100-118: instrument layer - obsoleted */
+/* 119-129: reserved */
+
+/* 130-139: variable length events
+ * event data type = snd_seq_ev_ext
+ * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
+ */
+#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */
+#define SNDRV_SEQ_EVENT_BOUNCE 131 /* error event */
+/* 132-134: reserved */
+#define SNDRV_SEQ_EVENT_USR_VAR0 135
+#define SNDRV_SEQ_EVENT_USR_VAR1 136
+#define SNDRV_SEQ_EVENT_USR_VAR2 137
+#define SNDRV_SEQ_EVENT_USR_VAR3 138
+#define SNDRV_SEQ_EVENT_USR_VAR4 139
+
+/* 150-151: kernel events with quote - DO NOT use in user clients */
+#define SNDRV_SEQ_EVENT_KERNEL_ERROR 150
+#define SNDRV_SEQ_EVENT_KERNEL_QUOTE 151 /* obsolete */
+
+/* 152-191: reserved */
+
+/* 192-254: hardware specific events */
+
+/* 255: special event */
+#define SNDRV_SEQ_EVENT_NONE 255
+
+
+typedef unsigned char snd_seq_event_type_t;
+
+/** event address */
+struct snd_seq_addr {
+ unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */
+ unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */
+};
+
+/** port connection */
+struct snd_seq_connect {
+ struct snd_seq_addr sender;
+ struct snd_seq_addr dest;
+};
+
+
+#define SNDRV_SEQ_ADDRESS_UNKNOWN 253 /* unknown source */
+#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS 254 /* send event to all subscribed ports */
+#define SNDRV_SEQ_ADDRESS_BROADCAST 255 /* send event to all queues/clients/ports/channels */
+#define SNDRV_SEQ_QUEUE_DIRECT 253 /* direct dispatch */
+
+ /* event mode flag - NOTE: only 8 bits available! */
+#define SNDRV_SEQ_TIME_STAMP_TICK (0<<0) /* timestamp in clock ticks */
+#define SNDRV_SEQ_TIME_STAMP_REAL (1<<0) /* timestamp in real time */
+#define SNDRV_SEQ_TIME_STAMP_MASK (1<<0)
+
+#define SNDRV_SEQ_TIME_MODE_ABS (0<<1) /* absolute timestamp */
+#define SNDRV_SEQ_TIME_MODE_REL (1<<1) /* relative to current time */
+#define SNDRV_SEQ_TIME_MODE_MASK (1<<1)
+
+#define SNDRV_SEQ_EVENT_LENGTH_FIXED (0<<2) /* fixed event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /* variable event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARUSR (2<<2) /* variable event size - user memory space */
+#define SNDRV_SEQ_EVENT_LENGTH_MASK (3<<2)
+
+#define SNDRV_SEQ_PRIORITY_NORMAL (0<<4) /* normal priority */
+#define SNDRV_SEQ_PRIORITY_HIGH (1<<4) /* event should be processed before others */
+#define SNDRV_SEQ_PRIORITY_MASK (1<<4)
+
+
+ /* note event */
+struct snd_seq_ev_note {
+ unsigned char channel;
+ unsigned char note;
+ unsigned char velocity;
+ unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */
+ unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */
+};
+
+ /* controller event */
+struct snd_seq_ev_ctrl {
+ unsigned char channel;
+ unsigned char unused1, unused2, unused3; /* pad */
+ unsigned int param;
+ signed int value;
+};
+
+ /* generic set of bytes (12x8 bit) */
+struct snd_seq_ev_raw8 {
+ unsigned char d[12]; /* 8 bit value */
+};
+
+ /* generic set of integers (3x32 bit) */
+struct snd_seq_ev_raw32 {
+ unsigned int d[3]; /* 32 bit value */
+};
+
+ /* external stored data */
+struct snd_seq_ev_ext {
+ unsigned int len; /* length of data */
+ void *ptr; /* pointer to data (note: maybe 64-bit) */
+} __attribute__((packed));
+
+struct snd_seq_result {
+ int event; /* processed event type */
+ int result;
+};
+
+
+struct snd_seq_real_time {
+ unsigned int tv_sec; /* seconds */
+ unsigned int tv_nsec; /* nanoseconds */
+};
+
+typedef unsigned int snd_seq_tick_time_t; /* midi ticks */
+
+union snd_seq_timestamp {
+ snd_seq_tick_time_t tick;
+ struct snd_seq_real_time time;
+};
+
+struct snd_seq_queue_skew {
+ unsigned int value;
+ unsigned int base;
+};
+
+ /* queue timer control */
+struct snd_seq_ev_queue_control {
+ unsigned char queue; /* affected queue */
+ unsigned char pad[3]; /* reserved */
+ union {
+ signed int value; /* affected value (e.g. tempo) */
+ union snd_seq_timestamp time; /* time */
+ unsigned int position; /* sync position */
+ struct snd_seq_queue_skew skew;
+ unsigned int d32[2];
+ unsigned char d8[8];
+ } param;
+};
+
+ /* quoted event - inside the kernel only */
+struct snd_seq_ev_quote {
+ struct snd_seq_addr origin; /* original sender */
+ unsigned short value; /* optional data */
+ struct snd_seq_event *event; /* quoted event */
+} __attribute__((packed));
+
+
+ /* sequencer event */
+struct snd_seq_event {
+ snd_seq_event_type_t type; /* event type */
+ unsigned char flags; /* event flags */
+ char tag;
+
+ unsigned char queue; /* schedule queue */
+ union snd_seq_timestamp time; /* schedule time */
+
+
+ struct snd_seq_addr source; /* source address */
+ struct snd_seq_addr dest; /* destination address */
+
+ union { /* event data... */
+ struct snd_seq_ev_note note;
+ struct snd_seq_ev_ctrl control;
+ struct snd_seq_ev_raw8 raw8;
+ struct snd_seq_ev_raw32 raw32;
+ struct snd_seq_ev_ext ext;
+ struct snd_seq_ev_queue_control queue;
+ union snd_seq_timestamp time;
+ struct snd_seq_addr addr;
+ struct snd_seq_connect connect;
+ struct snd_seq_result result;
+ struct snd_seq_ev_quote quote;
+ } data;
+};
+
+
+/*
+ * bounce event - stored as variable size data
+ */
+struct snd_seq_event_bounce {
+ int err;
+ struct snd_seq_event event;
+ /* external data follows here. */
+};
+
+
+ /* system information */
+struct snd_seq_system_info {
+ int queues; /* maximum queues count */
+ int clients; /* maximum clients count */
+ int ports; /* maximum ports per client */
+ int channels; /* maximum channels per port */
+ int cur_clients; /* current clients */
+ int cur_queues; /* current queues */
+ char reserved[24];
+};
+
+
+ /* system running information */
+struct snd_seq_running_info {
+ unsigned char client; /* client id */
+ unsigned char big_endian; /* 1 = big-endian */
+ unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */
+ unsigned char pad; /* reserved */
+ unsigned char reserved[12];
+};
+
+
+ /* known client numbers */
+#define SNDRV_SEQ_CLIENT_SYSTEM 0
+ /* internal client numbers */
+#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */
+#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */
+
+
+ /* client types */
+typedef int __bitwise snd_seq_client_type_t;
+#define NO_CLIENT ((__force snd_seq_client_type_t) 0)
+#define USER_CLIENT ((__force snd_seq_client_type_t) 1)
+#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2)
+
+ /* event filter flags */
+#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */
+#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */
+#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */
+#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */
+
+struct snd_seq_client_info {
+ int client; /* client number to inquire */
+ snd_seq_client_type_t type; /* client type */
+ char name[64]; /* client name */
+ unsigned int filter; /* filter flags */
+ unsigned char multicast_filter[8]; /* multicast filter bitmap */
+ unsigned char event_filter[32]; /* event filter bitmap */
+ int num_ports; /* RO: number of ports */
+ int event_lost; /* number of lost events */
+ int card; /* RO: card number[kernel] */
+ int pid; /* RO: pid[user] */
+ char reserved[56]; /* for future use */
+};
+
+
+/* client pool size */
+struct snd_seq_client_pool {
+ int client; /* client number to inquire */
+ int output_pool; /* outgoing (write) pool size */
+ int input_pool; /* incoming (read) pool size */
+ int output_room; /* minimum free pool size for select/blocking mode */
+ int output_free; /* unused size */
+ int input_free; /* unused size */
+ char reserved[64];
+};
+
+
+/* Remove events by specified criteria */
+
+#define SNDRV_SEQ_REMOVE_INPUT (1<<0) /* Flush input queues */
+#define SNDRV_SEQ_REMOVE_OUTPUT (1<<1) /* Flush output queues */
+#define SNDRV_SEQ_REMOVE_DEST (1<<2) /* Restrict by destination q:client:port */
+#define SNDRV_SEQ_REMOVE_DEST_CHANNEL (1<<3) /* Restrict by channel */
+#define SNDRV_SEQ_REMOVE_TIME_BEFORE (1<<4) /* Restrict to before time */
+#define SNDRV_SEQ_REMOVE_TIME_AFTER (1<<5) /* Restrict to time or after */
+#define SNDRV_SEQ_REMOVE_TIME_TICK (1<<6) /* Time is in ticks */
+#define SNDRV_SEQ_REMOVE_EVENT_TYPE (1<<7) /* Restrict to event type */
+#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */
+#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */
+
+struct snd_seq_remove_events {
+ unsigned int remove_mode; /* Flags that determine what gets removed */
+
+ union snd_seq_timestamp time;
+
+ unsigned char queue; /* Queue for REMOVE_DEST */
+ struct snd_seq_addr dest; /* Address for REMOVE_DEST */
+ unsigned char channel; /* Channel for REMOVE_DEST */
+
+ int type; /* For REMOVE_EVENT_TYPE */
+ char tag; /* Tag for REMOVE_TAG */
+
+ int reserved[10]; /* To allow for future binary compatibility */
+
+};
+
+
+ /* known port numbers */
+#define SNDRV_SEQ_PORT_SYSTEM_TIMER 0
+#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE 1
+
+ /* port capabilities (32 bits) */
+#define SNDRV_SEQ_PORT_CAP_READ (1<<0) /* readable from this port */
+#define SNDRV_SEQ_PORT_CAP_WRITE (1<<1) /* writable to this port */
+
+#define SNDRV_SEQ_PORT_CAP_SYNC_READ (1<<2)
+#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE (1<<3)
+
+#define SNDRV_SEQ_PORT_CAP_DUPLEX (1<<4)
+
+#define SNDRV_SEQ_PORT_CAP_SUBS_READ (1<<5) /* allow read subscription */
+#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */
+#define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */
+
+ /* port type */
+#define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /* generic MIDI device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM (1<<2) /* General MIDI compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GS (1<<3) /* GS compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_XG (1<<4) /* XG compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /* MT-32 compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2 (1<<6) /* General MIDI 2 compatible device */
+
+/* other standards...*/
+#define SNDRV_SEQ_PORT_TYPE_SYNTH (1<<10) /* Synth device (no MIDI compatible - direct wavetable) */
+#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */
+#define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */
+/*...*/
+#define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */
+#define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */
+#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */
+#define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */
+#define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */
+
+/* misc. conditioning flags */
+#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT (1<<0)
+#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1)
+#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2)
+
+struct snd_seq_port_info {
+ struct snd_seq_addr addr; /* client/port numbers */
+ char name[64]; /* port name */
+
+ unsigned int capability; /* port capability bits */
+ unsigned int type; /* port type bits */
+ int midi_channels; /* channels per MIDI port */
+ int midi_voices; /* voices per MIDI port */
+ int synth_voices; /* voices per SYNTH port */
+
+ int read_use; /* R/O: subscribers for output (from this port) */
+ int write_use; /* R/O: subscribers for input (to this port) */
+
+ void *kernel; /* reserved for kernel use (must be NULL) */
+ unsigned int flags; /* misc. conditioning */
+ unsigned char time_queue; /* queue # for timestamping */
+ char reserved[59]; /* for future use */
+};
+
+
+/* queue flags */
+#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */
+
+/* queue information */
+struct snd_seq_queue_info {
+ int queue; /* queue id */
+
+ /*
+ * security settings, only owner of this queue can start/stop timer
+ * etc. if the queue is locked for other clients
+ */
+ int owner; /* client id for owner of the queue */
+ unsigned locked:1; /* timing queue locked for other queues */
+ char name[64]; /* name of this queue */
+ unsigned int flags; /* flags */
+ char reserved[60]; /* for future use */
+
+};
+
+/* queue info/status */
+struct snd_seq_queue_status {
+ int queue; /* queue id */
+ int events; /* read-only - queue size */
+ snd_seq_tick_time_t tick; /* current tick */
+ struct snd_seq_real_time time; /* current time */
+ int running; /* running state of queue */
+ int flags; /* various flags */
+ char reserved[64]; /* for the future */
+};
+
+
+/* queue tempo */
+struct snd_seq_queue_tempo {
+ int queue; /* sequencer queue */
+ unsigned int tempo; /* current tempo, us/tick */
+ int ppq; /* time resolution, ticks/quarter */
+ unsigned int skew_value; /* queue skew */
+ unsigned int skew_base; /* queue skew base */
+ char reserved[24]; /* for the future */
+};
+
+
+/* sequencer timer sources */
+#define SNDRV_SEQ_TIMER_ALSA 0 /* ALSA timer */
+#define SNDRV_SEQ_TIMER_MIDI_CLOCK 1 /* Midi Clock (CLOCK event) */
+#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */
+
+/* queue timer info */
+struct snd_seq_queue_timer {
+ int queue; /* sequencer queue */
+ int type; /* source timer type */
+ union {
+ struct {
+ struct snd_timer_id id; /* ALSA's timer ID */
+ unsigned int resolution; /* resolution in Hz */
+ } alsa;
+ } u;
+ char reserved[64]; /* for the future use */
+};
+
+
+struct snd_seq_queue_client {
+ int queue; /* sequencer queue */
+ int client; /* sequencer client */
+ int used; /* queue is used with this client
+ (must be set for accepting events) */
+ /* per client watermarks */
+ char reserved[64]; /* for future use */
+};
+
+
+#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE (1<<0) /* exclusive connection */
+#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1)
+#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2)
+
+struct snd_seq_port_subscribe {
+ struct snd_seq_addr sender; /* sender address */
+ struct snd_seq_addr dest; /* destination address */
+ unsigned int voices; /* number of voices to be allocated (0 = don't care) */
+ unsigned int flags; /* modes */
+ unsigned char queue; /* input time-stamp queue (optional) */
+ unsigned char pad[3]; /* reserved */
+ char reserved[64];
+};
+
+/* type of query subscription */
+#define SNDRV_SEQ_QUERY_SUBS_READ 0
+#define SNDRV_SEQ_QUERY_SUBS_WRITE 1
+
+struct snd_seq_query_subs {
+ struct snd_seq_addr root; /* client/port id to be searched */
+ int type; /* READ or WRITE */
+ int index; /* 0..N-1 */
+ int num_subs; /* R/O: number of subscriptions on this port */
+ struct snd_seq_addr addr; /* R/O: result */
+ unsigned char queue; /* R/O: result */
+ unsigned int flags; /* R/O: result */
+ char reserved[64]; /* for future use */
+};
+
+
+/*
+ * IOCTL commands
+ */
+
+#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int)
+#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int)
+#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info)
+#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info)
+
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info)
+
+#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info)
+
+#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
+
+#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events)
+#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs)
+#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info)
+
+#endif /* _UAPI__SOUND_ASEQUENCER_H */
diff --git a/include/sound/uapi/asoc.h b/include/sound/uapi/asoc.h
new file mode 100644
index 00000000..a74ca232
--- /dev/null
+++ b/include/sound/uapi/asoc.h
@@ -0,0 +1,633 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * uapi/sound/asoc.h -- ALSA SoC Firmware Controls and DAPM
+ *
+ * Copyright (C) 2012 Texas Instruments Inc.
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simple file API to load FW that includes mixers, coefficients, DAPM graphs,
+ * algorithms, equalisers, DAIs, widgets etc.
+*/
+
+#ifndef __LINUX_UAPI_SND_ASOC_H
+#define __LINUX_UAPI_SND_ASOC_H
+
+#include <linux/types.h>
+#include <sound/asound.h>
+
+/*
+ * Maximum number of channels topology kcontrol can represent.
+ */
+#define SND_SOC_TPLG_MAX_CHAN 8
+
+/*
+ * Maximum number of PCM formats capability
+ */
+#define SND_SOC_TPLG_MAX_FORMATS 16
+
+/*
+ * Maximum number of PCM stream configs
+ */
+#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8
+
+/*
+ * Maximum number of physical link's hardware configs
+ */
+#define SND_SOC_TPLG_HW_CONFIG_MAX 8
+
+/* individual kcontrol info types - can be mixed with other types */
+#define SND_SOC_TPLG_CTL_VOLSW 1
+#define SND_SOC_TPLG_CTL_VOLSW_SX 2
+#define SND_SOC_TPLG_CTL_VOLSW_XR_SX 3
+#define SND_SOC_TPLG_CTL_ENUM 4
+#define SND_SOC_TPLG_CTL_BYTES 5
+#define SND_SOC_TPLG_CTL_ENUM_VALUE 6
+#define SND_SOC_TPLG_CTL_RANGE 7
+#define SND_SOC_TPLG_CTL_STROBE 8
+
+
+/* individual widget kcontrol info types - can be mixed with other types */
+#define SND_SOC_TPLG_DAPM_CTL_VOLSW 64
+#define SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE 65
+#define SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT 66
+#define SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE 67
+#define SND_SOC_TPLG_DAPM_CTL_PIN 68
+
+/* DAPM widget types - add new items to the end */
+#define SND_SOC_TPLG_DAPM_INPUT 0
+#define SND_SOC_TPLG_DAPM_OUTPUT 1
+#define SND_SOC_TPLG_DAPM_MUX 2
+#define SND_SOC_TPLG_DAPM_MIXER 3
+#define SND_SOC_TPLG_DAPM_PGA 4
+#define SND_SOC_TPLG_DAPM_OUT_DRV 5
+#define SND_SOC_TPLG_DAPM_ADC 6
+#define SND_SOC_TPLG_DAPM_DAC 7
+#define SND_SOC_TPLG_DAPM_SWITCH 8
+#define SND_SOC_TPLG_DAPM_PRE 9
+#define SND_SOC_TPLG_DAPM_POST 10
+#define SND_SOC_TPLG_DAPM_AIF_IN 11
+#define SND_SOC_TPLG_DAPM_AIF_OUT 12
+#define SND_SOC_TPLG_DAPM_DAI_IN 13
+#define SND_SOC_TPLG_DAPM_DAI_OUT 14
+#define SND_SOC_TPLG_DAPM_DAI_LINK 15
+#define SND_SOC_TPLG_DAPM_BUFFER 16
+#define SND_SOC_TPLG_DAPM_SCHEDULER 17
+#define SND_SOC_TPLG_DAPM_EFFECT 18
+#define SND_SOC_TPLG_DAPM_SIGGEN 19
+#define SND_SOC_TPLG_DAPM_SRC 20
+#define SND_SOC_TPLG_DAPM_ASRC 21
+#define SND_SOC_TPLG_DAPM_ENCODER 22
+#define SND_SOC_TPLG_DAPM_DECODER 23
+#define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DECODER
+
+/* Header magic number and string sizes */
+#define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */
+
+/* string sizes */
+#define SND_SOC_TPLG_NUM_TEXTS 16
+
+/* ABI version */
+#define SND_SOC_TPLG_ABI_VERSION 0x5 /* current version */
+#define SND_SOC_TPLG_ABI_VERSION_MIN 0x4 /* oldest version supported */
+
+/* Max size of TLV data */
+#define SND_SOC_TPLG_TLV_SIZE 32
+
+/*
+ * File and Block header data types.
+ * Add new generic and vendor types to end of list.
+ * Generic types are handled by the core whilst vendors types are passed
+ * to the component drivers for handling.
+ */
+#define SND_SOC_TPLG_TYPE_MIXER 1
+#define SND_SOC_TPLG_TYPE_BYTES 2
+#define SND_SOC_TPLG_TYPE_ENUM 3
+#define SND_SOC_TPLG_TYPE_DAPM_GRAPH 4
+#define SND_SOC_TPLG_TYPE_DAPM_WIDGET 5
+#define SND_SOC_TPLG_TYPE_DAI_LINK 6
+#define SND_SOC_TPLG_TYPE_PCM 7
+#define SND_SOC_TPLG_TYPE_MANIFEST 8
+#define SND_SOC_TPLG_TYPE_CODEC_LINK 9
+#define SND_SOC_TPLG_TYPE_BACKEND_LINK 10
+#define SND_SOC_TPLG_TYPE_PDATA 11
+#define SND_SOC_TPLG_TYPE_DAI 12
+#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_DAI
+
+/* vendor block IDs - please add new vendor types to end */
+#define SND_SOC_TPLG_TYPE_VENDOR_FW 1000
+#define SND_SOC_TPLG_TYPE_VENDOR_CONFIG 1001
+#define SND_SOC_TPLG_TYPE_VENDOR_COEFF 1002
+#define SND_SOC_TPLG_TYPEVENDOR_CODEC 1003
+
+#define SND_SOC_TPLG_STREAM_PLAYBACK 0
+#define SND_SOC_TPLG_STREAM_CAPTURE 1
+
+/* vendor tuple types */
+#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0
+#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1
+#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2
+#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3
+#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4
+#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5
+
+/* DAI flags */
+#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0)
+#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
+#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
+
+/* DAI clock gating */
+#define SND_SOC_TPLG_DAI_CLK_GATE_UNDEFINED 0
+#define SND_SOC_TPLG_DAI_CLK_GATE_GATED 1
+#define SND_SOC_TPLG_DAI_CLK_GATE_CONT 2
+
+/* DAI mclk_direction */
+#define SND_SOC_TPLG_MCLK_CO 0 /* for codec, mclk is output */
+#define SND_SOC_TPLG_MCLK_CI 1 /* for codec, mclk is input */
+
+/* DAI physical PCM data formats.
+ * Add new formats to the end of the list.
+ */
+#define SND_SOC_DAI_FORMAT_I2S 1 /* I2S mode */
+#define SND_SOC_DAI_FORMAT_RIGHT_J 2 /* Right Justified mode */
+#define SND_SOC_DAI_FORMAT_LEFT_J 3 /* Left Justified mode */
+#define SND_SOC_DAI_FORMAT_DSP_A 4 /* L data MSB after FRM LRC */
+#define SND_SOC_DAI_FORMAT_DSP_B 5 /* L data MSB during FRM LRC */
+#define SND_SOC_DAI_FORMAT_AC97 6 /* AC97 */
+#define SND_SOC_DAI_FORMAT_PDM 7 /* Pulse density modulation */
+
+/* left and right justified also known as MSB and LSB respectively */
+#define SND_SOC_DAI_FORMAT_MSB SND_SOC_DAI_FORMAT_LEFT_J
+#define SND_SOC_DAI_FORMAT_LSB SND_SOC_DAI_FORMAT_RIGHT_J
+
+/* DAI link flags */
+#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES (1 << 0)
+#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
+#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
+#define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP (1 << 3)
+
+/* DAI topology BCLK parameter
+ * For the backwards capability, by default codec is bclk master
+ */
+#define SND_SOC_TPLG_BCLK_CM 0 /* codec is bclk master */
+#define SND_SOC_TPLG_BCLK_CS 1 /* codec is bclk slave */
+
+/* DAI topology FSYNC parameter
+ * For the backwards capability, by default codec is fsync master
+ */
+#define SND_SOC_TPLG_FSYNC_CM 0 /* codec is fsync master */
+#define SND_SOC_TPLG_FSYNC_CS 1 /* codec is fsync slave */
+
+/*
+ * Block Header.
+ * This header precedes all object and object arrays below.
+ */
+struct snd_soc_tplg_hdr {
+ __le32 magic; /* magic number */
+ __le32 abi; /* ABI version */
+ __le32 version; /* optional vendor specific version details */
+ __le32 type; /* SND_SOC_TPLG_TYPE_ */
+ __le32 size; /* size of this structure */
+ __le32 vendor_type; /* optional vendor specific type info */
+ __le32 payload_size; /* data bytes, excluding this header */
+ __le32 index; /* identifier for block */
+ __le32 count; /* number of elements in block */
+} __attribute__((packed));
+
+/* vendor tuple for uuid */
+struct snd_soc_tplg_vendor_uuid_elem {
+ __le32 token;
+ char uuid[16];
+} __attribute__((packed));
+
+/* vendor tuple for a bool/byte/short/word value */
+struct snd_soc_tplg_vendor_value_elem {
+ __le32 token;
+ __le32 value;
+} __attribute__((packed));
+
+/* vendor tuple for string */
+struct snd_soc_tplg_vendor_string_elem {
+ __le32 token;
+ char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+} __attribute__((packed));
+
+struct snd_soc_tplg_vendor_array {
+ __le32 size; /* size in bytes of the array, including all elements */
+ __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */
+ __le32 num_elems; /* number of elements in array */
+ union {
+ struct snd_soc_tplg_vendor_uuid_elem uuid[0];
+ struct snd_soc_tplg_vendor_value_elem value[0];
+ struct snd_soc_tplg_vendor_string_elem string[0];
+ };
+} __attribute__((packed));
+
+/*
+ * Private data.
+ * All topology objects may have private data that can be used by the driver or
+ * firmware. Core will ignore this data.
+ */
+struct snd_soc_tplg_private {
+ __le32 size; /* in bytes of private data */
+ union {
+ char data[0];
+ struct snd_soc_tplg_vendor_array array[0];
+ };
+} __attribute__((packed));
+
+/*
+ * Kcontrol TLV data.
+ */
+struct snd_soc_tplg_tlv_dbscale {
+ __le32 min;
+ __le32 step;
+ __le32 mute;
+} __attribute__((packed));
+
+struct snd_soc_tplg_ctl_tlv {
+ __le32 size; /* in bytes of this structure */
+ __le32 type; /* SNDRV_CTL_TLVT_*, type of TLV */
+ union {
+ __le32 data[SND_SOC_TPLG_TLV_SIZE];
+ struct snd_soc_tplg_tlv_dbscale scale;
+ };
+} __attribute__((packed));
+
+/*
+ * Kcontrol channel data
+ */
+struct snd_soc_tplg_channel {
+ __le32 size; /* in bytes of this structure */
+ __le32 reg;
+ __le32 shift;
+ __le32 id; /* ID maps to Left, Right, LFE etc */
+} __attribute__((packed));
+
+/*
+ * Genericl Operations IDs, for binding Kcontrol or Bytes ext ops
+ * Kcontrol ops need get/put/info.
+ * Bytes ext ops need get/put.
+ */
+struct snd_soc_tplg_io_ops {
+ __le32 get;
+ __le32 put;
+ __le32 info;
+} __attribute__((packed));
+
+/*
+ * kcontrol header
+ */
+struct snd_soc_tplg_ctl_hdr {
+ __le32 size; /* in bytes of this structure */
+ __le32 type;
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ __le32 access;
+ struct snd_soc_tplg_io_ops ops;
+ struct snd_soc_tplg_ctl_tlv tlv;
+} __attribute__((packed));
+
+/*
+ * Stream Capabilities
+ */
+struct snd_soc_tplg_stream_caps {
+ __le32 size; /* in bytes of this structure */
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */
+ __le32 rates; /* supported rates SNDRV_PCM_RATE_* */
+ __le32 rate_min; /* min rate */
+ __le32 rate_max; /* max rate */
+ __le32 channels_min; /* min channels */
+ __le32 channels_max; /* max channels */
+ __le32 periods_min; /* min number of periods */
+ __le32 periods_max; /* max number of periods */
+ __le32 period_size_min; /* min period size bytes */
+ __le32 period_size_max; /* max period size bytes */
+ __le32 buffer_size_min; /* min buffer size bytes */
+ __le32 buffer_size_max; /* max buffer size bytes */
+ __le32 sig_bits; /* number of bits of content */
+} __attribute__((packed));
+
+/*
+ * FE or BE Stream configuration supported by SW/FW
+ */
+struct snd_soc_tplg_stream {
+ __le32 size; /* in bytes of this structure */
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* Name of the stream */
+ __le64 format; /* SNDRV_PCM_FMTBIT_* */
+ __le32 rate; /* SNDRV_PCM_RATE_* */
+ __le32 period_bytes; /* size of period in bytes */
+ __le32 buffer_bytes; /* size of buffer in bytes */
+ __le32 channels; /* channels */
+} __attribute__((packed));
+
+
+/*
+ * Describes a physical link's runtime supported hardware config,
+ * i.e. hardware audio formats.
+ */
+struct snd_soc_tplg_hw_config {
+ __le32 size; /* in bytes of this structure */
+ __le32 id; /* unique ID - - used to match */
+ __le32 fmt; /* SND_SOC_DAI_FORMAT_ format value */
+ __u8 clock_gated; /* SND_SOC_TPLG_DAI_CLK_GATE_ value */
+ __u8 invert_bclk; /* 1 for inverted BCLK, 0 for normal */
+ __u8 invert_fsync; /* 1 for inverted frame clock, 0 for normal */
+ __u8 bclk_master; /* SND_SOC_TPLG_BCLK_ value */
+ __u8 fsync_master; /* SND_SOC_TPLG_FSYNC_ value */
+ __u8 mclk_direction; /* SND_SOC_TPLG_MCLK_ value */
+ __le16 reserved; /* for 32bit alignment */
+ __le32 mclk_rate; /* MCLK or SYSCLK freqency in Hz */
+ __le32 bclk_rate; /* BCLK freqency in Hz */
+ __le32 fsync_rate; /* frame clock in Hz */
+ __le32 tdm_slots; /* number of TDM slots in use */
+ __le32 tdm_slot_width; /* width in bits for each slot */
+ __le32 tx_slots; /* bit mask for active Tx slots */
+ __le32 rx_slots; /* bit mask for active Rx slots */
+ __le32 tx_channels; /* number of Tx channels */
+ __le32 tx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */
+ __le32 rx_channels; /* number of Rx channels */
+ __le32 rx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */
+} __attribute__((packed));
+
+/*
+ * Manifest. List totals for each payload type. Not used in parsing, but will
+ * be passed to the component driver before any other objects in order for any
+ * global component resource allocations.
+ *
+ * File block representation for manifest :-
+ * +-----------------------------------+----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-----------------------------------+----+
+ * | struct snd_soc_tplg_manifest | 1 |
+ * +-----------------------------------+----+
+ */
+struct snd_soc_tplg_manifest {
+ __le32 size; /* in bytes of this structure */
+ __le32 control_elems; /* number of control elements */
+ __le32 widget_elems; /* number of widget elements */
+ __le32 graph_elems; /* number of graph elements */
+ __le32 pcm_elems; /* number of PCM elements */
+ __le32 dai_link_elems; /* number of DAI link elements */
+ __le32 dai_elems; /* number of physical DAI elements */
+ __le32 reserved[20]; /* reserved for new ABI element types */
+ struct snd_soc_tplg_private priv;
+} __attribute__((packed));
+
+/*
+ * Mixer kcontrol.
+ *
+ * File block representation for mixer kcontrol :-
+ * +-----------------------------------+----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-----------------------------------+----+
+ * | struct snd_soc_tplg_mixer_control | N |
+ * +-----------------------------------+----+
+ */
+struct snd_soc_tplg_mixer_control {
+ struct snd_soc_tplg_ctl_hdr hdr;
+ __le32 size; /* in bytes of this structure */
+ __le32 min;
+ __le32 max;
+ __le32 platform_max;
+ __le32 invert;
+ __le32 num_channels;
+ struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
+ struct snd_soc_tplg_private priv;
+} __attribute__((packed));
+
+/*
+ * Enumerated kcontrol
+ *
+ * File block representation for enum kcontrol :-
+ * +-----------------------------------+----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-----------------------------------+----+
+ * | struct snd_soc_tplg_enum_control | N |
+ * +-----------------------------------+----+
+ */
+struct snd_soc_tplg_enum_control {
+ struct snd_soc_tplg_ctl_hdr hdr;
+ __le32 size; /* in bytes of this structure */
+ __le32 num_channels;
+ struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
+ __le32 items;
+ __le32 mask;
+ __le32 count;
+ char texts[SND_SOC_TPLG_NUM_TEXTS][SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ __le32 values[SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN / 4];
+ struct snd_soc_tplg_private priv;
+} __attribute__((packed));
+
+/*
+ * Bytes kcontrol
+ *
+ * File block representation for bytes kcontrol :-
+ * +-----------------------------------+----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-----------------------------------+----+
+ * | struct snd_soc_tplg_bytes_control | N |
+ * +-----------------------------------+----+
+ */
+struct snd_soc_tplg_bytes_control {
+ struct snd_soc_tplg_ctl_hdr hdr;
+ __le32 size; /* in bytes of this structure */
+ __le32 max;
+ __le32 mask;
+ __le32 base;
+ __le32 num_regs;
+ struct snd_soc_tplg_io_ops ext_ops;
+ struct snd_soc_tplg_private priv;
+} __attribute__((packed));
+
+/*
+ * DAPM Graph Element
+ *
+ * File block representation for DAPM graph elements :-
+ * +-------------------------------------+----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-------------------------------------+----+
+ * | struct snd_soc_tplg_dapm_graph_elem | N |
+ * +-------------------------------------+----+
+ */
+struct snd_soc_tplg_dapm_graph_elem {
+ char sink[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ char control[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ char source[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+} __attribute__((packed));
+
+/*
+ * DAPM Widget.
+ *
+ * File block representation for DAPM widget :-
+ * +-------------------------------------+-----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-------------------------------------+-----+
+ * | struct snd_soc_tplg_dapm_widget | N |
+ * +-------------------------------------+-----+
+ * | struct snd_soc_tplg_enum_control | 0|1 |
+ * | struct snd_soc_tplg_mixer_control | 0|N |
+ * +-------------------------------------+-----+
+ *
+ * Optional enum or mixer control can be appended to the end of each widget
+ * in the block.
+ */
+struct snd_soc_tplg_dapm_widget {
+ __le32 size; /* in bytes of this structure */
+ __le32 id; /* SND_SOC_DAPM_CTL */
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ char sname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+
+ __le32 reg; /* negative reg = no direct dapm */
+ __le32 shift; /* bits to shift */
+ __le32 mask; /* non-shifted mask */
+ __le32 subseq; /* sort within widget type */
+ __le32 invert; /* invert the power bit */
+ __le32 ignore_suspend; /* kept enabled over suspend */
+ __le16 event_flags;
+ __le16 event_type;
+ __le32 num_kcontrols;
+ struct snd_soc_tplg_private priv;
+ /*
+ * kcontrols that relate to this widget
+ * follow here after widget private data
+ */
+} __attribute__((packed));
+
+
+/*
+ * Describes SW/FW specific features of PCM (FE DAI & DAI link).
+ *
+ * File block representation for PCM :-
+ * +-----------------------------------+-----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-----------------------------------+-----+
+ * | struct snd_soc_tplg_pcm | N |
+ * +-----------------------------------+-----+
+ */
+struct snd_soc_tplg_pcm {
+ __le32 size; /* in bytes of this structure */
+ char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ __le32 pcm_id; /* unique ID - used to match with DAI link */
+ __le32 dai_id; /* unique ID - used to match */
+ __le32 playback; /* supports playback mode */
+ __le32 capture; /* supports capture mode */
+ __le32 compress; /* 1 = compressed; 0 = PCM */
+ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */
+ __le32 num_streams; /* number of streams */
+ struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */
+ __le32 flag_mask; /* bitmask of flags to configure */
+ __le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */
+ struct snd_soc_tplg_private priv;
+} __attribute__((packed));
+
+
+/*
+ * Describes the physical link runtime supported configs or params
+ *
+ * File block representation for physical link config :-
+ * +-----------------------------------+-----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-----------------------------------+-----+
+ * | struct snd_soc_tplg_link_config | N |
+ * +-----------------------------------+-----+
+ */
+struct snd_soc_tplg_link_config {
+ __le32 size; /* in bytes of this structure */
+ __le32 id; /* unique ID - used to match */
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */
+ char stream_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* stream name - used to match */
+ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
+ __le32 num_streams; /* number of streams */
+ struct snd_soc_tplg_hw_config hw_config[SND_SOC_TPLG_HW_CONFIG_MAX]; /* hw configs */
+ __le32 num_hw_configs; /* number of hw configs */
+ __le32 default_hw_config_id; /* default hw config ID for init */
+ __le32 flag_mask; /* bitmask of flags to configure */
+ __le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */
+ struct snd_soc_tplg_private priv;
+} __attribute__((packed));
+
+/*
+ * Describes SW/FW specific features of physical DAI.
+ * It can be used to configure backend DAIs for DPCM.
+ *
+ * File block representation for physical DAI :-
+ * +-----------------------------------+-----+
+ * | struct snd_soc_tplg_hdr | 1 |
+ * +-----------------------------------+-----+
+ * | struct snd_soc_tplg_dai | N |
+ * +-----------------------------------+-----+
+ */
+struct snd_soc_tplg_dai {
+ __le32 size; /* in bytes of this structure */
+ char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */
+ __le32 dai_id; /* unique ID - used to match */
+ __le32 playback; /* supports playback mode */
+ __le32 capture; /* supports capture mode */
+ struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */
+ __le32 flag_mask; /* bitmask of flags to configure */
+ __le32 flags; /* SND_SOC_TPLG_DAI_FLGBIT_* */
+ struct snd_soc_tplg_private priv;
+} __attribute__((packed));
+
+/*
+ * Old version of ABI structs, supported for backward compatibility.
+ */
+
+/* Manifest v4 */
+struct snd_soc_tplg_manifest_v4 {
+ __le32 size; /* in bytes of this structure */
+ __le32 control_elems; /* number of control elements */
+ __le32 widget_elems; /* number of widget elements */
+ __le32 graph_elems; /* number of graph elements */
+ __le32 pcm_elems; /* number of PCM elements */
+ __le32 dai_link_elems; /* number of DAI link elements */
+ struct snd_soc_tplg_private priv;
+} __packed;
+
+/* Stream Capabilities v4 */
+struct snd_soc_tplg_stream_caps_v4 {
+ __le32 size; /* in bytes of this structure */
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */
+ __le32 rates; /* supported rates SNDRV_PCM_RATE_* */
+ __le32 rate_min; /* min rate */
+ __le32 rate_max; /* max rate */
+ __le32 channels_min; /* min channels */
+ __le32 channels_max; /* max channels */
+ __le32 periods_min; /* min number of periods */
+ __le32 periods_max; /* max number of periods */
+ __le32 period_size_min; /* min period size bytes */
+ __le32 period_size_max; /* max period size bytes */
+ __le32 buffer_size_min; /* min buffer size bytes */
+ __le32 buffer_size_max; /* max buffer size bytes */
+} __packed;
+
+/* PCM v4 */
+struct snd_soc_tplg_pcm_v4 {
+ __le32 size; /* in bytes of this structure */
+ char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ __le32 pcm_id; /* unique ID - used to match with DAI link */
+ __le32 dai_id; /* unique ID - used to match */
+ __le32 playback; /* supports playback mode */
+ __le32 capture; /* supports capture mode */
+ __le32 compress; /* 1 = compressed; 0 = PCM */
+ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */
+ __le32 num_streams; /* number of streams */
+ struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */
+} __packed;
+
+/* Physical link config v4 */
+struct snd_soc_tplg_link_config_v4 {
+ __le32 size; /* in bytes of this structure */
+ __le32 id; /* unique ID - used to match */
+ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
+ __le32 num_streams; /* number of streams */
+} __packed;
+
+#endif
diff --git a/include/sound/uapi/asound.h b/include/sound/uapi/asound.h
new file mode 100644
index 00000000..df1153ce
--- /dev/null
+++ b/include/sound/uapi/asound.h
@@ -0,0 +1,1038 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Advanced Linux Sound Architecture - ALSA - Driver
+ * Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
+ * Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _UAPI__SOUND_ASOUND_H
+#define _UAPI__SOUND_ASOUND_H
+
+#if defined(__KERNEL__) || defined(__linux__)
+#include <linux/types.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#include <time.h>
+#endif
+
+/*
+ * protocol version
+ */
+
+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
+#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
+ (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
+ (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
+ SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
+
+/****************************************************************************
+ * *
+ * Digital audio interface *
+ * *
+ ****************************************************************************/
+
+struct snd_aes_iec958 {
+ unsigned char status[24]; /* AES/IEC958 channel status bits */
+ unsigned char subcode[147]; /* AES/IEC958 subcode bits */
+ unsigned char pad; /* nothing */
+ unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */
+};
+
+/****************************************************************************
+ * *
+ * CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort *
+ * *
+ ****************************************************************************/
+
+struct snd_cea_861_aud_if {
+ unsigned char db1_ct_cc; /* coding type and channel count */
+ unsigned char db2_sf_ss; /* sample frequency and size */
+ unsigned char db3; /* not used, all zeros */
+ unsigned char db4_ca; /* channel allocation code */
+ unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
+};
+
+/****************************************************************************
+ * *
+ * Section for driver hardware dependent interface - /dev/snd/hw? *
+ * *
+ ****************************************************************************/
+
+#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+enum {
+ SNDRV_HWDEP_IFACE_OPL2 = 0,
+ SNDRV_HWDEP_IFACE_OPL3,
+ SNDRV_HWDEP_IFACE_OPL4,
+ SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */
+ SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */
+ SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */
+ SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */
+ SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */
+ SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */
+ SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
+ SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */
+ SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */
+ SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */
+ SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
+ SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
+ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
+ SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
+ SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
+ SNDRV_HWDEP_IFACE_FW_DICE, /* TC DICE FireWire device */
+ SNDRV_HWDEP_IFACE_FW_FIREWORKS, /* Echo Audio Fireworks based device */
+ SNDRV_HWDEP_IFACE_FW_BEBOB, /* BridgeCo BeBoB based device */
+ SNDRV_HWDEP_IFACE_FW_OXFW, /* Oxford OXFW970/971 based device */
+ SNDRV_HWDEP_IFACE_FW_DIGI00X, /* Digidesign Digi 002/003 family */
+ SNDRV_HWDEP_IFACE_FW_TASCAM, /* TASCAM FireWire series */
+ SNDRV_HWDEP_IFACE_LINE6, /* Line6 USB processors */
+ SNDRV_HWDEP_IFACE_FW_MOTU, /* MOTU FireWire series */
+ SNDRV_HWDEP_IFACE_FW_FIREFACE, /* RME Fireface series */
+
+ /* Don't forget to change the following: */
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_FIREFACE
+};
+
+struct snd_hwdep_info {
+ unsigned int device; /* WR: device number */
+ int card; /* R: card number */
+ unsigned char id[64]; /* ID (user selectable) */
+ unsigned char name[80]; /* hwdep name */
+ int iface; /* hwdep interface */
+ unsigned char reserved[64]; /* reserved for future */
+};
+
+/* generic DSP loader */
+struct snd_hwdep_dsp_status {
+ unsigned int version; /* R: driver-specific version */
+ unsigned char id[32]; /* R: driver-specific ID string */
+ unsigned int num_dsps; /* R: number of DSP images to transfer */
+ unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */
+ unsigned int chip_ready; /* R: 1 = initialization finished */
+ unsigned char reserved[16]; /* reserved for future use */
+};
+
+struct snd_hwdep_dsp_image {
+ unsigned int index; /* W: DSP index */
+ unsigned char name[64]; /* W: ID (e.g. file name) */
+ unsigned char __user *image; /* W: binary image */
+ size_t length; /* W: size of image in bytes */
+ unsigned long driver_data; /* W: driver-specific data */
+};
+
+#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
+
+/*****************************************************************************
+ * *
+ * Digital Audio (PCM) interface - /dev/snd/pcm?? *
+ * *
+ *****************************************************************************/
+
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14)
+
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
+
+enum {
+ SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */
+ SNDRV_PCM_CLASS_MULTI, /* multichannel device */
+ SNDRV_PCM_CLASS_MODEM, /* software modem class */
+ SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */
+ /* Don't forget to change the following: */
+ SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
+};
+
+enum {
+ SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
+ SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */
+ /* Don't forget to change the following: */
+ SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
+};
+
+enum {
+ SNDRV_PCM_STREAM_PLAYBACK = 0,
+ SNDRV_PCM_STREAM_CAPTURE,
+ SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
+};
+
+typedef int __bitwise snd_pcm_access_t;
+#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */
+#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
+#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */
+#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */
+#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */
+#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
+#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
+#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
+#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
+#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
+#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
+#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
+#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
+#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
+#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
+#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
+#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
+#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
+#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
+#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
+#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
+#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
+#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
+#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
+#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
+#define SNDRV_PCM_FORMAT_S20_LE ((__force snd_pcm_format_t) 25) /* in four bytes, LSB justified */
+#define SNDRV_PCM_FORMAT_S20_BE ((__force snd_pcm_format_t) 26) /* in four bytes, LSB justified */
+#define SNDRV_PCM_FORMAT_U20_LE ((__force snd_pcm_format_t) 27) /* in four bytes, LSB justified */
+#define SNDRV_PCM_FORMAT_U20_BE ((__force snd_pcm_format_t) 28) /* in four bytes, LSB justified */
+/* gap in the numbering for a future standard linear format */
+#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
+#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
+#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
+#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
+#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
+#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
+#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
+#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
+#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */
+#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */
+#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */
+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE
+#define SNDRV_PCM_FORMAT_FIRST SNDRV_PCM_FORMAT_S8
+
+#ifdef SNDRV_LITTLE_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_LE
+#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_LE
+#endif
+#ifdef SNDRV_BIG_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_BE
+#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_BE
+#endif
+
+typedef int __bitwise snd_pcm_subformat_t;
+#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
+#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
+
+#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
+#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
+#define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
+#define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
+#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */
+#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
+#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
+#define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
+#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */
+#define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */
+#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */
+#define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */
+#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */
+#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
+#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
+#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
+#define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */
+#define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */
+#define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */
+#define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */
+#define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */
+
+#define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
+
+
+
+typedef int __bitwise snd_pcm_state_t;
+#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
+#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
+#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */
+#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */
+#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
+#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */
+#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
+#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
+#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
+#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
+
+enum {
+ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+ SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+ SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+};
+
+union snd_pcm_sync_id {
+ unsigned char id[16];
+ unsigned short id16[8];
+ unsigned int id32[4];
+};
+
+struct snd_pcm_info {
+ unsigned int device; /* RO/WR (control): device number */
+ unsigned int subdevice; /* RO/WR (control): subdevice number */
+ int stream; /* RO/WR (control): stream direction */
+ int card; /* R: card number */
+ unsigned char id[64]; /* ID (user selectable) */
+ unsigned char name[80]; /* name of this device */
+ unsigned char subname[32]; /* subdevice name */
+ int dev_class; /* SNDRV_PCM_CLASS_* */
+ int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ union snd_pcm_sync_id sync; /* hardware synchronization ID */
+ unsigned char reserved[64]; /* reserved for future... */
+};
+
+typedef int snd_pcm_hw_param_t;
+#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */
+#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */
+#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */
+#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
+#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */
+#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */
+#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */
+#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */
+#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between
+ * interrupts in us
+ */
+#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between
+ * interrupts
+ */
+#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between
+ * interrupts
+ */
+#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per
+ * buffer
+ */
+#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer
+ * in us
+ */
+#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */
+#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */
+#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */
+#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
+
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
+#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */
+#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */
+
+struct snd_interval {
+ unsigned int min, max;
+ unsigned int openmin:1,
+ openmax:1,
+ integer:1,
+ empty:1;
+};
+
+#define SNDRV_MASK_MAX 256
+
+struct snd_mask {
+ __u32 bits[(SNDRV_MASK_MAX+31)/32];
+};
+
+struct snd_pcm_hw_params {
+ unsigned int flags;
+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
+ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
+ struct snd_mask mres[5]; /* reserved masks */
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+ struct snd_interval ires[9]; /* reserved intervals */
+ unsigned int rmask; /* W: requested masks */
+ unsigned int cmask; /* R: changed masks */
+ unsigned int info; /* R: Info flags for returned setup */
+ unsigned int msbits; /* R: used most significant bits */
+ unsigned int rate_num; /* R: rate numerator */
+ unsigned int rate_den; /* R: rate denominator */
+ snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
+ unsigned char reserved[64]; /* reserved for future */
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_NONE = 0,
+ SNDRV_PCM_TSTAMP_ENABLE,
+ SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
+};
+
+struct snd_pcm_sw_params {
+ int tstamp_mode; /* timestamp mode */
+ unsigned int period_step;
+ unsigned int sleep_min; /* min ticks to sleep */
+ snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
+ snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */
+ snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
+ snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
+ snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
+ snd_pcm_uframes_t silence_size; /* silence block size */
+ snd_pcm_uframes_t boundary; /* pointers wrap point */
+ unsigned int proto; /* protocol version */
+ unsigned int tstamp_type; /* timestamp type (req. proto >= 2.0.12) */
+ unsigned char reserved[56]; /* reserved for future */
+};
+
+struct snd_pcm_channel_info {
+ unsigned int channel;
+ __kernel_off_t offset; /* mmap offset */
+ unsigned int first; /* offset to first sample in bits */
+ unsigned int step; /* samples distance in bits */
+};
+
+enum {
+ /*
+ * first definition for backwards compatibility only,
+ * maps to wallclock/link time for HDAudio playback and DEFAULT/DMA time for everything else
+ */
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT = 0,
+
+ /* timestamp definitions */
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT = 1, /* DMA time, reported as per hw_ptr */
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK = 2, /* link time reported by sample or wallclock counter, reset on startup */
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE = 3, /* link time reported by sample or wallclock counter, not reset on startup */
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED = 4, /* link time estimated indirectly */
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED = 5, /* link time synchronized with system time */
+ SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
+};
+
+struct snd_pcm_status {
+ snd_pcm_state_t state; /* stream state */
+ struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
+ struct timespec tstamp; /* reference timestamp */
+ snd_pcm_uframes_t appl_ptr; /* appl ptr */
+ snd_pcm_uframes_t hw_ptr; /* hw ptr */
+ snd_pcm_sframes_t delay; /* current delay in frames */
+ snd_pcm_uframes_t avail; /* number of frames available */
+ snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
+ snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
+ snd_pcm_state_t suspended_state; /* suspended stream state */
+ __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
+ struct timespec audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */
+ struct timespec driver_tstamp; /* useful in case reference system tstamp is reported with delay */
+ __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */
+ unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
+};
+
+struct snd_pcm_mmap_status {
+ snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
+ int pad1; /* Needed for 64 bit alignment */
+ snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
+ struct timespec tstamp; /* Timestamp */
+ snd_pcm_state_t suspended_state; /* RO: suspended stream state */
+ struct timespec audio_tstamp; /* from sample counter or wall clock */
+};
+
+struct snd_pcm_mmap_control {
+ snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
+ snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
+};
+
+#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */
+#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
+
+struct snd_pcm_sync_ptr {
+ unsigned int flags;
+ union {
+ struct snd_pcm_mmap_status status;
+ unsigned char reserved[64];
+ } s;
+ union {
+ struct snd_pcm_mmap_control control;
+ unsigned char reserved[64];
+ } c;
+};
+
+struct snd_xferi {
+ snd_pcm_sframes_t result;
+ void __user *buf;
+ snd_pcm_uframes_t frames;
+};
+
+struct snd_xfern {
+ snd_pcm_sframes_t result;
+ void __user * __user *bufs;
+ snd_pcm_uframes_t frames;
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW, /* monotonic_raw (no NTP) */
+ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
+};
+
+/* channel positions */
+enum {
+ SNDRV_CHMAP_UNKNOWN = 0,
+ SNDRV_CHMAP_NA, /* N/A, silent */
+ SNDRV_CHMAP_MONO, /* mono stream */
+ /* this follows the alsa-lib mixer channel value + 3 */
+ SNDRV_CHMAP_FL, /* front left */
+ SNDRV_CHMAP_FR, /* front right */
+ SNDRV_CHMAP_RL, /* rear left */
+ SNDRV_CHMAP_RR, /* rear right */
+ SNDRV_CHMAP_FC, /* front center */
+ SNDRV_CHMAP_LFE, /* LFE */
+ SNDRV_CHMAP_SL, /* side left */
+ SNDRV_CHMAP_SR, /* side right */
+ SNDRV_CHMAP_RC, /* rear center */
+ /* new definitions */
+ SNDRV_CHMAP_FLC, /* front left center */
+ SNDRV_CHMAP_FRC, /* front right center */
+ SNDRV_CHMAP_RLC, /* rear left center */
+ SNDRV_CHMAP_RRC, /* rear right center */
+ SNDRV_CHMAP_FLW, /* front left wide */
+ SNDRV_CHMAP_FRW, /* front right wide */
+ SNDRV_CHMAP_FLH, /* front left high */
+ SNDRV_CHMAP_FCH, /* front center high */
+ SNDRV_CHMAP_FRH, /* front right high */
+ SNDRV_CHMAP_TC, /* top center */
+ SNDRV_CHMAP_TFL, /* top front left */
+ SNDRV_CHMAP_TFR, /* top front right */
+ SNDRV_CHMAP_TFC, /* top front center */
+ SNDRV_CHMAP_TRL, /* top rear left */
+ SNDRV_CHMAP_TRR, /* top rear right */
+ SNDRV_CHMAP_TRC, /* top rear center */
+ /* new definitions for UAC2 */
+ SNDRV_CHMAP_TFLC, /* top front left center */
+ SNDRV_CHMAP_TFRC, /* top front right center */
+ SNDRV_CHMAP_TSL, /* top side left */
+ SNDRV_CHMAP_TSR, /* top side right */
+ SNDRV_CHMAP_LLFE, /* left LFE */
+ SNDRV_CHMAP_RLFE, /* right LFE */
+ SNDRV_CHMAP_BC, /* bottom center */
+ SNDRV_CHMAP_BLC, /* bottom left center */
+ SNDRV_CHMAP_BRC, /* bottom right center */
+ SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
+};
+
+#define SNDRV_CHMAP_POSITION_MASK 0xffff
+#define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16)
+#define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
+
+#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
+
+/*****************************************************************************
+ * *
+ * MIDI v1.0 interface *
+ * *
+ *****************************************************************************/
+
+/*
+ * Raw MIDI section - /dev/snd/midi??
+ */
+
+#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
+
+enum {
+ SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
+ SNDRV_RAWMIDI_STREAM_INPUT,
+ SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
+};
+
+#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
+#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
+#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
+
+struct snd_rawmidi_info {
+ unsigned int device; /* RO/WR (control): device number */
+ unsigned int subdevice; /* RO/WR (control): subdevice number */
+ int stream; /* WR: stream */
+ int card; /* R: card number */
+ unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */
+ unsigned char id[64]; /* ID (user selectable) */
+ unsigned char name[80]; /* name of device */
+ unsigned char subname[32]; /* name of active or selected subdevice */
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ unsigned char reserved[64]; /* reserved for future use */
+};
+
+struct snd_rawmidi_params {
+ int stream;
+ size_t buffer_size; /* queue size in bytes */
+ size_t avail_min; /* minimum avail bytes for wakeup */
+ unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
+ unsigned char reserved[16]; /* reserved for future use */
+};
+
+struct snd_rawmidi_status {
+ int stream;
+ struct timespec tstamp; /* Timestamp */
+ size_t avail; /* available bytes */
+ size_t xruns; /* count of overruns since last status (in bytes) */
+ unsigned char reserved[16]; /* reserved for future use */
+};
+
+#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
+
+/*
+ * Timer section - /dev/snd/timer
+ */
+
+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+enum {
+ SNDRV_TIMER_CLASS_NONE = -1,
+ SNDRV_TIMER_CLASS_SLAVE = 0,
+ SNDRV_TIMER_CLASS_GLOBAL,
+ SNDRV_TIMER_CLASS_CARD,
+ SNDRV_TIMER_CLASS_PCM,
+ SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
+};
+
+/* slave timer classes */
+enum {
+ SNDRV_TIMER_SCLASS_NONE = 0,
+ SNDRV_TIMER_SCLASS_APPLICATION,
+ SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */
+ SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */
+ SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+};
+
+/* global timers (device member) */
+#define SNDRV_TIMER_GLOBAL_SYSTEM 0
+#define SNDRV_TIMER_GLOBAL_RTC 1 /* unused */
+#define SNDRV_TIMER_GLOBAL_HPET 2
+#define SNDRV_TIMER_GLOBAL_HRTIMER 3
+
+/* info flags */
+#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
+
+struct snd_timer_id {
+ int dev_class;
+ int dev_sclass;
+ int card;
+ int device;
+ int subdevice;
+};
+
+struct snd_timer_ginfo {
+ struct snd_timer_id tid; /* requested timer ID */
+ unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
+ int card; /* card number */
+ unsigned char id[64]; /* timer identification */
+ unsigned char name[80]; /* timer name */
+ unsigned long reserved0; /* reserved for future use */
+ unsigned long resolution; /* average period resolution in ns */
+ unsigned long resolution_min; /* minimal period resolution in ns */
+ unsigned long resolution_max; /* maximal period resolution in ns */
+ unsigned int clients; /* active timer clients */
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gparams {
+ struct snd_timer_id tid; /* requested timer ID */
+ unsigned long period_num; /* requested precise period duration (in seconds) - numerator */
+ unsigned long period_den; /* requested precise period duration (in seconds) - denominator */
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gstatus {
+ struct snd_timer_id tid; /* requested timer ID */
+ unsigned long resolution; /* current period resolution in ns */
+ unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */
+ unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */
+ unsigned char reserved[32];
+};
+
+struct snd_timer_select {
+ struct snd_timer_id id; /* bind to timer ID */
+ unsigned char reserved[32]; /* reserved */
+};
+
+struct snd_timer_info {
+ unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
+ int card; /* card number */
+ unsigned char id[64]; /* timer identificator */
+ unsigned char name[80]; /* timer name */
+ unsigned long reserved0; /* reserved for future use */
+ unsigned long resolution; /* average period resolution in ns */
+ unsigned char reserved[64]; /* reserved */
+};
+
+#define SNDRV_TIMER_PSFLG_AUTO (1<<0) /* auto start, otherwise one-shot */
+#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */
+#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
+
+struct snd_timer_params {
+ unsigned int flags; /* flags - SNDRV_TIMER_PSFLG_* */
+ unsigned int ticks; /* requested resolution in ticks */
+ unsigned int queue_size; /* total size of queue (32-1024) */
+ unsigned int reserved0; /* reserved, was: failure locations */
+ unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
+ unsigned char reserved[60]; /* reserved */
+};
+
+struct snd_timer_status {
+ struct timespec tstamp; /* Timestamp - last update */
+ unsigned int resolution; /* current period resolution in ns */
+ unsigned int lost; /* counter of master tick lost */
+ unsigned int overrun; /* count of read queue overruns */
+ unsigned int queue; /* used queue size */
+ unsigned char reserved[64]; /* reserved */
+};
+
+#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
+/* The following four ioctls are changed since 1.0.9 due to confliction */
+#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
+
+struct snd_timer_read {
+ unsigned int resolution;
+ unsigned int ticks;
+};
+
+enum {
+ SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */
+ SNDRV_TIMER_EVENT_TICK, /* val = ticks */
+ SNDRV_TIMER_EVENT_START, /* val = resolution in ns */
+ SNDRV_TIMER_EVENT_STOP, /* val = 0 */
+ SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */
+ SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */
+ SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */
+ SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */
+ SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */
+ /* master timer events for slave timer instances */
+ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
+ SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
+ SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
+ SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
+};
+
+struct snd_timer_tread {
+ int event;
+ struct timespec tstamp;
+ unsigned int val;
+};
+
+/****************************************************************************
+ * *
+ * Section for driver control interface - /dev/snd/control? *
+ * *
+ ****************************************************************************/
+
+#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
+
+struct snd_ctl_card_info {
+ int card; /* card number */
+ int pad; /* reserved for future (was type) */
+ unsigned char id[16]; /* ID of card (user selectable) */
+ unsigned char driver[16]; /* Driver name */
+ unsigned char name[32]; /* Short name of soundcard */
+ unsigned char longname[80]; /* name + info text about soundcard */
+ unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
+ unsigned char mixername[80]; /* visual mixer identification */
+ unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
+};
+
+typedef int __bitwise snd_ctl_elem_type_t;
+#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */
+#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */
+#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */
+#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
+#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */
+#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
+#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
+#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */
+#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
+#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
+#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
+#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
+#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */
+#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
+#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
+
+#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
+#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
+#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */
+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */
+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */
+#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */
+#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */
+#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */
+/* bits 30 and 31 are obsoleted (for indirect access) */
+
+/* for further details see the ACPI and PCI power management specification */
+#define SNDRV_CTL_POWER_D0 0x0000 /* full On */
+#define SNDRV_CTL_POWER_D1 0x0100 /* partial On */
+#define SNDRV_CTL_POWER_D2 0x0200 /* partial On */
+#define SNDRV_CTL_POWER_D3 0x0300 /* Off */
+#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */
+#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */
+
+#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44
+
+struct snd_ctl_elem_id {
+ unsigned int numid; /* numeric identifier, zero = invalid */
+ snd_ctl_elem_iface_t iface; /* interface identifier */
+ unsigned int device; /* device/client number */
+ unsigned int subdevice; /* subdevice (substream) number */
+ unsigned char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* ASCII name of item */
+ unsigned int index; /* index of item */
+};
+
+struct snd_ctl_elem_list {
+ unsigned int offset; /* W: first element ID to get */
+ unsigned int space; /* W: count of element IDs to get */
+ unsigned int used; /* R: count of element IDs set */
+ unsigned int count; /* R: count of all elements */
+ struct snd_ctl_elem_id __user *pids; /* R: IDs */
+ unsigned char reserved[50];
+};
+
+struct snd_ctl_elem_info {
+ struct snd_ctl_elem_id id; /* W: element ID */
+ snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
+ unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
+ unsigned int count; /* count of values */
+ __kernel_pid_t owner; /* owner's PID of this control */
+ union {
+ struct {
+ long min; /* R: minimum value */
+ long max; /* R: maximum value */
+ long step; /* R: step (0 variable) */
+ } integer;
+ struct {
+ long long min; /* R: minimum value */
+ long long max; /* R: maximum value */
+ long long step; /* R: step (0 variable) */
+ } integer64;
+ struct {
+ unsigned int items; /* R: number of items */
+ unsigned int item; /* W: item number */
+ char name[64]; /* R: value name */
+ __u64 names_ptr; /* W: names list (ELEM_ADD only) */
+ unsigned int names_length;
+ } enumerated;
+ unsigned char reserved[128];
+ } value;
+ union {
+ unsigned short d[4]; /* dimensions */
+ unsigned short *d_ptr; /* indirect - obsoleted */
+ } dimen;
+ unsigned char reserved[64-4*sizeof(unsigned short)];
+};
+
+struct snd_ctl_elem_value {
+ struct snd_ctl_elem_id id; /* W: element ID */
+ unsigned int indirect: 1; /* W: indirect access - obsoleted */
+ union {
+ union {
+ long value[128];
+ long *value_ptr; /* obsoleted */
+ } integer;
+ union {
+ long long value[64];
+ long long *value_ptr; /* obsoleted */
+ } integer64;
+ union {
+ unsigned int item[128];
+ unsigned int *item_ptr; /* obsoleted */
+ } enumerated;
+ union {
+ unsigned char data[512];
+ unsigned char *data_ptr; /* obsoleted */
+ } bytes;
+ struct snd_aes_iec958 iec958;
+ } value; /* RO */
+ struct timespec tstamp;
+ unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+struct snd_ctl_tlv {
+ unsigned int numid; /* control element numeric identification */
+ unsigned int length; /* in bytes aligned to 4 */
+ unsigned int tlv[0]; /* first TLV */
+};
+
+#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
+
+/*
+ * Read interface.
+ */
+
+enum sndrv_ctl_event_type {
+ SNDRV_CTL_EVENT_ELEM = 0,
+ SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
+};
+
+#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */
+#define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */
+#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */
+#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */
+#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */
+
+struct snd_ctl_event {
+ int type; /* event type - SNDRV_CTL_EVENT_* */
+ union {
+ struct {
+ unsigned int mask;
+ struct snd_ctl_elem_id id;
+ } elem;
+ unsigned char data8[60];
+ } data;
+};
+
+/*
+ * Control names
+ */
+
+#define SNDRV_CTL_NAME_NONE ""
+#define SNDRV_CTL_NAME_PLAYBACK "Playback "
+#define SNDRV_CTL_NAME_CAPTURE "Capture "
+
+#define SNDRV_CTL_NAME_IEC958_NONE ""
+#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
+#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
+#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
+#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
+#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
+#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
+#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
+
+#endif /* _UAPI__SOUND_ASOUND_H */
diff --git a/include/sound/uapi/asound_fm.h b/include/sound/uapi/asound_fm.h
new file mode 100644
index 00000000..8471f404
--- /dev/null
+++ b/include/sound/uapi/asound_fm.h
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+#ifndef __SOUND_ASOUND_FM_H
+#define __SOUND_ASOUND_FM_H
+
+/*
+ * Advanced Linux Sound Architecture - ALSA
+ *
+ * Interface file between ALSA driver & user space
+ * Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>,
+ * 4Front Technologies
+ *
+ * Direct FM control
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define SNDRV_DM_FM_MODE_OPL2 0x00
+#define SNDRV_DM_FM_MODE_OPL3 0x01
+
+struct snd_dm_fm_info {
+ unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
+ unsigned char rhythm; /* percussion mode flag */
+};
+
+/*
+ * Data structure composing an FM "note" or sound event.
+ */
+
+struct snd_dm_fm_voice {
+ unsigned char op; /* operator cell (0 or 1) */
+ unsigned char voice; /* FM voice (0 to 17) */
+
+ unsigned char am; /* amplitude modulation */
+ unsigned char vibrato; /* vibrato effect */
+ unsigned char do_sustain; /* sustain phase */
+ unsigned char kbd_scale; /* keyboard scaling */
+ unsigned char harmonic; /* 4 bits: harmonic and multiplier */
+ unsigned char scale_level; /* 2 bits: decrease output freq rises */
+ unsigned char volume; /* 6 bits: volume */
+
+ unsigned char attack; /* 4 bits: attack rate */
+ unsigned char decay; /* 4 bits: decay rate */
+ unsigned char sustain; /* 4 bits: sustain level */
+ unsigned char release; /* 4 bits: release rate */
+
+ unsigned char feedback; /* 3 bits: feedback for op0 */
+ unsigned char connection; /* 0 for serial, 1 for parallel */
+ unsigned char left; /* stereo left */
+ unsigned char right; /* stereo right */
+ unsigned char waveform; /* 3 bits: waveform shape */
+};
+
+/*
+ * This describes an FM note by its voice, octave, frequency number (10bit)
+ * and key on/off.
+ */
+
+struct snd_dm_fm_note {
+ unsigned char voice; /* 0-17 voice channel */
+ unsigned char octave; /* 3 bits: what octave to play */
+ unsigned int fnum; /* 10 bits: frequency number */
+ unsigned char key_on; /* set for active, clear for silent */
+};
+
+/*
+ * FM parameters that apply globally to all voices, and thus are not "notes"
+ */
+
+struct snd_dm_fm_params {
+ unsigned char am_depth; /* amplitude modulation depth (1=hi) */
+ unsigned char vib_depth; /* vibrato depth (1=hi) */
+ unsigned char kbd_split; /* keyboard split */
+ unsigned char rhythm; /* percussion mode select */
+
+ /* This block is the percussion instrument data */
+ unsigned char bass;
+ unsigned char snare;
+ unsigned char tomtom;
+ unsigned char cymbal;
+ unsigned char hihat;
+};
+
+/*
+ * FM mode ioctl settings
+ */
+
+#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, struct snd_dm_fm_info)
+#define SNDRV_DM_FM_IOCTL_RESET _IO ('H', 0x21)
+#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, struct snd_dm_fm_note)
+#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, struct snd_dm_fm_voice)
+#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, struct snd_dm_fm_params)
+#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int)
+/* for OPL3 only */
+#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int)
+/* SBI patch management */
+#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES _IO ('H', 0x40)
+
+#define SNDRV_DM_FM_OSS_IOCTL_RESET 0x20
+#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21
+#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22
+#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23
+#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24
+#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25
+
+/*
+ * Patch Record - fixed size for write
+ */
+
+#define FM_KEY_SBI "SBI\032"
+#define FM_KEY_2OP "2OP\032"
+#define FM_KEY_4OP "4OP\032"
+
+struct sbi_patch {
+ unsigned char prog;
+ unsigned char bank;
+ char key[4];
+ char name[25];
+ char extension[7];
+ unsigned char data[32];
+};
+
+#endif /* __SOUND_ASOUND_FM_H */
diff --git a/include/sound/uapi/emu10k1.h b/include/sound/uapi/emu10k1.h
new file mode 100644
index 00000000..c1150e4d
--- /dev/null
+++ b/include/sound/uapi/emu10k1.h
@@ -0,0 +1,395 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
+ * Creative Labs, Inc.
+ * Definitions for EMU10K1 (SB Live!) chips
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_EMU10K1_H
+#define _UAPI__SOUND_EMU10K1_H
+
+/*
+ * ---- FX8010 ----
+ */
+
+#define EMU10K1_CARD_CREATIVE 0x00000000
+#define EMU10K1_CARD_EMUAPS 0x00000001
+
+#define EMU10K1_FX8010_PCM_COUNT 8
+
+/*
+ * Following definition is copied from linux/types.h to support compiling
+ * this header file in userspace since they are not generally available for
+ * uapi headers.
+ */
+#define __EMU10K1_DECLARE_BITMAP(name,bits) \
+ unsigned long name[(bits) / (sizeof(unsigned long) * 8)]
+
+/* instruction set */
+#define iMAC0 0x00 /* R = A + (X * Y >> 31) ; saturation */
+#define iMAC1 0x01 /* R = A + (-X * Y >> 31) ; saturation */
+#define iMAC2 0x02 /* R = A + (X * Y >> 31) ; wraparound */
+#define iMAC3 0x03 /* R = A + (-X * Y >> 31) ; wraparound */
+#define iMACINT0 0x04 /* R = A + X * Y ; saturation */
+#define iMACINT1 0x05 /* R = A + X * Y ; wraparound (31-bit) */
+#define iACC3 0x06 /* R = A + X + Y ; saturation */
+#define iMACMV 0x07 /* R = A, acc += X * Y >> 31 */
+#define iANDXOR 0x08 /* R = (A & X) ^ Y */
+#define iTSTNEG 0x09 /* R = (A >= Y) ? X : ~X */
+#define iLIMITGE 0x0a /* R = (A >= Y) ? X : Y */
+#define iLIMITLT 0x0b /* R = (A < Y) ? X : Y */
+#define iLOG 0x0c /* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
+#define iEXP 0x0d /* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
+#define iINTERP 0x0e /* R = A + (X * (Y - A) >> 31) ; saturation */
+#define iSKIP 0x0f /* R = A (cc_reg), X (count), Y (cc_test) */
+
+/* GPRs */
+#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */
+#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */
+#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
+#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
+ /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
+
+#define C_00000000 0x40
+#define C_00000001 0x41
+#define C_00000002 0x42
+#define C_00000003 0x43
+#define C_00000004 0x44
+#define C_00000008 0x45
+#define C_00000010 0x46
+#define C_00000020 0x47
+#define C_00000100 0x48
+#define C_00010000 0x49
+#define C_00080000 0x4a
+#define C_10000000 0x4b
+#define C_20000000 0x4c
+#define C_40000000 0x4d
+#define C_80000000 0x4e
+#define C_7fffffff 0x4f
+#define C_ffffffff 0x50
+#define C_fffffffe 0x51
+#define C_c0000000 0x52
+#define C_4f1bbcdc 0x53
+#define C_5a7ef9db 0x54
+#define C_00100000 0x55 /* ?? */
+#define GPR_ACCU 0x56 /* ACCUM, accumulator */
+#define GPR_COND 0x57 /* CCR, condition register */
+#define GPR_NOISE0 0x58 /* noise source */
+#define GPR_NOISE1 0x59 /* noise source */
+#define GPR_IRQ 0x5a /* IRQ register */
+#define GPR_DBAC 0x5b /* TRAM Delay Base Address Counter */
+#define GPR(x) (FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
+#define ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+#define ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+
+#define A_ITRAM_DATA(x) (TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_DATA(x) (TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_ADDR(x) (TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_ADDR(x) (TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+
+#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */
+#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */
+#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
+#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */
+#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
+#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
+#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
+#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
+#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
+#define A_GPR(x) (A_FXGPREGBASE + (x))
+
+/* cc_reg constants */
+#define CC_REG_NORMALIZED C_00000001
+#define CC_REG_BORROW C_00000002
+#define CC_REG_MINUS C_00000004
+#define CC_REG_ZERO C_00000008
+#define CC_REG_SATURATE C_00000010
+#define CC_REG_NONZERO C_00000100
+
+/* FX buses */
+#define FXBUS_PCM_LEFT 0x00
+#define FXBUS_PCM_RIGHT 0x01
+#define FXBUS_PCM_LEFT_REAR 0x02
+#define FXBUS_PCM_RIGHT_REAR 0x03
+#define FXBUS_MIDI_LEFT 0x04
+#define FXBUS_MIDI_RIGHT 0x05
+#define FXBUS_PCM_CENTER 0x06
+#define FXBUS_PCM_LFE 0x07
+#define FXBUS_PCM_LEFT_FRONT 0x08
+#define FXBUS_PCM_RIGHT_FRONT 0x09
+#define FXBUS_MIDI_REVERB 0x0c
+#define FXBUS_MIDI_CHORUS 0x0d
+#define FXBUS_PCM_LEFT_SIDE 0x0e
+#define FXBUS_PCM_RIGHT_SIDE 0x0f
+#define FXBUS_PT_LEFT 0x14
+#define FXBUS_PT_RIGHT 0x15
+
+/* Inputs */
+#define EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */
+#define EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */
+#define EXTIN_SPDIF_CD_L 0x02 /* internal S/PDIF CD - onboard - left */
+#define EXTIN_SPDIF_CD_R 0x03 /* internal S/PDIF CD - onboard - right */
+#define EXTIN_ZOOM_L 0x04 /* Zoom Video I2S - left */
+#define EXTIN_ZOOM_R 0x05 /* Zoom Video I2S - right */
+#define EXTIN_TOSLINK_L 0x06 /* LiveDrive - TOSLink Optical - left */
+#define EXTIN_TOSLINK_R 0x07 /* LiveDrive - TOSLink Optical - right */
+#define EXTIN_LINE1_L 0x08 /* LiveDrive - Line/Mic 1 - left */
+#define EXTIN_LINE1_R 0x09 /* LiveDrive - Line/Mic 1 - right */
+#define EXTIN_COAX_SPDIF_L 0x0a /* LiveDrive - Coaxial S/PDIF - left */
+#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
+#define EXTIN_LINE2_L 0x0c /* LiveDrive - Line/Mic 2 - left */
+#define EXTIN_LINE2_R 0x0d /* LiveDrive - Line/Mic 2 - right */
+
+/* Outputs */
+#define EXTOUT_AC97_L 0x00 /* AC'97 playback channel - left */
+#define EXTOUT_AC97_R 0x01 /* AC'97 playback channel - right */
+#define EXTOUT_TOSLINK_L 0x02 /* LiveDrive - TOSLink Optical - left */
+#define EXTOUT_TOSLINK_R 0x03 /* LiveDrive - TOSLink Optical - right */
+#define EXTOUT_AC97_CENTER 0x04 /* SB Live 5.1 - center */
+#define EXTOUT_AC97_LFE 0x05 /* SB Live 5.1 - LFE */
+#define EXTOUT_HEADPHONE_L 0x06 /* LiveDrive - Headphone - left */
+#define EXTOUT_HEADPHONE_R 0x07 /* LiveDrive - Headphone - right */
+#define EXTOUT_REAR_L 0x08 /* Rear channel - left */
+#define EXTOUT_REAR_R 0x09 /* Rear channel - right */
+#define EXTOUT_ADC_CAP_L 0x0a /* ADC Capture buffer - left */
+#define EXTOUT_ADC_CAP_R 0x0b /* ADC Capture buffer - right */
+#define EXTOUT_MIC_CAP 0x0c /* MIC Capture buffer */
+#define EXTOUT_AC97_REAR_L 0x0d /* SB Live 5.1 (c) 2003 - Rear Left */
+#define EXTOUT_AC97_REAR_R 0x0e /* SB Live 5.1 (c) 2003 - Rear Right */
+#define EXTOUT_ACENTER 0x11 /* Analog Center */
+#define EXTOUT_ALFE 0x12 /* Analog LFE */
+
+/* Audigy Inputs */
+#define A_EXTIN_AC97_L 0x00 /* AC'97 capture channel - left */
+#define A_EXTIN_AC97_R 0x01 /* AC'97 capture channel - right */
+#define A_EXTIN_SPDIF_CD_L 0x02 /* digital CD left */
+#define A_EXTIN_SPDIF_CD_R 0x03 /* digital CD left */
+#define A_EXTIN_OPT_SPDIF_L 0x04 /* audigy drive Optical SPDIF - left */
+#define A_EXTIN_OPT_SPDIF_R 0x05 /* right */
+#define A_EXTIN_LINE2_L 0x08 /* audigy drive line2/mic2 - left */
+#define A_EXTIN_LINE2_R 0x09 /* right */
+#define A_EXTIN_ADC_L 0x0a /* Philips ADC - left */
+#define A_EXTIN_ADC_R 0x0b /* right */
+#define A_EXTIN_AUX2_L 0x0c /* audigy drive aux2 - left */
+#define A_EXTIN_AUX2_R 0x0d /* - right */
+
+/* Audigiy Outputs */
+#define A_EXTOUT_FRONT_L 0x00 /* digital front left */
+#define A_EXTOUT_FRONT_R 0x01 /* right */
+#define A_EXTOUT_CENTER 0x02 /* digital front center */
+#define A_EXTOUT_LFE 0x03 /* digital front lfe */
+#define A_EXTOUT_HEADPHONE_L 0x04 /* headphone audigy drive left */
+#define A_EXTOUT_HEADPHONE_R 0x05 /* right */
+#define A_EXTOUT_REAR_L 0x06 /* digital rear left */
+#define A_EXTOUT_REAR_R 0x07 /* right */
+#define A_EXTOUT_AFRONT_L 0x08 /* analog front left */
+#define A_EXTOUT_AFRONT_R 0x09 /* right */
+#define A_EXTOUT_ACENTER 0x0a /* analog center */
+#define A_EXTOUT_ALFE 0x0b /* analog LFE */
+#define A_EXTOUT_ASIDE_L 0x0c /* analog side left - Audigy 2 ZS */
+#define A_EXTOUT_ASIDE_R 0x0d /* right - Audigy 2 ZS */
+#define A_EXTOUT_AREAR_L 0x0e /* analog rear left */
+#define A_EXTOUT_AREAR_R 0x0f /* right */
+#define A_EXTOUT_AC97_L 0x10 /* AC97 left (front) */
+#define A_EXTOUT_AC97_R 0x11 /* right */
+#define A_EXTOUT_ADC_CAP_L 0x16 /* ADC capture buffer left */
+#define A_EXTOUT_ADC_CAP_R 0x17 /* right */
+#define A_EXTOUT_MIC_CAP 0x18 /* Mic capture buffer */
+
+/* Audigy constants */
+#define A_C_00000000 0xc0
+#define A_C_00000001 0xc1
+#define A_C_00000002 0xc2
+#define A_C_00000003 0xc3
+#define A_C_00000004 0xc4
+#define A_C_00000008 0xc5
+#define A_C_00000010 0xc6
+#define A_C_00000020 0xc7
+#define A_C_00000100 0xc8
+#define A_C_00010000 0xc9
+#define A_C_00000800 0xca
+#define A_C_10000000 0xcb
+#define A_C_20000000 0xcc
+#define A_C_40000000 0xcd
+#define A_C_80000000 0xce
+#define A_C_7fffffff 0xcf
+#define A_C_ffffffff 0xd0
+#define A_C_fffffffe 0xd1
+#define A_C_c0000000 0xd2
+#define A_C_4f1bbcdc 0xd3
+#define A_C_5a7ef9db 0xd4
+#define A_C_00100000 0xd5
+#define A_GPR_ACCU 0xd6 /* ACCUM, accumulator */
+#define A_GPR_COND 0xd7 /* CCR, condition register */
+#define A_GPR_NOISE0 0xd8 /* noise source */
+#define A_GPR_NOISE1 0xd9 /* noise source */
+#define A_GPR_IRQ 0xda /* IRQ register */
+#define A_GPR_DBAC 0xdb /* TRAM Delay Base Address Counter - internal */
+#define A_GPR_DBACE 0xde /* TRAM Delay Base Address Counter - external */
+
+/* definitions for debug register */
+#define EMU10K1_DBG_ZC 0x80000000 /* zero tram counter */
+#define EMU10K1_DBG_SATURATION_OCCURED 0x02000000 /* saturation control */
+#define EMU10K1_DBG_SATURATION_ADDR 0x01ff0000 /* saturation address */
+#define EMU10K1_DBG_SINGLE_STEP 0x00008000 /* single step mode */
+#define EMU10K1_DBG_STEP 0x00004000 /* start single step */
+#define EMU10K1_DBG_CONDITION_CODE 0x00003e00 /* condition code */
+#define EMU10K1_DBG_SINGLE_STEP_ADDR 0x000001ff /* single step address */
+
+/* tank memory address line */
+#ifndef __KERNEL__
+#define TANKMEMADDRREG_ADDR_MASK 0x000fffff /* 20 bit tank address field */
+#define TANKMEMADDRREG_CLEAR 0x00800000 /* Clear tank memory */
+#define TANKMEMADDRREG_ALIGN 0x00400000 /* Align read or write relative to tank access */
+#define TANKMEMADDRREG_WRITE 0x00200000 /* Write to tank memory */
+#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */
+#endif
+
+struct snd_emu10k1_fx8010_info {
+ unsigned int internal_tram_size; /* in samples */
+ unsigned int external_tram_size; /* in samples */
+ char fxbus_names[16][32]; /* names of FXBUSes */
+ char extin_names[16][32]; /* names of external inputs */
+ char extout_names[32][32]; /* names of external outputs */
+ unsigned int gpr_controls; /* count of GPR controls */
+};
+
+#define EMU10K1_GPR_TRANSLATION_NONE 0
+#define EMU10K1_GPR_TRANSLATION_TABLE100 1
+#define EMU10K1_GPR_TRANSLATION_BASS 2
+#define EMU10K1_GPR_TRANSLATION_TREBLE 3
+#define EMU10K1_GPR_TRANSLATION_ONOFF 4
+
+enum emu10k1_ctl_elem_iface {
+ EMU10K1_CTL_ELEM_IFACE_MIXER = 2, /* virtual mixer device */
+ EMU10K1_CTL_ELEM_IFACE_PCM = 3, /* PCM device */
+};
+
+struct emu10k1_ctl_elem_id {
+ unsigned int pad; /* don't use */
+ int iface; /* interface identifier */
+ unsigned int device; /* device/client number */
+ unsigned int subdevice; /* subdevice (substream) number */
+ unsigned char name[44]; /* ASCII name of item */
+ unsigned int index; /* index of item */
+};
+
+struct snd_emu10k1_fx8010_control_gpr {
+ struct emu10k1_ctl_elem_id id; /* full control ID definition */
+ unsigned int vcount; /* visible count */
+ unsigned int count; /* count of GPR (1..16) */
+ unsigned short gpr[32]; /* GPR number(s) */
+ unsigned int value[32]; /* initial values */
+ unsigned int min; /* minimum range */
+ unsigned int max; /* maximum range */
+ unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */
+ const unsigned int *tlv;
+};
+
+/* old ABI without TLV support */
+struct snd_emu10k1_fx8010_control_old_gpr {
+ struct emu10k1_ctl_elem_id id;
+ unsigned int vcount;
+ unsigned int count;
+ unsigned short gpr[32];
+ unsigned int value[32];
+ unsigned int min;
+ unsigned int max;
+ unsigned int translation;
+};
+
+struct snd_emu10k1_fx8010_code {
+ char name[128];
+
+ __EMU10K1_DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
+ __u32 *gpr_map; /* initializers */
+
+ unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
+ struct snd_emu10k1_fx8010_control_gpr *gpr_add_controls; /* GPR controls to add/replace */
+
+ unsigned int gpr_del_control_count; /* count of GPR controls to remove */
+ struct emu10k1_ctl_elem_id *gpr_del_controls; /* IDs of GPR controls to remove */
+
+ unsigned int gpr_list_control_count; /* count of GPR controls to list */
+ unsigned int gpr_list_control_total; /* total count of GPR controls */
+ struct snd_emu10k1_fx8010_control_gpr *gpr_list_controls; /* listed GPR controls */
+
+ __EMU10K1_DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
+ __u32 *tram_data_map; /* data initializers */
+ __u32 *tram_addr_map; /* map initializers */
+
+ __EMU10K1_DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
+ __u32 *code; /* one instruction - 64 bits */
+};
+
+struct snd_emu10k1_fx8010_tram {
+ unsigned int address; /* 31.bit == 1 -> external TRAM */
+ unsigned int size; /* size in samples (4 bytes) */
+ unsigned int *samples; /* pointer to samples (20-bit) */
+ /* NULL->clear memory */
+};
+
+struct snd_emu10k1_fx8010_pcm_rec {
+ unsigned int substream; /* substream number */
+ unsigned int res1; /* reserved */
+ unsigned int channels; /* 16-bit channels count, zero = remove this substream */
+ unsigned int tram_start; /* ring buffer position in TRAM (in samples) */
+ unsigned int buffer_size; /* count of buffered samples */
+ unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */
+ unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
+ unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */
+ unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */
+ unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */
+ unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */
+ unsigned char pad; /* reserved */
+ unsigned char etram[32]; /* external TRAM address & data (one per channel) */
+ unsigned int res2; /* reserved */
+};
+
+#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
+#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
+#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int)
+#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80)
+#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81)
+#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
+#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int)
+#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int)
+
+#ifndef __KERNEL__
+/* typedefs for compatibility to user-space */
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
+typedef struct emu10k1_ctl_elem_id emu10k1_ctl_elem_id_t;
+#endif
+
+#endif /* _UAPI__SOUND_EMU10K1_H */
diff --git a/include/sound/uapi/hdsp.h b/include/sound/uapi/hdsp.h
new file mode 100644
index 00000000..88c92a3f
--- /dev/null
+++ b/include/sound/uapi/hdsp.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+#ifndef __SOUND_HDSP_H
+#define __SOUND_HDSP_H
+
+/*
+ * Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define HDSP_MATRIX_MIXER_SIZE 2048
+
+enum HDSP_IO_Type {
+ Digiface,
+ Multiface,
+ H9652,
+ H9632,
+ RPM,
+ Undefined,
+};
+
+struct hdsp_peak_rms {
+ __u32 input_peaks[26];
+ __u32 playback_peaks[26];
+ __u32 output_peaks[28];
+ __u64 input_rms[26];
+ __u64 playback_rms[26];
+ /* These are only used for H96xx cards */
+ __u64 output_rms[26];
+};
+
+#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
+
+struct hdsp_config_info {
+ unsigned char pref_sync_ref;
+ unsigned char wordclock_sync_check;
+ unsigned char spdif_sync_check;
+ unsigned char adatsync_sync_check;
+ unsigned char adat_sync_check[3];
+ unsigned char spdif_in;
+ unsigned char spdif_out;
+ unsigned char spdif_professional;
+ unsigned char spdif_emphasis;
+ unsigned char spdif_nonaudio;
+ unsigned int spdif_sample_rate;
+ unsigned int system_sample_rate;
+ unsigned int autosync_sample_rate;
+ unsigned char system_clock_mode;
+ unsigned char clock_source;
+ unsigned char autosync_ref;
+ unsigned char line_out;
+ unsigned char passthru;
+ unsigned char da_gain;
+ unsigned char ad_gain;
+ unsigned char phone_gain;
+ unsigned char xlr_breakout_cable;
+ unsigned char analog_extension_board;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
+
+struct hdsp_firmware {
+ void *firmware_data; /* 24413 x 4 bytes */
+};
+
+#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
+
+struct hdsp_version {
+ enum HDSP_IO_Type io_type;
+ unsigned short firmware_rev;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version)
+
+struct hdsp_mixer {
+ unsigned short matrix[HDSP_MATRIX_MIXER_SIZE];
+};
+
+#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer)
+
+struct hdsp_9632_aeb {
+ int aebi;
+ int aebo;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
+
+/* typedefs for compatibility to user-space */
+typedef enum HDSP_IO_Type HDSP_IO_Type;
+typedef struct hdsp_peak_rms hdsp_peak_rms_t;
+typedef struct hdsp_config_info hdsp_config_info_t;
+typedef struct hdsp_firmware hdsp_firmware_t;
+typedef struct hdsp_version hdsp_version_t;
+typedef struct hdsp_mixer hdsp_mixer_t;
+typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
+
+#endif /* __SOUND_HDSP_H */
diff --git a/include/sound/uapi/hdspm.h b/include/sound/uapi/hdspm.h
new file mode 100644
index 00000000..2d91f90e
--- /dev/null
+++ b/include/sound/uapi/hdspm.h
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+#ifndef __SOUND_HDSPM_H
+#define __SOUND_HDSPM_H
+/*
+ * Copyright (C) 2003 Winfried Ritsch (IEM)
+ * based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
+#define HDSPM_MAX_CHANNELS 64
+
+enum hdspm_io_type {
+ MADI,
+ MADIface,
+ AIO,
+ AES32,
+ RayDAT
+};
+
+enum hdspm_speed {
+ ss,
+ ds,
+ qs
+};
+
+/* -------------------- IOCTL Peak/RMS Meters -------------------- */
+
+struct hdspm_peak_rms {
+ __u32 input_peaks[64];
+ __u32 playback_peaks[64];
+ __u32 output_peaks[64];
+
+ __u64 input_rms[64];
+ __u64 playback_rms[64];
+ __u64 output_rms[64];
+
+ __u8 speed; /* enum {ss, ds, qs} */
+ int status2;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
+ _IOR('H', 0x42, struct hdspm_peak_rms)
+
+/* ------------ CONFIG block IOCTL ---------------------- */
+
+struct hdspm_config {
+ unsigned char pref_sync_ref;
+ unsigned char wordclock_sync_check;
+ unsigned char madi_sync_check;
+ unsigned int system_sample_rate;
+ unsigned int autosync_sample_rate;
+ unsigned char system_clock_mode;
+ unsigned char clock_source;
+ unsigned char autosync_ref;
+ unsigned char line_out;
+ unsigned int passthru;
+ unsigned int analog_out;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG \
+ _IOR('H', 0x41, struct hdspm_config)
+
+/*
+ * If there's a TCO (TimeCode Option) board installed,
+ * there are further options and status data available.
+ * The hdspm_ltc structure contains the current SMPTE
+ * timecode and some status information and can be
+ * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the
+ * hdspm_status struct.
+ */
+
+enum hdspm_ltc_format {
+ format_invalid,
+ fps_24,
+ fps_25,
+ fps_2997,
+ fps_30
+};
+
+enum hdspm_ltc_frame {
+ frame_invalid,
+ drop_frame,
+ full_frame
+};
+
+enum hdspm_ltc_input_format {
+ ntsc,
+ pal,
+ no_video
+};
+
+struct hdspm_ltc {
+ unsigned int ltc;
+
+ enum hdspm_ltc_format format;
+ enum hdspm_ltc_frame frame;
+ enum hdspm_ltc_input_format input_format;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_ltc)
+
+/*
+ * The status data reflects the device's current state
+ * as determined by the card's configuration and
+ * connection status.
+ */
+
+enum hdspm_sync {
+ hdspm_sync_no_lock = 0,
+ hdspm_sync_lock = 1,
+ hdspm_sync_sync = 2
+};
+
+enum hdspm_madi_input {
+ hdspm_input_optical = 0,
+ hdspm_input_coax = 1
+};
+
+enum hdspm_madi_channel_format {
+ hdspm_format_ch_64 = 0,
+ hdspm_format_ch_56 = 1
+};
+
+enum hdspm_madi_frame_format {
+ hdspm_frame_48 = 0,
+ hdspm_frame_96 = 1
+};
+
+enum hdspm_syncsource {
+ syncsource_wc = 0,
+ syncsource_madi = 1,
+ syncsource_tco = 2,
+ syncsource_sync = 3,
+ syncsource_none = 4
+};
+
+struct hdspm_status {
+ __u8 card_type; /* enum hdspm_io_type */
+ enum hdspm_syncsource autosync_source;
+
+ __u64 card_clock;
+ __u32 master_period;
+
+ union {
+ struct {
+ __u8 sync_wc; /* enum hdspm_sync */
+ __u8 sync_madi; /* enum hdspm_sync */
+ __u8 sync_tco; /* enum hdspm_sync */
+ __u8 sync_in; /* enum hdspm_sync */
+ __u8 madi_input; /* enum hdspm_madi_input */
+ __u8 channel_format; /* enum hdspm_madi_channel_format */
+ __u8 frame_format; /* enum hdspm_madi_frame_format */
+ } madi;
+ } card_specific;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_STATUS \
+ _IOR('H', 0x47, struct hdspm_status)
+
+/*
+ * Get information about the card and its add-ons.
+ */
+
+#define HDSPM_ADDON_TCO 1
+
+struct hdspm_version {
+ __u8 card_type; /* enum hdspm_io_type */
+ char cardname[20];
+ unsigned int serial;
+ unsigned short firmware_rev;
+ int addons;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version)
+
+/* ------------- get Matrix Mixer IOCTL --------------- */
+
+/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte =
+ * 32768 Bytes
+ */
+
+/* organisation is 64 channelfader in a continuous memory block */
+/* equivalent to hardware definition, maybe for future feature of mmap of
+ * them
+ */
+/* each of 64 outputs has 64 infader and 64 outfader:
+ Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
+
+#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
+
+struct hdspm_channelfader {
+ unsigned int in[HDSPM_MIXER_CHANNELS];
+ unsigned int pb[HDSPM_MIXER_CHANNELS];
+};
+
+struct hdspm_mixer {
+ struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS];
+};
+
+struct hdspm_mixer_ioctl {
+ struct hdspm_mixer *mixer;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
+
+/* typedefs for compatibility to user-space */
+typedef struct hdspm_peak_rms hdspm_peak_rms_t;
+typedef struct hdspm_config_info hdspm_config_info_t;
+typedef struct hdspm_version hdspm_version_t;
+typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
+typedef struct hdspm_mixer hdspm_mixer_t;
+
+
+#endif
diff --git a/include/sound/uapi/sb16_csp.h b/include/sound/uapi/sb16_csp.h
new file mode 100644
index 00000000..e6485148
--- /dev/null
+++ b/include/sound/uapi/sb16_csp.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
+ * Takashi Iwai <tiwai@suse.de>
+ *
+ * SB16ASP/AWE32 CSP control
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_SB16_CSP_H
+#define _UAPI__SOUND_SB16_CSP_H
+
+
+/* CSP modes */
+#define SNDRV_SB_CSP_MODE_NONE 0x00
+#define SNDRV_SB_CSP_MODE_DSP_READ 0x01 /* Record from DSP */
+#define SNDRV_SB_CSP_MODE_DSP_WRITE 0x02 /* Play to DSP */
+#define SNDRV_SB_CSP_MODE_QSOUND 0x04 /* QSound */
+
+/* CSP load flags */
+#define SNDRV_SB_CSP_LOAD_FROMUSER 0x01
+#define SNDRV_SB_CSP_LOAD_INITBLOCK 0x02
+
+/* CSP sample width */
+#define SNDRV_SB_CSP_SAMPLE_8BIT 0x01
+#define SNDRV_SB_CSP_SAMPLE_16BIT 0x02
+
+/* CSP channels */
+#define SNDRV_SB_CSP_MONO 0x01
+#define SNDRV_SB_CSP_STEREO 0x02
+
+/* CSP rates */
+#define SNDRV_SB_CSP_RATE_8000 0x01
+#define SNDRV_SB_CSP_RATE_11025 0x02
+#define SNDRV_SB_CSP_RATE_22050 0x04
+#define SNDRV_SB_CSP_RATE_44100 0x08
+#define SNDRV_SB_CSP_RATE_ALL 0x0f
+
+/* CSP running state */
+#define SNDRV_SB_CSP_ST_IDLE 0x00
+#define SNDRV_SB_CSP_ST_LOADED 0x01
+#define SNDRV_SB_CSP_ST_RUNNING 0x02
+#define SNDRV_SB_CSP_ST_PAUSED 0x04
+#define SNDRV_SB_CSP_ST_AUTO 0x08
+#define SNDRV_SB_CSP_ST_QSOUND 0x10
+
+/* maximum QSound value (180 degrees right) */
+#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT 0x20
+
+/* maximum microcode RIFF file size */
+#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000
+
+/* microcode header */
+struct snd_sb_csp_mc_header {
+ char codec_name[16]; /* id name of codec */
+ unsigned short func_req; /* requested function */
+};
+
+/* microcode to be loaded */
+struct snd_sb_csp_microcode {
+ struct snd_sb_csp_mc_header info;
+ unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
+};
+
+/* start CSP with sample_width in mono/stereo */
+struct snd_sb_csp_start {
+ int sample_width; /* sample width, look above */
+ int channels; /* channels, look above */
+};
+
+/* CSP information */
+struct snd_sb_csp_info {
+ char codec_name[16]; /* id name of codec */
+ unsigned short func_nr; /* function number */
+ unsigned int acc_format; /* accepted PCM formats */
+ unsigned short acc_channels; /* accepted channels */
+ unsigned short acc_width; /* accepted sample width */
+ unsigned short acc_rates; /* accepted sample rates */
+ unsigned short csp_mode; /* CSP mode, see above */
+ unsigned short run_channels; /* current channels */
+ unsigned short run_width; /* current sample width */
+ unsigned short version; /* version id: 0x10 - 0x1f */
+ unsigned short state; /* state bits */
+};
+
+/* HWDEP controls */
+/* get CSP information */
+#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info)
+/* load microcode to CSP */
+/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
+ * defined for some architectures like MIPS, and it leads to build errors.
+ * (x86 and co have 14-bit size, thus it's valid, though.)
+ * As a workaround for skipping the size-limit check, here we don't use the
+ * normal _IOW() macro but _IOC() with the manual argument.
+ */
+#define SNDRV_SB_CSP_IOCTL_LOAD_CODE \
+ _IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
+/* unload microcode from CSP */
+#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
+/* start CSP */
+#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start)
+/* stop CSP */
+#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14)
+/* pause CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15)
+/* restart CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16)
+
+
+#endif /* _UAPI__SOUND_SB16_CSP_H */
diff --git a/include/sound/uapi/sscape_ioctl.h b/include/sound/uapi/sscape_ioctl.h
new file mode 100644
index 00000000..c6653ebf
--- /dev/null
+++ b/include/sound/uapi/sscape_ioctl.h
@@ -0,0 +1,21 @@
+#ifndef SSCAPE_IOCTL_H
+#define SSCAPE_IOCTL_H
+
+
+struct sscape_bootblock
+{
+ unsigned char code[256];
+ unsigned version;
+};
+
+#define SSCAPE_MICROCODE_SIZE 65536
+
+struct sscape_microcode
+{
+ unsigned char *code;
+};
+
+#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock)
+#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode)
+
+#endif
diff --git a/include/sound/uapi/tlv.h b/include/sound/uapi/tlv.h
new file mode 100644
index 00000000..7d6d65f6
--- /dev/null
+++ b/include/sound/uapi/tlv.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __UAPI_SOUND_TLV_H
+#define __UAPI_SOUND_TLV_H
+
+#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */
+#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
+#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */
+#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */
+#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */
+#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */
+
+/*
+ * channel-mapping TLV items
+ * TLV length must match with num_channels
+ */
+#define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */
+#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */
+#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */
+
+/*
+ * TLV structure is right behind the struct snd_ctl_tlv:
+ * unsigned int type - see SNDRV_CTL_TLVT_*
+ * unsigned int length
+ * .... data aligned to sizeof(unsigned int), use
+ * block_length = (length + (sizeof(unsigned int) - 1)) &
+ * ~(sizeof(unsigned int) - 1)) ....
+ */
+#define SNDRV_CTL_TLVD_ITEM(type, ...) \
+ (type), SNDRV_CTL_TLVD_LENGTH(__VA_ARGS__), __VA_ARGS__
+#define SNDRV_CTL_TLVD_LENGTH(...) \
+ ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
+
+/* Accessor offsets for TLV data items */
+#define SNDRV_CTL_TLVO_TYPE 0
+#define SNDRV_CTL_TLVO_LEN 1
+
+#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)
+#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_CONTAINER_ITEM(__VA_ARGS__) \
+ }
+
+#define SNDRV_CTL_TLVD_DB_SCALE_MASK 0xffff
+#define SNDRV_CTL_TLVD_DB_SCALE_MUTE 0x10000
+#define SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \
+ (min), \
+ ((step) & SNDRV_CTL_TLVD_DB_SCALE_MASK) | \
+ ((mute) ? SNDRV_CTL_TLVD_DB_SCALE_MUTE : 0))
+#define SNDRV_CTL_TLVD_DECLARE_DB_SCALE(name, min, step, mute) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
+ }
+
+/* Accessor offsets for min, mute and step items in dB scale type TLV */
+#define SNDRV_CTL_TLVO_DB_SCALE_MIN 2
+#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 3
+
+/* dB scale specified with min/max values instead of step */
+#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(name, min_dB, max_dB) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
+ }
+#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE(name, min_dB, max_dB) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
+ }
+
+/* Accessor offsets for min, max items in db-minmax types of TLV. */
+#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 2
+#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 3
+
+/* linear volume between min_dB and max_dB (.01dB unit) */
+#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))
+#define SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(name, min_dB, max_dB) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
+ }
+
+/* Accessor offsets for min, max items in db-linear type of TLV. */
+#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 2
+#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 3
+
+/* dB range container:
+ * Items in dB range container must be ordered by their values and by their
+ * dB values. This implies that larger values must correspond with larger
+ * dB values (which is also required for all other mixer controls).
+ */
+/* Each item is: <min> <max> <TLV> */
+#define SNDRV_CTL_TLVD_DB_RANGE_ITEM(...) \
+ SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__)
+#define SNDRV_CTL_TLVD_DECLARE_DB_RANGE(name, ...) \
+ unsigned int name[] = { \
+ SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) \
+ }
+
+#define SNDRV_CTL_TLVD_DB_GAIN_MUTE -9999999
+
+#endif
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 11efce6d..101491a4 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -18,8 +18,7 @@
#include "list.h"
#include "topology.h"
-#define __packed __attribute__((__packed__))
-
+#include <sound/type_compat.h>
#include <sound/asound.h>
#include <sound/asoc.h>
#include <sound/tlv.h>
--
2.24.1
From 75584fe660880b332fbf60dd7968e2ed8b49a38b Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 20 Dec 2019 16:12:50 +0100
Subject: [PATCH 30/69] type_compat: Add missing __s64 and __u64 definitions
for non-Linux
Just for the case without Linux-compatible definitions.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/sound/type_compat.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/sound/type_compat.h b/include/sound/type_compat.h
index d4790c1f..5b765f44 100644
--- a/include/sound/type_compat.h
+++ b/include/sound/type_compat.h
@@ -9,9 +9,11 @@
typedef uint8_t __u8;
typedef uint16_t __u16;
typedef uint32_t __u32;
+typedef uint64_t __u64;
typedef int8_t __s8;
typedef int16_t __s16;
typedef int32_t __s32;
+typedef int64_t __s64;
#include <endian.h>
#include <byteswap.h>
--
2.24.1
From 59792f467b38d6a4c4dffdb30528f7fb03d23d96 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 20 Dec 2019 17:12:37 +0100
Subject: [PATCH 31/69] uapi: Move typedefs from uapi to sound/*
For keeping uapi/*.h cleaner.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/sound/emu10k1.h | 9 +++++++++
include/sound/hdsp.h | 10 ++++++++++
include/sound/hdspm.h | 8 ++++++++
include/sound/sb16_csp.h | 4 ++++
include/sound/uapi/emu10k1.h | 10 ----------
include/sound/uapi/hdsp.h | 9 ---------
include/sound/uapi/hdspm.h | 8 --------
7 files changed, 31 insertions(+), 27 deletions(-)
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index f06ecee5..0832f95b 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1,2 +1,11 @@
#include <alsa/sound/type_compat.h>
#include <alsa/sound/uapi/emu10k1.h>
+#ifndef __emu10k1_type_defined
+#define __emu10k1_type_defined
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
+typedef struct emu10k1_ctl_elem_id emu10k1_ctl_elem_id_t;
+#endif
diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h
index 78fb745b..e8f93156 100644
--- a/include/sound/hdsp.h
+++ b/include/sound/hdsp.h
@@ -1,2 +1,12 @@
#include <alsa/sound/type_compat.h>
#include <alsa/sound/uapi/hdsp.h>
+#ifndef __hdsp_type_defined
+#define __hdsp_type_defined
+typedef enum HDSP_IO_Type HDSP_IO_Type;
+typedef struct hdsp_peak_rms hdsp_peak_rms_t;
+typedef struct hdsp_config_info hdsp_config_info_t;
+typedef struct hdsp_firmware hdsp_firmware_t;
+typedef struct hdsp_version hdsp_version_t;
+typedef struct hdsp_mixer hdsp_mixer_t;
+typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
+#endif
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
index af6d19ed..d9095d9f 100644
--- a/include/sound/hdspm.h
+++ b/include/sound/hdspm.h
@@ -1,2 +1,10 @@
#include <alsa/sound/type_compat.h>
#include <alsa/sound/uapi/hdspm.h>
+#ifndef __hdspm_type_defined
+#define __hdspm_type_defined
+typedef struct hdspm_peak_rms hdspm_peak_rms_t;
+typedef struct hdspm_config_info hdspm_config_info_t;
+typedef struct hdspm_version hdspm_version_t;
+typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
+typedef struct hdspm_mixer hdspm_mixer_t;
+#endif
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
index 24121fcb..fd02bc56 100644
--- a/include/sound/sb16_csp.h
+++ b/include/sound/sb16_csp.h
@@ -1 +1,5 @@
#include <alsa/sound/uapi/sb16_csp.h>
+#ifndef __sb16_csp_type_defined
+#define __sb16_csp_type_defined
+typedef struct snd_sb_csp_microcode snd_sb_csp_microcode_t;
+#endif
diff --git a/include/sound/uapi/emu10k1.h b/include/sound/uapi/emu10k1.h
index c1150e4d..6bcd76f6 100644
--- a/include/sound/uapi/emu10k1.h
+++ b/include/sound/uapi/emu10k1.h
@@ -382,14 +382,4 @@ struct snd_emu10k1_fx8010_pcm_rec {
#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int)
#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int)
-#ifndef __KERNEL__
-/* typedefs for compatibility to user-space */
-typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
-typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
-typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
-typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
-typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
-typedef struct emu10k1_ctl_elem_id emu10k1_ctl_elem_id_t;
-#endif
-
#endif /* _UAPI__SOUND_EMU10K1_H */
diff --git a/include/sound/uapi/hdsp.h b/include/sound/uapi/hdsp.h
index 88c92a3f..7ac2d3f2 100644
--- a/include/sound/uapi/hdsp.h
+++ b/include/sound/uapi/hdsp.h
@@ -97,13 +97,4 @@ struct hdsp_9632_aeb {
#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
-/* typedefs for compatibility to user-space */
-typedef enum HDSP_IO_Type HDSP_IO_Type;
-typedef struct hdsp_peak_rms hdsp_peak_rms_t;
-typedef struct hdsp_config_info hdsp_config_info_t;
-typedef struct hdsp_firmware hdsp_firmware_t;
-typedef struct hdsp_version hdsp_version_t;
-typedef struct hdsp_mixer hdsp_mixer_t;
-typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
-
#endif /* __SOUND_HDSP_H */
diff --git a/include/sound/uapi/hdspm.h b/include/sound/uapi/hdspm.h
index 2d91f90e..3fbfd9dc 100644
--- a/include/sound/uapi/hdspm.h
+++ b/include/sound/uapi/hdspm.h
@@ -219,12 +219,4 @@ struct hdspm_mixer_ioctl {
/* use indirect access due to the limit of ioctl bit size */
#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
-/* typedefs for compatibility to user-space */
-typedef struct hdspm_peak_rms hdspm_peak_rms_t;
-typedef struct hdspm_config_info hdspm_config_info_t;
-typedef struct hdspm_version hdspm_version_t;
-typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
-typedef struct hdspm_mixer hdspm_mixer_t;
-
-
#endif
--
2.24.1
From 9e2bbccfcc8069a676519149a280f20c1e05f0ac Mon Sep 17 00:00:00 2001
From: David Ward <david.ward@ll.mit.edu>
Date: Fri, 3 Jan 2020 13:05:51 -0500
Subject: [PATCH 32/69] Update the attributes.m4 macro file from xine
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This file was imported from the xine project. Update it to the current
revision, which resolves the "no AC_LANG_SOURCE call detected in body"
warnings with Autoconf 2.68 or later.
Cc: Diego Pettenò <flameeyes@gmail.com>
Signed-off-by: David Ward <david.ward@ll.mit.edu>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
m4/attributes.m4 | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/m4/attributes.m4 b/m4/attributes.m4
index e86456a4..3d9c256a 100644
--- a/m4/attributes.m4
+++ b/m4/attributes.m4
@@ -1,6 +1,6 @@
dnl Macros to check the presence of generic (non-typed) symbols.
-dnl Copyright (c) 2006-2007 Diego Pettenò <flameeyes@gmail.com>
-dnl Copyright (c) 2006-2007 xine project
+dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
+dnl Copyright (c) 2006-2008 xine project
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ dnl License when using or distributing such scripts, even though portions
dnl of the text of the Macro appear in them. The GNU General Public
dnl License (GPL) does govern all other use of the material that
dnl constitutes the Autoconf Macro.
-dnl
+dnl
dnl This special exception to the GPL applies to versions of the
dnl Autoconf Macro released by this project. When you make and
dnl distribute a modified version of the Autoconf Macro, you may extend
@@ -39,7 +39,7 @@ AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [
AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]),
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
- AC_COMPILE_IFELSE([int a;],
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])],
[eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_cflags_$1])='no'"])
CFLAGS="$ac_save_CFLAGS"
@@ -71,7 +71,7 @@ AC_DEFUN([CC_CHECK_CFLAG_APPEND], [
)
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
- [CFLAGS="$CFLAGS $1"; $2], [$3])
+ [CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3])
])
dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not])
@@ -89,7 +89,7 @@ AC_DEFUN([CC_CHECK_LDFLAGS], [
AS_TR_SH([cc_cv_ldflags_$1]),
[ac_save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $1"
- AC_LINK_IFELSE([int main() { return 1; }],
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])],
[eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_ldflags_$1])="])
LDFLAGS="$ac_save_LDFLAGS"
@@ -109,14 +109,21 @@ AC_DEFUN([CC_NOUNDEFINED], [
dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
dnl are requested, as different implementations are present; to avoid problems
dnl use -Wl,-z,defs only for those platform not behaving this way.
- *-freebsd*) ;;
+ dnl
+ dnl MinGW platforms: for libraries required -no-undefined,
+ dnl use it only for libraries in mingw32-w64
+
+ *-freebsd* | *-openbsd*) ;;
+ *-mingw*)
+ LDFLAGS_NOUNDEFINED="-no-undefined"
+ ;;
*)
dnl First of all check for the --no-undefined variant of GNU ld. This allows
dnl for a much more readable commandline, so that people can understand what
dnl it does without going to look for what the heck -z defs does.
- for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
+ for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
- break
+ if test "x$LDFLAGS_NOUNDEFINED" = "x"; then break; fi
done
;;
esac
@@ -147,7 +154,7 @@ AC_DEFUN([CC_CHECK_ATTRIBUTE], [
AS_TR_SH([cc_cv_attribute_$1]),
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $cc_cv_werror"
- AC_COMPILE_IFELSE([$3],
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
[eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
CFLAGS="$ac_save_CFLAGS"
@@ -257,7 +264,7 @@ AC_DEFUN([CC_FLAG_VISIBILITY], [
cc_cv_flag_visibility='yes',
cc_cv_flag_visibility='no')
CFLAGS="$cc_flag_visibility_save_CFLAGS"])
-
+
AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
[AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
[Define this if the compiler supports the -fvisibility flag])
@@ -295,11 +302,11 @@ AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $cc_cv_werror"
for cc_attribute_align_try in 64 32 16 8 4 2; do
- AC_COMPILE_IFELSE([
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int main() {
static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
return c;
- }], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
+ }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
done
CFLAGS="$ac_save_CFLAGS"
])
--
2.24.1
From f373bf1f6eea0f2037a7714e9b55aa65fa00b889 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 14 Dec 2019 13:36:09 +0100
Subject: [PATCH 33/69] topology: avoid to use the atoi() directly when
expected
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/channel.c | 10 +--
src/topology/ctl.c | 37 +++++-----
src/topology/dapm.c | 32 +++++----
src/topology/data.c | 14 ++--
src/topology/elem.c | 9 ++-
src/topology/ops.c | 2 +-
src/topology/parser.c | 29 ++++++++
src/topology/pcm.c | 148 +++++++++++++++++---------------------
src/topology/tplg_local.h | 2 +
9 files changed, 150 insertions(+), 133 deletions(-)
diff --git a/src/topology/channel.c b/src/topology/channel.c
index 60f7e219..4569eb31 100644
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -80,8 +80,8 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
snd_config_iterator_t i, next;
snd_config_t *n;
struct snd_soc_tplg_channel *channel = private;
- const char *id, *value;
- int channel_id;
+ const char *id;
+ int channel_id, value;
if (tplg->channel_idx >= SND_SOC_TPLG_MAX_CHAN)
return -EINVAL;
@@ -109,13 +109,13 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
continue;
/* get value */
- if (snd_config_get_string(n, &value) < 0)
+ if (tplg_get_integer(n, &value, 0) < 0)
continue;
if (strcmp(id, "reg") == 0)
- channel->reg = atoi(value);
+ channel->reg = value;
else if (strcmp(id, "shift") == 0)
- channel->shift = atoi(value);
+ channel->shift = value;
tplg_dbg("\t\t%s = %s\n", id, value);
}
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 1db0b16e..e1896f46 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -286,7 +286,8 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
snd_config_t *n;
struct snd_soc_tplg_ctl_tlv *tplg_tlv;
struct snd_soc_tplg_tlv_dbscale *scale;
- const char *id = NULL, *value = NULL;
+ const char *id = NULL;
+ int val;
tplg_dbg(" scale: %s\n", elem->id);
@@ -310,18 +311,18 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
}
/* get value */
- if (snd_config_get_string(n, &value) < 0)
+ if (tplg_get_integer(n, &val, 0))
continue;
- tplg_dbg("\t%s = %s\n", id, value);
+ tplg_dbg("\t%s = %i\n", id, val);
/* get TLV data */
if (strcmp(id, "min") == 0)
- scale->min = atoi(value);
+ scale->min = val;
else if (strcmp(id, "step") == 0)
- scale->step = atoi(value);
+ scale->step = val;
else if (strcmp(id, "mute") == 0)
- scale->mute = atoi(value);
+ scale->mute = val;
else
SNDERR("error: unknown key %s\n", id);
}
@@ -372,7 +373,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id, *val = NULL;
- int err;
+ int err, ival;
bool access_set = false, tlv_set = false;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES);
@@ -398,37 +399,37 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
continue;
if (strcmp(id, "base") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- be->base = atoi(val);
+ be->base = ival;
tplg_dbg("\t%s: %d\n", id, be->base);
continue;
}
if (strcmp(id, "num_regs") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- be->num_regs = atoi(val);
+ be->num_regs = ival;
tplg_dbg("\t%s: %d\n", id, be->num_regs);
continue;
}
if (strcmp(id, "max") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- be->max = atoi(val);
+ be->max = ival;
tplg_dbg("\t%s: %d\n", id, be->max);
continue;
}
if (strcmp(id, "mask") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 16))
return -EINVAL;
- be->mask = strtol(val, NULL, 16);
+ be->mask = ival;
tplg_dbg("\t%s: %d\n", id, be->mask);
continue;
}
@@ -598,7 +599,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id, *val = NULL;
- int err, j;
+ int err, j, ival;
bool access_set = false, tlv_set = false;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER);
@@ -647,10 +648,10 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
}
if (strcmp(id, "max") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- mc->max = atoi(val);
+ mc->max = ival;
tplg_dbg("\t%s: %d\n", id, mc->max);
continue;
}
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index ce469131..c6fd793d 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -426,7 +426,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
snd_config_iterator_t i, next;
snd_config_t *n;
int err;
- const char *graph_id, *val = NULL;
+ const char *graph_id;
int index = -1;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
@@ -445,9 +445,10 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
}
if (strcmp(id, "index") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &index, 0))
+ return -EINVAL;
+ if (index < 0)
return -EINVAL;
- index = atoi(val);
}
if (strcmp(id, "lines") == 0) {
@@ -479,6 +480,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
snd_config_t *n;
const char *id, *val = NULL;
int widget_type, err;
+ int ival;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DAPM_WIDGET);
if (!elem)
@@ -540,55 +542,55 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
}
if (strcmp(id, "shift") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- widget->shift = atoi(val);
+ widget->shift = ival;
tplg_dbg("\t%s: %d\n", id, widget->shift);
continue;
}
if (strcmp(id, "reg") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- widget->reg = atoi(val);
+ widget->reg = ival;
tplg_dbg("\t%s: %d\n", id, widget->reg);
continue;
}
if (strcmp(id, "invert") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- widget->invert = atoi(val);
+ widget->invert = ival;
tplg_dbg("\t%s: %d\n", id, widget->invert);
continue;
}
if (strcmp(id, "subseq") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- widget->subseq= atoi(val);
+ widget->subseq = ival;
tplg_dbg("\t%s: %d\n", id, widget->subseq);
continue;
}
if (strcmp(id, "event_type") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- widget->event_type = atoi(val);
+ widget->event_type = ival;
tplg_dbg("\t%s: %d\n", id, widget->event_type);
continue;
}
if (strcmp(id, "event_flags") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- widget->event_flags = atoi(val);
+ widget->event_flags = ival;
tplg_dbg("\t%s: %d\n", id, widget->event_flags);
continue;
}
diff --git a/src/topology/data.c b/src/topology/data.c
index 729ce1f4..0edfe54f 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -800,10 +800,10 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
{
snd_config_iterator_t i, next;
snd_config_t *n;
- const char *id, *value;
+ const char *id;
struct tplg_elem *elem;
struct tplg_vendor_tokens *tokens;
- int num_tokens = 0;
+ int num_tokens = 0, value;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TOKEN);
if (!elem)
@@ -830,12 +830,12 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
if (snd_config_get_id(n, &id) < 0)
continue;
- if (snd_config_get_string(n, &value) < 0)
+ if (tplg_get_integer(n, &value, 0))
continue;
snd_strlcpy(tokens->token[tokens->num_tokens].id, id,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tokens->token[tokens->num_tokens].value = atoi(value);
+ tokens->token[tokens->num_tokens].value = value;
tplg_dbg("\t\t %s : %d\n", tokens->token[tokens->num_tokens].id,
tokens->token[tokens->num_tokens].value);
tokens->num_tokens++;
@@ -1013,7 +1013,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id, *val = NULL;
- int err = 0;
+ int err = 0, ival;
struct tplg_elem *elem;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DATA);
@@ -1071,10 +1071,10 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
}
if (strcmp(id, "type") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (tplg_get_integer(n, &ival, 0))
return -EINVAL;
- elem->vendor_type = atoi(val);
+ elem->vendor_type = ival;
tplg_dbg("\t%s: %d\n", id, elem->index);
continue;
}
diff --git a/src/topology/elem.c b/src/topology/elem.c
index d8618cc9..f2076f79 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -153,7 +153,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
enum snd_tplg_type type)
{
struct tplg_elem *elem;
- const char *id, *val = NULL;
+ const char *id;
int obj_size = 0;
void *obj;
snd_config_iterator_t i, next;
@@ -178,11 +178,14 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
if (snd_config_get_id(n, &id))
continue;
if (strcmp(id, "index") == 0) {
- if (snd_config_get_string(n, &val) < 0) {
+ if (tplg_get_integer(n, &elem->index, 0)) {
+ free(elem);
+ return NULL;
+ }
+ if (elem->index < 0) {
free(elem);
return NULL;
}
- elem->index = atoi(val);
}
}
} else if (name != NULL)
diff --git a/src/topology/ops.c b/src/topology/ops.c
index 0f4295a2..073acdcb 100644
--- a/src/topology/ops.c
+++ b/src/topology/ops.c
@@ -42,7 +42,7 @@ static int lookup_ops(const char *c)
}
/* cant find string name in our table so we use its ID number */
- return atoi(c);
+ return strtol(c, NULL, 0);
}
/* Parse Control operations. Ops can come from standard names above or
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 5940692d..7e657809 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -21,6 +21,35 @@
#include "list.h"
#include "tplg_local.h"
+/*
+ * Get integer value
+ */
+int tplg_get_integer(snd_config_t *n, int *val, int base)
+{
+ const char *str;
+ long lval;
+ int err;
+
+ switch (snd_config_get_type(n)) {
+ case SND_CONFIG_TYPE_INTEGER:
+ err = snd_config_get_integer(n, &lval);
+ if (err < 0)
+ return err;
+ if (lval < INT_MIN || lval > INT_MAX)
+ return -EINVAL;
+ *val = lval;
+ return err;
+ case SND_CONFIG_TYPE_STRING:
+ err = snd_config_get_string(n, &str);
+ if (err < 0)
+ return err;
+ *val = strtol(str, NULL, base);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
/*
* Parse compound
*/
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 98a8df97..d6c52b47 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -368,6 +368,24 @@ static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str)
return 0;
}
+static int parse_unsigned(snd_config_t *n, unsigned int *dst)
+{
+ int ival;
+
+ if (tplg_get_integer(n, &ival, 0) < 0)
+ return -EINVAL;
+
+ *dst = ival;
+#if TPLG_DEBUG
+ {
+ const char *id;
+ if (snd_config_get_id(n, &id) >= 0)
+ tplg_dbg("\t\t%s: %d\n", id, *dst);
+ }
+#endif
+ return 0;
+}
+
/* Parse pcm stream capabilities */
int tplg_parse_stream_caps(snd_tplg_t *tplg,
snd_config_t *cfg,
@@ -402,10 +420,10 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
if (id[0] == '#')
continue;
- if (snd_config_get_string(n, &val) < 0)
- return -EINVAL;
-
if (strcmp(id, "formats") == 0) {
+ if (snd_config_get_string(n, &val) < 0)
+ return -EINVAL;
+
s = strdup(val);
if (s == NULL)
return -ENOMEM;
@@ -421,6 +439,9 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
}
if (strcmp(id, "rates") == 0) {
+ if (snd_config_get_string(n, &val) < 0)
+ return -EINVAL;
+
s = strdup(val);
if (!s)
return -ENOMEM;
@@ -436,68 +457,68 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
}
if (strcmp(id, "rate_min") == 0) {
- sc->rate_min = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->rate_min);
+ if (parse_unsigned(n, &sc->rate_min))
+ return -EINVAL;
continue;
}
if (strcmp(id, "rate_max") == 0) {
- sc->rate_max = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->rate_max);
+ if (parse_unsigned(n, &sc->rate_max))
+ return -EINVAL;
continue;
}
if (strcmp(id, "channels_min") == 0) {
- sc->channels_min = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->channels_min);
+ if (parse_unsigned(n, &sc->channels_min))
+ return -EINVAL;
continue;
}
if (strcmp(id, "channels_max") == 0) {
- sc->channels_max = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->channels_max);
+ if (parse_unsigned(n, &sc->channels_max))
+ return -EINVAL;
continue;
}
if (strcmp(id, "periods_min") == 0) {
- sc->periods_min = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->periods_min);
+ if (parse_unsigned(n, &sc->periods_min))
+ return -EINVAL;
continue;
}
if (strcmp(id, "periods_max") == 0) {
- sc->periods_max = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->periods_max);
+ if (parse_unsigned(n, &sc->periods_max))
+ return -EINVAL;
continue;
}
if (strcmp(id, "period_size_min") == 0) {
- sc->period_size_min = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->period_size_min);
+ if (parse_unsigned(n, &sc->period_size_min))
+ return -EINVAL;
continue;
}
if (strcmp(id, "period_size_max") == 0) {
- sc->period_size_max = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->period_size_max);
+ if (parse_unsigned(n, &sc->period_size_max))
+ return -EINVAL;
continue;
}
if (strcmp(id, "buffer_size_min") == 0) {
- sc->buffer_size_min = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->buffer_size_min);
+ if (parse_unsigned(n, &sc->buffer_size_min))
+ return -EINVAL;
continue;
}
if (strcmp(id, "buffer_size_max") == 0) {
- sc->buffer_size_max = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->buffer_size_max);
+ if (parse_unsigned(n, &sc->buffer_size_max))
+ return -EINVAL;
continue;
}
if (strcmp(id, "sig_bits") == 0) {
- sc->sig_bits = atoi(val);
- tplg_dbg("\t\t%s: %d\n", id, sc->sig_bits);
+ if (parse_unsigned(n, &sc->sig_bits))
+ return -EINVAL;
continue;
}
@@ -674,11 +695,8 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
continue;
if (strcmp(id, "id") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &pcm->pcm_id))
return -EINVAL;
-
- pcm->pcm_id = atoi(val);
- tplg_dbg("\t%s: %d\n", id, pcm->pcm_id);
continue;
}
@@ -784,30 +802,21 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
continue;
if (strcmp(id, "id") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &dai->dai_id))
return -EINVAL;
-
- dai->dai_id = atoi(val);
- tplg_dbg("\t%s: %d\n", id, dai->dai_id);
continue;
}
if (strcmp(id, "playback") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &dai->playback))
return -EINVAL;
-
- dai->playback = atoi(val);
- tplg_dbg("\t%s: %d\n", id, dai->playback);
continue;
}
if (strcmp(id, "capture") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &dai->capture))
return -EINVAL;
-
- dai->capture = atoi(val);
- tplg_dbg("\t%s: %d\n", id, dai->capture);
continue;
}
@@ -949,11 +958,8 @@ int tplg_parse_link(snd_tplg_t *tplg,
continue;
if (strcmp(id, "id") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &link->id))
return -EINVAL;
-
- link->id = atoi(val);
- tplg_dbg("\t%s: %d\n", id, link->id);
continue;
}
@@ -975,10 +981,8 @@ int tplg_parse_link(snd_tplg_t *tplg,
}
if (strcmp(id, "default_hw_conf_id") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &link->default_hw_config_id))
return -EINVAL;
-
- link->default_hw_config_id = atoi(val);
continue;
}
@@ -1030,7 +1034,7 @@ int tplg_parse_cc(snd_tplg_t *tplg,
struct tplg_elem *elem;
snd_config_iterator_t i, next;
snd_config_t *n;
- const char *id, *val = NULL;
+ const char *id;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_CC);
if (!elem)
@@ -1054,11 +1058,8 @@ int tplg_parse_cc(snd_tplg_t *tplg,
continue;
if (strcmp(id, "id") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &link->id))
return -EINVAL;
-
- link->id = atoi(val);
- tplg_dbg("\t%s: %d\n", id, link->id);
continue;
}
@@ -1130,11 +1131,8 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
continue;
if (strcmp(id, "id") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->id))
return -EINVAL;
-
- hw_cfg->id = atoi(val);
- tplg_dbg("\t%s: %d\n", id, hw_cfg->id);
continue;
}
@@ -1173,10 +1171,8 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "bclk_freq") == 0 ||
strcmp(id, "bclk_rate") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->bclk_rate))
return -EINVAL;
-
- hw_cfg->bclk_rate = atoi(val);
continue;
}
@@ -1223,19 +1219,15 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "fsync_freq") == 0 ||
strcmp(id, "fsync_rate") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->fsync_rate))
return -EINVAL;
-
- hw_cfg->fsync_rate = atoi(val);
continue;
}
if (strcmp(id, "mclk_freq") == 0 ||
strcmp(id, "mclk_rate") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->mclk_rate))
return -EINVAL;
-
- hw_cfg->mclk_rate = atoi(val);
continue;
}
@@ -1275,50 +1267,38 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
}
if (strcmp(id, "tdm_slots") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->tdm_slots))
return -EINVAL;
-
- hw_cfg->tdm_slots = atoi(val);
continue;
}
if (strcmp(id, "tdm_slot_width") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->tdm_slot_width))
return -EINVAL;
-
- hw_cfg->tdm_slot_width = atoi(val);
continue;
}
if (strcmp(id, "tx_slots") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->tx_slots))
return -EINVAL;
-
- hw_cfg->tx_slots = atoi(val);
continue;
}
if (strcmp(id, "rx_slots") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->rx_slots))
return -EINVAL;
-
- hw_cfg->rx_slots = atoi(val);
continue;
}
if (strcmp(id, "tx_channels") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->tx_channels))
return -EINVAL;
-
- hw_cfg->tx_channels = atoi(val);
continue;
}
if (strcmp(id, "rx_channels") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ if (parse_unsigned(n, &hw_cfg->rx_channels))
return -EINVAL;
-
- hw_cfg->rx_channels = atoi(val);
continue;
}
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 101491a4..991e0b41 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -280,6 +280,8 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base,
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
snd_config_t *cfg, const char *name, enum snd_tplg_type type);
+int tplg_get_integer(snd_config_t *n, int *val, int base);
+
int tplg_parse_channel(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_t *cfg, void *private);
--
2.24.1
From 5925a6d870331c631f85ed4e18a8c5e6459b3c36 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 14 Dec 2019 13:50:04 +0100
Subject: [PATCH 34/69] topology: use snd_config_get_bool() instead own
implementation
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/ctl.c | 9 +++------
src/topology/dapm.c | 9 ++++-----
src/topology/data.c | 15 ++++++++++++---
src/topology/pcm.c | 29 +++++++++++++++--------------
4 files changed, 34 insertions(+), 28 deletions(-)
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index e1896f46..9190efef 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -657,13 +657,10 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
}
if (strcmp(id, "invert") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ ival = snd_config_get_bool(n);
+ if (ival < 0)
return -EINVAL;
-
- if (strcmp(val, "true") == 0)
- mc->invert = 1;
- else if (strcmp(val, "false") == 0)
- mc->invert = 0;
+ mc->invert = ival;
tplg_dbg("\t%s: %d\n", id, mc->invert);
continue;
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index c6fd793d..ad709210 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -479,8 +479,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id, *val = NULL;
- int widget_type, err;
- int ival;
+ int widget_type, err, ival;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DAPM_WIDGET);
if (!elem)
@@ -531,11 +530,11 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
}
if (strcmp(id, "no_pm") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ ival = snd_config_get_bool(n);
+ if (ival < 0)
return -EINVAL;
- if (strcmp(val, "true") == 0)
- widget->reg = -1;
+ widget->reg = ival ? -1 : 0;
tplg_dbg("\t%s: %s\n", id, val);
continue;
diff --git a/src/topology/data.c b/src/topology/data.c
index 0edfe54f..6b1337b3 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -557,6 +557,7 @@ static int parse_tuple_set(snd_config_t *cfg,
unsigned int type, num_tuples = 0;
struct tplg_tuple *tuple;
unsigned long int tuple_val;
+ int ival;
snd_config_get_id(cfg, &id);
@@ -607,25 +608,33 @@ static int parse_tuple_set(snd_config_t *cfg,
switch (type) {
case SND_SOC_TPLG_TUPLE_TYPE_UUID:
+ if (snd_config_get_string(n, &value) < 0)
+ continue;
if (get_uuid(value, tuple->uuid) < 0)
goto err;
break;
case SND_SOC_TPLG_TUPLE_TYPE_STRING:
+ if (snd_config_get_string(n, &value) < 0)
+ continue;
snd_strlcpy(tuple->string, value,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
tplg_dbg("\t\t%s = %s\n", tuple->token, tuple->string);
break;
case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
- if (strcmp(value, "true") == 0)
- tuple->value = 1;
+ ival = snd_config_get_bool(n);
+ if (ival < 0)
+ continue;
+ tuple->value = ival;
tplg_dbg("\t\t%s = %d\n", tuple->token, tuple->value);
break;
case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
case SND_SOC_TPLG_TUPLE_TYPE_WORD:
+ if (snd_config_get_string(n, &value) < 0)
+ continue;
errno = 0;
/* no support for negative value */
tuple_val = strtoul(value, NULL, 0);
@@ -1012,7 +1021,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
{
snd_config_iterator_t i, next;
snd_config_t *n;
- const char *id, *val = NULL;
+ const char *id;
int err = 0, ival;
struct tplg_elem *elem;
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index d6c52b47..6364e24f 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -669,8 +669,8 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
struct tplg_elem *elem;
snd_config_iterator_t i, next;
snd_config_t *n;
- const char *id, *val = NULL;
- int err;
+ const char *id;
+ int err, ival;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_PCM);
if (!elem)
@@ -709,11 +709,11 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
}
if (strcmp(id, "compress") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ ival = snd_config_get_bool(n);
+ if (ival < 0)
return -EINVAL;
- if (strcmp(val, "true") == 0)
- pcm->compress = 1;
+ pcm->compress = ival;
tplg_dbg("\t%s: %s\n", id, val);
continue;
@@ -1107,7 +1107,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id, *val = NULL;
- int ret;
+ int ret, ival;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_HW_CONFIG);
if (!elem)
@@ -1178,11 +1178,11 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "bclk_invert") == 0 ||
strcmp(id, "invert_bclk") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ ival = snd_config_get_bool(n);
+ if (ival < 0)
return -EINVAL;
- if (!strcmp(val, "true"))
- hw_cfg->invert_bclk = true;
+ hw_cfg->invert_bclk = ival;
continue;
}
@@ -1209,11 +1209,11 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "fsync_invert") == 0 ||
strcmp(id, "invert_fsync") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ ival = snd_config_get_bool(n);
+ if (ival < 0)
return -EINVAL;
- if (!strcmp(val, "true"))
- hw_cfg->invert_fsync = true;
+ hw_cfg->invert_fsync = ival;
continue;
}
@@ -1254,10 +1254,11 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "pm_gate_clocks") == 0 ||
strcmp(id, "clock_gated") == 0) {
- if (snd_config_get_string(n, &val) < 0)
+ ival = snd_config_get_bool(n);
+ if (ival < 0)
return -EINVAL;
- if (!strcmp(val, "true"))
+ if (ival)
hw_cfg->clock_gated =
SND_SOC_TPLG_DAI_CLK_GATE_GATED;
else
--
2.24.1
From 1047a5f3c0d39a3b0579db027f52d7facdf44077 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 14 Dec 2019 13:52:18 +0100
Subject: [PATCH 35/69] topology: fix tplg_get_integer() - handle errno ==
ERANGE
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/parser.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 7e657809..667c8d45 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -36,14 +36,19 @@ int tplg_get_integer(snd_config_t *n, int *val, int base)
if (err < 0)
return err;
if (lval < INT_MIN || lval > INT_MAX)
- return -EINVAL;
+ return -ERANGE;
*val = lval;
return err;
case SND_CONFIG_TYPE_STRING:
err = snd_config_get_string(n, &str);
if (err < 0)
return err;
+ errno = 0;
*val = strtol(str, NULL, base);
+ if (errno == ERANGE)
+ return -ERANGE;
+ if (errno && *val == 0)
+ return -EINVAL;
return 0;
default:
return -EINVAL;
--
2.24.1
From 14e43a11873d14ec6f16967c83629237ef44ac38 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 14 Dec 2019 14:05:49 +0100
Subject: [PATCH 36/69] topology: add tplg_get_unsigned() function
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/data.c | 19 +++++-----------
src/topology/parser.c | 47 +++++++++++++++++++++++++++++++++++++++
src/topology/pcm.c | 13 ++---------
src/topology/tplg_local.h | 1 +
4 files changed, 55 insertions(+), 25 deletions(-)
diff --git a/src/topology/data.c b/src/topology/data.c
index 6b1337b3..9807445e 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -556,7 +556,7 @@ static int parse_tuple_set(snd_config_t *cfg,
struct tplg_tuple_set *set;
unsigned int type, num_tuples = 0;
struct tplg_tuple *tuple;
- unsigned long int tuple_val;
+ unsigned int tuple_val;
int ival;
snd_config_get_id(cfg, &id);
@@ -598,10 +598,6 @@ static int parse_tuple_set(snd_config_t *cfg,
if (snd_config_get_id(n, &id) < 0)
continue;
- /* get value */
- if (snd_config_get_string(n, &value) < 0)
- continue;
-
tuple = &set->tuple[set->num_tuples];
snd_strlcpy(tuple->token, id,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
@@ -633,14 +629,9 @@ static int parse_tuple_set(snd_config_t *cfg,
case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
case SND_SOC_TPLG_TUPLE_TYPE_WORD:
- if (snd_config_get_string(n, &value) < 0)
- continue;
- errno = 0;
- /* no support for negative value */
- tuple_val = strtoul(value, NULL, 0);
- if ((errno == ERANGE && tuple_val == ULONG_MAX)
- || (errno != 0 && tuple_val == 0)) {
- SNDERR("error: tuple %s:strtoul fail\n", id);
+ ival = tplg_get_unsigned(n, &tuple_val, 0);
+ if (ival < 0) {
+ SNDERR("error: tuple %s: %s\n", id, snd_strerror(ival));
goto err;
}
@@ -654,7 +645,7 @@ static int parse_tuple_set(snd_config_t *cfg,
goto err;
}
- tuple->value = (unsigned int) tuple_val;
+ tuple->value = tuple_val;
tplg_dbg("\t\t%s = 0x%x\n", tuple->token, tuple->value);
break;
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 667c8d45..f56ad97e 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -55,6 +55,53 @@ int tplg_get_integer(snd_config_t *n, int *val, int base)
}
}
+/*
+ * Get unsigned integer value
+ */
+int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base)
+{
+ const char *str;
+ long lval;
+ long long llval;
+ unsigned long uval;
+ int err;
+
+ switch (snd_config_get_type(n)) {
+ case SND_CONFIG_TYPE_INTEGER:
+ err = snd_config_get_integer(n, &lval);
+ if (err < 0)
+ return err;
+ if (lval < 0 || lval > UINT_MAX)
+ return -ERANGE;
+ *val = lval;
+ return err;
+ case SND_CONFIG_TYPE_INTEGER64:
+ err = snd_config_get_integer64(n, &llval);
+ if (err < 0)
+ return err;
+ if (llval < 0 || llval > UINT_MAX)
+ return -ERANGE;
+ *val = llval;
+ return err;
+ case SND_CONFIG_TYPE_STRING:
+ err = snd_config_get_string(n, &str);
+ if (err < 0)
+ return err;
+ errno = 0;
+ uval = strtoul(str, NULL, base);
+ if (errno == ERANGE && uval == ULONG_MAX)
+ return -ERANGE;
+ if (errno && uval == 0)
+ return -EINVAL;
+ if (uval > UINT_MAX)
+ return -ERANGE;
+ *val = uval;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
/*
* Parse compound
*/
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 6364e24f..9b87549c 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -606,8 +606,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct snd_soc_tplg_pcm *pcm = elem->pcm;
snd_config_iterator_t i, next;
snd_config_t *n;
- const char *id, *value = NULL;
- unsigned long int id_val;
+ const char *id;
snd_config_get_id(cfg, &id);
tplg_dbg("\t\tFE DAI %s:\n", id);
@@ -622,19 +621,11 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
continue;
if (strcmp(id, "id") == 0) {
- if (snd_config_get_string(n, &value) < 0)
- continue;
- errno = 0;
- /* no support for negative value */
- id_val = strtoul(value, NULL, 0);
- if ((errno == ERANGE && id_val == ULONG_MAX)
- || (errno != 0 && id_val == 0)
- || id_val > UINT_MAX) {
+ if (tplg_get_unsigned(n, &pcm->dai_id, 0)) {
SNDERR("error: invalid fe dai ID\n");
return -EINVAL;
}
- pcm->dai_id = (int) id_val;
tplg_dbg("\t\t\tindex: %d\n", pcm->dai_id);
}
}
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 991e0b41..e16c78d4 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -281,6 +281,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
snd_config_t *cfg, const char *name, enum snd_tplg_type type);
int tplg_get_integer(snd_config_t *n, int *val, int base);
+int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base);
int tplg_parse_channel(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_t *cfg, void *private);
--
2.24.1
From 39fb37fef5bd3b3fa7a63e06a5f0a147197fddb9 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 14 Dec 2019 19:13:53 +0100
Subject: [PATCH 37/69] topology: convert builder to use the mallocated memory
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 88 +++++++++++++++++++++++++++++++--------
src/topology/parser.c | 74 +++++++++++++-------------------
src/topology/tplg_local.h | 5 ++-
3 files changed, 103 insertions(+), 64 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index 1a22a453..40943b56 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -29,7 +29,7 @@ static void verbose(snd_tplg_t *tplg, const char *fmt, ...)
return;
va_start(va, fmt);
- fprintf(stdout, "0x%6.6zx/%6.6zd - ", tplg->out_pos, tplg->out_pos);
+ fprintf(stdout, "0x%6.6zx/%6.6zd - ", tplg->bin_pos, tplg->bin_pos);
vfprintf(stdout, fmt, va);
va_end(va);
}
@@ -37,18 +37,11 @@ static void verbose(snd_tplg_t *tplg, const char *fmt, ...)
/* write a block, track the position */
static ssize_t twrite(snd_tplg_t *tplg, void *data, size_t data_size)
{
- ssize_t r = write(tplg->out_fd, data, data_size);
- if (r != (ssize_t)data_size) {
- if (r < 0) {
- SNDERR("error: unable to write: %s", strerror(errno));
- return -errno;
- }
- tplg->out_pos += r;
- SNDERR("error: unable to write (partial)");
+ if (tplg->bin_pos + data_size > tplg->bin_size)
return -EIO;
- }
- tplg->out_pos += r;
- return r;
+ memcpy(tplg->bin + tplg->bin_pos, data, data_size);
+ tplg->bin_pos += data_size;
+ return data_size;
}
/* write out block header to output file */
@@ -71,12 +64,12 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type,
hdr.count = count;
/* make sure file offset is aligned with the calculated HDR offset */
- if (tplg->out_pos != tplg->next_hdr_pos) {
+ if (tplg->bin_pos != tplg->next_hdr_pos) {
SNDERR("error: New header is at offset 0x%zx but file"
" offset 0x%zx is %s by %ld bytes\n",
- tplg->next_hdr_pos, tplg->out_pos,
- tplg->out_pos > tplg->next_hdr_pos ? "ahead" : "behind",
- labs(tplg->out_pos - tplg->next_hdr_pos));
+ tplg->next_hdr_pos, tplg->bin_pos,
+ tplg->bin_pos > tplg->next_hdr_pos ? "ahead" : "behind",
+ labs(tplg->bin_pos - tplg->next_hdr_pos));
return -EINVAL;
}
@@ -163,6 +156,41 @@ static int write_elem_block(snd_tplg_t *tplg,
return 0;
}
+static size_t calc_manifest_size(snd_tplg_t *tplg)
+{
+ return sizeof(struct snd_soc_tplg_hdr) +
+ sizeof(tplg->manifest) +
+ tplg->manifest.priv.size;
+}
+
+static size_t calc_real_size(struct list_head *base)
+{
+ struct list_head *pos;
+ struct tplg_elem *elem, *elem_next;
+ size_t size = 0;
+
+ list_for_each(pos, base) {
+
+ elem = list_entry(pos, struct tplg_elem, list);
+
+ /* compound elems have already been copied to other elems */
+ if (elem->compound_elem)
+ continue;
+
+ if (elem->size <= 0)
+ continue;
+
+ size += elem->size;
+
+ elem_next = list_entry(pos->next, struct tplg_elem, list);
+
+ if ((pos->next == base) || (elem_next->index != elem->index))
+ size += sizeof(struct snd_soc_tplg_hdr);
+ }
+
+ return size;
+}
+
static size_t calc_block_size(struct list_head *base)
{
struct list_head *pos;
@@ -277,9 +305,27 @@ int tplg_write_data(snd_tplg_t *tplg)
};
ssize_t ret;
- size_t size;
+ size_t total_size, size;
unsigned int index;
+ /* calculate total size */
+ total_size = calc_manifest_size(tplg);
+ for (index = 0; index < ARRAY_SIZE(wtable); index++) {
+ wptr = &wtable[index];
+ size = calc_real_size(wptr->list);
+ total_size += size;
+ }
+
+ /* allocate new binary output */
+ free(tplg->bin);
+ tplg->bin = malloc(total_size);
+ tplg->bin_pos = 0;
+ tplg->bin_size = total_size;
+ if (tplg->bin == NULL) {
+ tplg->bin_size = 0;
+ return -ENOMEM;
+ }
+
/* write manifest */
ret = write_manifest_data(tplg);
if (ret < 0) {
@@ -306,7 +352,13 @@ int tplg_write_data(snd_tplg_t *tplg)
}
}
- verbose(tplg, "total size is 0x%zx/%zd\n", tplg->out_pos, tplg->out_pos);
+ verbose(tplg, "total size is 0x%zx/%zd\n", tplg->bin_pos, tplg->bin_pos);
+
+ if (total_size != tplg->bin_pos) {
+ SNDERR("total size mismatch (%zd != %zd)\n",
+ total_size, tplg->bin_pos);
+ return -EINVAL;
+ }
return 0;
}
diff --git a/src/topology/parser.c b/src/topology/parser.c
index f56ad97e..98a9f9e9 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -393,50 +393,29 @@ static int tplg_build_integ(snd_tplg_t *tplg)
return err;
}
-int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
- const char *outfile)
+int snd_tplg_build_file(snd_tplg_t *tplg,
+ const char *infile,
+ const char *outfile)
{
snd_config_t *cfg = NULL;
int err = 0;
- tplg->out_fd =
- open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
- if (tplg->out_fd < 0) {
- SNDERR("error: failed to open %s err %d\n",
- outfile, -errno);
- return -errno;
- }
-
err = tplg_load_config(infile, &cfg);
if (err < 0) {
SNDERR("error: failed to load topology file %s\n",
infile);
- goto out_close;
+ return err;
}
err = tplg_parse_config(tplg, cfg);
if (err < 0) {
SNDERR("error: failed to parse topology\n");
- goto out;
- }
-
- err = tplg_build_integ(tplg);
- if (err < 0) {
- SNDERR("error: failed to check topology integrity\n");
- goto out;
- }
-
- err = tplg_write_data(tplg);
- if (err < 0) {
- SNDERR("error: failed to write data %d\n", err);
- goto out;
+ return err;
}
-out:
snd_config_delete(cfg);
-out_close:
- close(tplg->out_fd);
- return err;
+
+ return snd_tplg_build(tplg, outfile);
}
int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
@@ -468,31 +447,38 @@ int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
int snd_tplg_build(snd_tplg_t *tplg, const char *outfile)
{
- int err;
-
- tplg->out_fd =
- open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
- if (tplg->out_fd < 0) {
- SNDERR("error: failed to open %s err %d\n",
- outfile, -errno);
- return -errno;
- }
+ int fd, err;
+ ssize_t r;
err = tplg_build_integ(tplg);
if (err < 0) {
SNDERR("error: failed to check topology integrity\n");
- goto out;
+ return err;
}
err = tplg_write_data(tplg);
if (err < 0) {
SNDERR("error: failed to write data %d\n", err);
- goto out;
+ return err;
}
-out:
- close(tplg->out_fd);
- return err;
+ fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ SNDERR("error: failed to open %s err %d\n", outfile, -errno);
+ return -errno;
+ }
+ r = write(fd, tplg->bin, tplg->bin_size);
+ close(fd);
+ if (r < 0) {
+ err = -errno;
+ SNDERR("error: write error: %s\n", strerror(errno));
+ return err;
+ }
+ if ((size_t)r != tplg->bin_size) {
+ SNDERR("error: partial write (%zd != %zd)\n", r, tplg->bin_size);
+ return -EIO;
+ }
+ return 0;
}
int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len)
@@ -571,8 +557,8 @@ snd_tplg_t *snd_tplg_new(void)
void snd_tplg_free(snd_tplg_t *tplg)
{
- if (tplg->manifest_pdata)
- free(tplg->manifest_pdata);
+ free(tplg->bin);
+ free(tplg->manifest_pdata);
tplg_elem_free_list(&tplg->tlv_list);
tplg_elem_free_list(&tplg->widget_list);
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index e16c78d4..87e6c9a5 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -60,8 +60,9 @@ typedef enum _snd_pcm_rates {
struct snd_tplg {
/* out file */
- int out_fd;
- size_t out_pos;
+ unsigned char *bin;
+ size_t bin_pos;
+ size_t bin_size;
int verbose;
unsigned int version;
--
2.24.1
From bee8d4fcaa52d00950d035ec561513c2b9e7cac7 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 14 Dec 2019 19:20:02 +0100
Subject: [PATCH 38/69] topology: add binary output from the builder
- snd_tplg_build_bin()
- snd_tplg_build_bin_file()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/topology.h | 22 +++++++++++-
src/topology/parser.c | 79 ++++++++++++++++++++++++++++++++++++-------
2 files changed, 87 insertions(+), 14 deletions(-)
diff --git a/include/topology.h b/include/topology.h
index 27da7308..c9ef554a 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -791,7 +791,18 @@ void snd_tplg_free(snd_tplg_t *tplg);
* \return Zero on success, otherwise a negative error code
*/
int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
- const char *outfile);
+ const char *outfile);
+
+/**
+ * \brief Parse and build topology text file into binary file.
+ * \param tplg Topology instance.
+ * \param infile Topology text input file to be parsed
+ * \param bin Binary topology output buffer (malloc).
+ * \param size Binary topology output buffer size in bytes.
+ * \return Zero on success, otherwise a negative error code
+ */
+int snd_tplg_build_bin_file(snd_tplg_t *tplg, const char *infile,
+ void **bin, size_t *size);
/**
* \brief Enable verbose reporting of binary file output
@@ -1089,6 +1100,15 @@ int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
*/
int snd_tplg_build(snd_tplg_t *tplg, const char *outfile);
+/**
+ * \brief Build all registered topology data into memory.
+ * \param tplg Topology instance.
+ * \param bin Binary topology output buffer (malloc).
+ * \param size Binary topology output buffer size in bytes.
+ * \return Zero on success, otherwise a negative error code
+ */
+int snd_tplg_build_bin(snd_tplg_t *tplg, void **bin, size_t *size);
+
/**
* \brief Attach private data to topology manifest.
* \param tplg Topology instance.
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 98a9f9e9..861565b7 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -393,9 +393,7 @@ static int tplg_build_integ(snd_tplg_t *tplg)
return err;
}
-int snd_tplg_build_file(snd_tplg_t *tplg,
- const char *infile,
- const char *outfile)
+static int tplg_load(snd_tplg_t *tplg, const char *infile)
{
snd_config_t *cfg = NULL;
int err = 0;
@@ -414,10 +412,53 @@ int snd_tplg_build_file(snd_tplg_t *tplg,
}
snd_config_delete(cfg);
+ return 0;
+}
+
+static int tplg_build(snd_tplg_t *tplg)
+{
+ int err;
+
+ err = tplg_build_integ(tplg);
+ if (err < 0) {
+ SNDERR("error: failed to check topology integrity\n");
+ return err;
+ }
+
+ err = tplg_write_data(tplg);
+ if (err < 0) {
+ SNDERR("error: failed to write data %d\n", err);
+ return err;
+ }
+ return 0;
+}
+
+int snd_tplg_build_file(snd_tplg_t *tplg,
+ const char *infile,
+ const char *outfile)
+{
+ int err;
+
+ err = tplg_load(tplg, infile);
+ if (err < 0)
+ return err;
return snd_tplg_build(tplg, outfile);
}
+int snd_tplg_build_bin_file(snd_tplg_t *tplg,
+ const char *infile,
+ void **bin, size_t *size)
+{
+ int err;
+
+ err = tplg_load(tplg, infile);
+ if (err < 0)
+ return err;
+
+ return snd_tplg_build_bin(tplg, bin, size);
+}
+
int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
{
switch (t->type) {
@@ -450,17 +491,9 @@ int snd_tplg_build(snd_tplg_t *tplg, const char *outfile)
int fd, err;
ssize_t r;
- err = tplg_build_integ(tplg);
- if (err < 0) {
- SNDERR("error: failed to check topology integrity\n");
- return err;
- }
-
- err = tplg_write_data(tplg);
- if (err < 0) {
- SNDERR("error: failed to write data %d\n", err);
+ err = tplg_build(tplg);
+ if (err < 0)
return err;
- }
fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd < 0) {
@@ -481,6 +514,26 @@ int snd_tplg_build(snd_tplg_t *tplg, const char *outfile)
return 0;
}
+int snd_tplg_build_bin(snd_tplg_t *tplg,
+ void **bin, size_t *size)
+{
+ int err;
+
+ err = tplg_build(tplg);
+ if (err < 0)
+ return err;
+
+ err = tplg_build(tplg);
+ if (err < 0)
+ return err;
+
+ *bin = tplg->bin;
+ *size = tplg->bin_size;
+ tplg->bin = NULL;
+ tplg->bin_size = tplg->bin_pos = 0;
+ return 0;
+}
+
int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len)
{
if (len <= 0)
--
2.24.1
From 22b66731f3dc0eb5149a99ff547eeb84eaf8d54b Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 14 Dec 2019 20:32:24 +0100
Subject: [PATCH 39/69] topology: parser - recode tplg_parse_config()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/parser.c | 225 +++++++++++++++-----------------------
src/topology/tplg_local.h | 67 +++---------
2 files changed, 108 insertions(+), 184 deletions(-)
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 861565b7..82af7cc5 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -142,9 +142,88 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
{
+ static struct _parser {
+ const char *id;
+ int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+ } *p, parsers[] = {
+ {
+ .id = "SectionTLV",
+ .parser = tplg_parse_tlv
+ },
+ {
+ .id = "SectionControlMixer",
+ .parser = tplg_parse_control_mixer
+ },
+ {
+ .id = "SectionControlEnum",
+ .parser = tplg_parse_control_enum
+ },
+ {
+ .id = "SectionControlBytes",
+ .parser = tplg_parse_control_bytes
+ },
+ {
+ .id = "SectionWidget",
+ .parser = tplg_parse_dapm_widget
+ },
+ {
+ .id = "SectionPCMCapabilities",
+ .parser = tplg_parse_stream_caps
+ },
+ {
+ .id = "SectionPCM",
+ .parser = tplg_parse_pcm
+ },
+ {
+ .id = "SectionDAI",
+ .parser = tplg_parse_dai
+ },
+ {
+ .id = "SectionHWConfig",
+ .parser = tplg_parse_hw_config
+ },
+ {
+ .id = "SectionLink",
+ .parser = tplg_parse_link
+ },
+ {
+ .id = "SectionBE",
+ .parser = tplg_parse_link
+ },
+ {
+ .id = "SectionCC",
+ .parser = tplg_parse_cc
+ },
+ {
+ .id = "SectionGraph",
+ .parser = tplg_parse_dapm_graph
+ },
+ {
+ .id = "SectionText",
+ .parser = tplg_parse_text
+ },
+ {
+ .id = "SectionData",
+ .parser = tplg_parse_data
+ },
+ {
+ .id = "SectionVendorTokens",
+ .parser = tplg_parse_tokens
+ },
+ {
+ .id = "SectionVendorTuples",
+ .parser = tplg_parse_tuples
+ },
+ {
+ .id = "SectionManifest",
+ .parser = tplg_parse_manifest_data
+ },
+ };
+ int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id;
+ unsigned int idx;
int err;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
@@ -159,145 +238,23 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
if (snd_config_get_id(n, &id) < 0)
continue;
- if (strcmp(id, "SectionTLV") == 0) {
- err = tplg_parse_compound(tplg, n, tplg_parse_tlv,
- NULL);
- if (err < 0)
- return err;
- continue;
+ parser = NULL;
+ for (idx = 0; idx < ARRAY_SIZE(parsers); idx++) {
+ p = &parsers[idx];
+ if (strcmp(id, p->id) == 0) {
+ parser = p->parser;
+ break;
+ }
}
- if (strcmp(id, "SectionControlMixer") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_control_mixer, NULL);
- if (err < 0)
- return err;
+ if (parser == NULL) {
+ SNDERR("error: unknown section %s\n", id);
continue;
}
- if (strcmp(id, "SectionControlEnum") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_control_enum, NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionControlBytes") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_control_bytes, NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionWidget") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_dapm_widget, NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionPCMCapabilities") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_stream_caps, NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionPCM") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_pcm, NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionDAI") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_dai, NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionHWConfig") == 0) {
- err = tplg_parse_compound(tplg, n, tplg_parse_hw_config,
- NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionLink") == 0
- || strcmp(id, "SectionBE") == 0) {
- err = tplg_parse_compound(tplg, n, tplg_parse_link,
- NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionCC") == 0) {
- err = tplg_parse_compound(tplg, n, tplg_parse_cc,
- NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionGraph") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_dapm_graph, NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionText") == 0) {
- err = tplg_parse_compound(tplg, n, tplg_parse_text,
- NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionData") == 0) {
- err = tplg_parse_compound(tplg, n, tplg_parse_data,
- NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionVendorTokens") == 0) {
- err = tplg_parse_compound(tplg, n, tplg_parse_tokens,
- NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionVendorTuples") == 0) {
- err = tplg_parse_compound(tplg, n, tplg_parse_tuples,
- NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- if (strcmp(id, "SectionManifest") == 0) {
- err = tplg_parse_compound(tplg, n,
- tplg_parse_manifest_data,
- NULL);
- if (err < 0)
- return err;
- continue;
- }
-
- SNDERR("error: unknown section %s\n", id);
+ err = tplg_parse_compound(tplg, n, parser, NULL);
+ if (err < 0)
+ return err;
}
return 0;
}
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 87e6c9a5..77a68189 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -202,59 +202,26 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
int tplg_write_data(snd_tplg_t *tplg);
-int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
+int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_control_bytes(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_control_mixer(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_dapm_widget(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_stream_caps(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_link(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_cc(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
void tplg_free_tuples(void *obj);
-int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_control_bytes(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_control_mixer(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_dapm_widget(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_stream_caps(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_pcm(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_link(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_cc(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
-
-int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED);
-
int tplg_build_data(snd_tplg_t *tplg);
int tplg_build_manifest_data(snd_tplg_t *tplg);
int tplg_build_controls(snd_tplg_t *tplg);
--
2.24.1
From d52eaba63dfe1d845663a4cd1bf676fafc43874a Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 15 Dec 2019 16:03:29 +0100
Subject: [PATCH 40/69] topology: add snd_tplg_load() remove
snd_tplg_build_bin_file()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/topology.h | 16 ++++----
src/topology/parser.c | 96 +++++++++++++++----------------------------
2 files changed, 41 insertions(+), 71 deletions(-)
diff --git a/include/topology.h b/include/topology.h
index c9ef554a..c9f4ffea 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -784,25 +784,23 @@ snd_tplg_t *snd_tplg_new(void);
void snd_tplg_free(snd_tplg_t *tplg);
/**
- * \brief Parse and build topology text file into binary file.
+ * \brief Load topology from the text buffer.
* \param tplg Topology instance.
- * \param infile Topology text input file to be parsed
- * \param outfile Binary topology output file.
+ * \param buf Text buffer.
+ * \param size Text buffer size in bytes.
* \return Zero on success, otherwise a negative error code
*/
-int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
- const char *outfile);
+int snd_tplg_load(snd_tplg_t *tplg, const char *buf, size_t size);
/**
* \brief Parse and build topology text file into binary file.
* \param tplg Topology instance.
* \param infile Topology text input file to be parsed
- * \param bin Binary topology output buffer (malloc).
- * \param size Binary topology output buffer size in bytes.
+ * \param outfile Binary topology output file.
* \return Zero on success, otherwise a negative error code
*/
-int snd_tplg_build_bin_file(snd_tplg_t *tplg, const char *infile,
- void **bin, size_t *size);
+int snd_tplg_build_file(snd_tplg_t *tplg, const char *infile,
+ const char *outfile);
/**
* \brief Enable verbose reporting of binary file output
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 82af7cc5..ed864d32 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -259,52 +259,30 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
return 0;
}
-static int tplg_load_config(const char *file, snd_config_t **cfg)
+static int tplg_load_config(snd_tplg_t *tplg, snd_input_t *in)
{
- FILE *fp;
- snd_input_t *in;
snd_config_t *top;
int ret;
- fp = fopen(file, "r");
- if (fp == NULL) {
- SNDERR("error: could not open configuration file %s",
- file);
- return -errno;
- }
-
- ret = snd_input_stdio_attach(&in, fp, 1);
- if (ret < 0) {
- fclose(fp);
- SNDERR("error: could not attach stdio %s", file);
- return ret;
- }
ret = snd_config_top(&top);
if (ret < 0)
- goto err;
+ return ret;
ret = snd_config_load(top, in);
if (ret < 0) {
- SNDERR("error: could not load configuration file %s",
- file);
- goto err_load;
+ SNDERR("error: could not load configuration");
+ snd_config_delete(top);
+ return ret;
}
- ret = snd_input_close(in);
+ ret = tplg_parse_config(tplg, top);
+ snd_config_delete(top);
if (ret < 0) {
- in = NULL;
- goto err_load;
+ SNDERR("error: failed to parse topology");
+ return ret;
}
- *cfg = top;
return 0;
-
-err_load:
- snd_config_delete(top);
-err:
- if (in)
- snd_input_close(in);
- return ret;
}
static int tplg_build_integ(snd_tplg_t *tplg)
@@ -350,26 +328,20 @@ static int tplg_build_integ(snd_tplg_t *tplg)
return err;
}
-static int tplg_load(snd_tplg_t *tplg, const char *infile)
+int snd_tplg_load(snd_tplg_t *tplg, const char *buf, size_t size)
{
- snd_config_t *cfg = NULL;
- int err = 0;
-
- err = tplg_load_config(infile, &cfg);
- if (err < 0) {
- SNDERR("error: failed to load topology file %s\n",
- infile);
- return err;
- }
+ snd_input_t *in;
+ int err;
- err = tplg_parse_config(tplg, cfg);
+ err = snd_input_buffer_open(&in, buf, size);
if (err < 0) {
- SNDERR("error: failed to parse topology\n");
+ SNDERR("error: could not create input buffer");
return err;
}
- snd_config_delete(cfg);
- return 0;
+ err = tplg_load_config(tplg, in);
+ snd_input_close(in);
+ return err;
}
static int tplg_build(snd_tplg_t *tplg)
@@ -394,26 +366,30 @@ int snd_tplg_build_file(snd_tplg_t *tplg,
const char *infile,
const char *outfile)
{
+ FILE *fp;
+ snd_input_t *in;
int err;
- err = tplg_load(tplg, infile);
- if (err < 0)
- return err;
-
- return snd_tplg_build(tplg, outfile);
-}
+ fp = fopen(infile, "r");
+ if (fp == NULL) {
+ SNDERR("error: could not open configuration file %s",
+ infile);
+ return -errno;
+ }
-int snd_tplg_build_bin_file(snd_tplg_t *tplg,
- const char *infile,
- void **bin, size_t *size)
-{
- int err;
+ err = snd_input_stdio_attach(&in, fp, 1);
+ if (err < 0) {
+ fclose(fp);
+ SNDERR("error: could not attach stdio %s", infile);
+ return err;
+ }
- err = tplg_load(tplg, infile);
+ err = tplg_load_config(tplg, in);
+ snd_input_close(in);
if (err < 0)
return err;
- return snd_tplg_build_bin(tplg, bin, size);
+ return snd_tplg_build(tplg, outfile);
}
int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
@@ -476,10 +452,6 @@ int snd_tplg_build_bin(snd_tplg_t *tplg,
{
int err;
- err = tplg_build(tplg);
- if (err < 0)
- return err;
-
err = tplg_build(tplg);
if (err < 0)
return err;
--
2.24.1
From 4f076f5b69a873418ecb826a4198e4d95a3a2a6f Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 15 Dec 2019 16:15:29 +0100
Subject: [PATCH 41/69] topology: move the topology element table from builder
to elem
- use offsetof() for the lists
- add other info to describe the elements
- use the table in the element constructor
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 98 ++++------------
src/topology/ctl.c | 7 +-
src/topology/elem.c | 232 +++++++++++++++++++++++++++-----------
src/topology/tplg_local.h | 15 +++
4 files changed, 199 insertions(+), 153 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index 40943b56..cadb5583 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -236,83 +236,20 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg)
int tplg_write_data(snd_tplg_t *tplg)
{
- struct wtable {
- const char *name;
- struct list_head *list;
- int type;
- int tsoc;
- } *wptr, wtable[] = {
- {
- .name = "control mixer",
- .list = &tplg->mixer_list,
- .type = SND_TPLG_TYPE_MIXER,
- .tsoc = SND_SOC_TPLG_TYPE_MIXER,
- },
- {
- .name = "control enum",
- .list = &tplg->enum_list,
- .type = SND_TPLG_TYPE_ENUM,
- .tsoc = SND_SOC_TPLG_TYPE_ENUM,
- },
- {
- .name = "control extended (bytes)",
- .list = &tplg->bytes_ext_list,
- .type = SND_TPLG_TYPE_BYTES,
- .tsoc = SND_SOC_TPLG_TYPE_BYTES,
- },
- {
- .name = "dapm widget",
- .list = &tplg->widget_list,
- .type = SND_TPLG_TYPE_DAPM_WIDGET,
- .tsoc = SND_SOC_TPLG_TYPE_DAPM_WIDGET,
- },
- {
- .name = "pcm",
- .list = &tplg->pcm_list,
- .type = SND_TPLG_TYPE_PCM,
- .tsoc = SND_SOC_TPLG_TYPE_PCM,
- },
- {
- .name = "physical dai",
- .list = &tplg->dai_list,
- .type = SND_TPLG_TYPE_DAI,
- .tsoc = SND_SOC_TPLG_TYPE_DAI,
- },
- {
- .name = "be",
- .list = &tplg->be_list,
- .type = SND_TPLG_TYPE_BE,
- .tsoc = SND_SOC_TPLG_TYPE_BACKEND_LINK,
- },
- {
- .name = "cc",
- .list = &tplg->cc_list,
- .type = SND_TPLG_TYPE_CC,
- .tsoc = SND_SOC_TPLG_TYPE_CODEC_LINK,
- },
- {
- .name = "route (dapm graph)",
- .list = &tplg->route_list,
- .type = SND_TPLG_TYPE_DAPM_GRAPH,
- .tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH,
- },
- {
- .name = "private data",
- .list = &tplg->pdata_list,
- .type = SND_TPLG_TYPE_DATA,
- .tsoc = SND_SOC_TPLG_TYPE_PDATA,
- },
- };
-
+ struct tplg_table *tptr;
+ struct list_head *list;
ssize_t ret;
size_t total_size, size;
unsigned int index;
/* calculate total size */
total_size = calc_manifest_size(tplg);
- for (index = 0; index < ARRAY_SIZE(wtable); index++) {
- wptr = &wtable[index];
- size = calc_real_size(wptr->list);
+ for (index = 0; index < tplg_table_items; index++) {
+ tptr = &tplg_table[index];
+ if (!tptr->build)
+ continue;
+ list = (struct list_head *)((void *)tplg + tptr->loff);
+ size = calc_real_size(list);
total_size += size;
}
@@ -334,20 +271,23 @@ int tplg_write_data(snd_tplg_t *tplg)
}
/* write all blocks */
- for (index = 0; index < ARRAY_SIZE(wtable); index++) {
- wptr = &wtable[index];
+ for (index = 0; index < tplg_table_items; index++) {
+ tptr = &tplg_table[index];
+ if (!tptr->build)
+ continue;
+ list = (struct list_head *)((void *)tplg + tptr->loff);
/* calculate the block size in bytes for all elems in this list */
- size = calc_block_size(wptr->list);
+ size = calc_block_size(list);
if (size == 0)
continue;
verbose(tplg, "block size for type %s (%d:%d) is 0x%zx/%zd\n",
- wptr->name, wptr->type,
- wptr->tsoc, size, size);
- ret = write_elem_block(tplg, wptr->list, size,
- wptr->tsoc, wptr->name);
+ tptr->name, tptr->type,
+ tptr->tsoc, size, size);
+ ret = write_elem_block(tplg, list, size,
+ tptr->tsoc, tptr->name);
if (ret < 0) {
SNDERR("failed to write %s elements: %s\n",
- wptr->name, snd_strerror(-ret));
+ tptr->name, snd_strerror(-ret));
return ret;
}
}
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 9190efef..539329cd 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -284,18 +284,13 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
{
snd_config_iterator_t i, next;
snd_config_t *n;
- struct snd_soc_tplg_ctl_tlv *tplg_tlv;
+ struct snd_soc_tplg_ctl_tlv *tplg_tlv = elem->tlv;
struct snd_soc_tplg_tlv_dbscale *scale;
const char *id = NULL;
int val;
tplg_dbg(" scale: %s\n", elem->id);
- tplg_tlv = calloc(1, sizeof(*tplg_tlv));
- if (!tplg_tlv)
- return -ENOMEM;
-
- elem->tlv = tplg_tlv;
tplg_tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
tplg_tlv->type = SNDRV_CTL_TLVT_DB_SCALE;
scale = &tplg_tlv->scale;
diff --git a/src/topology/elem.c b/src/topology/elem.c
index f2076f79..92ca7da4 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -20,6 +20,154 @@
#include "list.h"
#include "tplg_local.h"
+struct tplg_table tplg_table[] = {
+ {
+ .name = "manifest",
+ .loff = offsetof(snd_tplg_t, manifest_list),
+ .type = SND_TPLG_TYPE_MANIFEST,
+ .tsoc = SND_SOC_TPLG_TYPE_MANIFEST,
+ .size = sizeof(struct snd_soc_tplg_manifest),
+ .enew = 1,
+ },
+ {
+ .name = "control mixer",
+ .loff = offsetof(snd_tplg_t, mixer_list),
+ .type = SND_TPLG_TYPE_MIXER,
+ .tsoc = SND_SOC_TPLG_TYPE_MIXER,
+ .size = sizeof(struct snd_soc_tplg_mixer_control),
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "control enum",
+ .loff = offsetof(snd_tplg_t, enum_list),
+ .type = SND_TPLG_TYPE_ENUM,
+ .tsoc = SND_SOC_TPLG_TYPE_ENUM,
+ .size = sizeof(struct snd_soc_tplg_enum_control),
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "control extended (bytes)",
+ .loff = offsetof(snd_tplg_t, bytes_ext_list),
+ .type = SND_TPLG_TYPE_BYTES,
+ .tsoc = SND_SOC_TPLG_TYPE_BYTES,
+ .size = sizeof(struct snd_soc_tplg_bytes_control),
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "dapm widget",
+ .loff = offsetof(snd_tplg_t, widget_list),
+ .type = SND_TPLG_TYPE_DAPM_WIDGET,
+ .tsoc = SND_SOC_TPLG_TYPE_DAPM_WIDGET,
+ .size = sizeof(struct snd_soc_tplg_dapm_widget),
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "pcm",
+ .loff = offsetof(snd_tplg_t, pcm_list),
+ .type = SND_TPLG_TYPE_PCM,
+ .tsoc = SND_SOC_TPLG_TYPE_PCM,
+ .size = sizeof(struct snd_soc_tplg_pcm),
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "physical dai",
+ .loff = offsetof(snd_tplg_t, dai_list),
+ .type = SND_TPLG_TYPE_DAI,
+ .tsoc = SND_SOC_TPLG_TYPE_DAI,
+ .size = sizeof(struct snd_soc_tplg_dai),
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "be",
+ .loff = offsetof(snd_tplg_t, be_list),
+ .type = SND_TPLG_TYPE_BE,
+ .tsoc = SND_SOC_TPLG_TYPE_BACKEND_LINK,
+ .size = sizeof(struct snd_soc_tplg_link_config),
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "cc",
+ .loff = offsetof(snd_tplg_t, cc_list),
+ .type = SND_TPLG_TYPE_CC,
+ .tsoc = SND_SOC_TPLG_TYPE_CODEC_LINK,
+ .size = sizeof(struct snd_soc_tplg_link_config),
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "route (dapm graph)",
+ .loff = offsetof(snd_tplg_t, route_list),
+ .type = SND_TPLG_TYPE_DAPM_GRAPH,
+ .tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH,
+ .build = 1,
+ },
+ {
+ .name = "private data",
+ .loff = offsetof(snd_tplg_t, pdata_list),
+ .type = SND_TPLG_TYPE_DATA,
+ .tsoc = SND_SOC_TPLG_TYPE_PDATA,
+ .build = 1,
+ .enew = 1,
+ },
+ {
+ .name = "text",
+ .loff = offsetof(snd_tplg_t, text_list),
+ .type = SND_TPLG_TYPE_TEXT,
+ .size = sizeof(struct tplg_texts),
+ .enew = 1,
+ },
+ {
+ .name = "tlv",
+ .loff = offsetof(snd_tplg_t, tlv_list),
+ .type = SND_TPLG_TYPE_TLV,
+ .size = sizeof(struct snd_soc_tplg_ctl_tlv),
+ .enew = 1,
+ },
+ {
+ .name = "stream config",
+ .loff = offsetof(snd_tplg_t, pcm_config_list),
+ .type = SND_TPLG_TYPE_STREAM_CONFIG,
+ .size = sizeof(struct snd_soc_tplg_stream),
+ .enew = 1,
+ },
+ {
+ .name = "stream capabilities",
+ .loff = offsetof(snd_tplg_t, pcm_caps_list),
+ .type = SND_TPLG_TYPE_STREAM_CAPS,
+ .size = sizeof(struct snd_soc_tplg_stream_caps),
+ .enew = 1,
+ },
+ {
+ .name = "token",
+ .loff = offsetof(snd_tplg_t, token_list),
+ .type = SND_TPLG_TYPE_TOKEN,
+ .enew = 1,
+ },
+ {
+ .name = "tuple",
+ .loff = offsetof(snd_tplg_t, tuple_list),
+ .type = SND_TPLG_TYPE_TUPLE,
+ .free = tplg_free_tuples,
+ .enew = 1,
+ },
+ {
+ .name = "hw config",
+ .loff = offsetof(snd_tplg_t, hw_cfg_list),
+ .type = SND_TPLG_TYPE_HW_CONFIG,
+ .size = sizeof(struct snd_soc_tplg_hw_config),
+ .enew = 1,
+ }
+};
+
+unsigned int tplg_table_items = ARRAY_SIZE(tplg_table);
+
int tplg_ref_add(struct tplg_elem *elem, int type, const char* id)
{
struct tplg_ref *ref;
@@ -152,9 +300,12 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
const char *name,
enum snd_tplg_type type)
{
+ struct tplg_table *tptr;
struct tplg_elem *elem;
+ struct list_head *list;
const char *id;
int obj_size = 0;
+ unsigned index;
void *obj;
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -191,79 +342,24 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
} else if (name != NULL)
snd_strlcpy(elem->id, name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- switch (type) {
- case SND_TPLG_TYPE_DATA:
- tplg_elem_insert(elem, &tplg->pdata_list);
- break;
- case SND_TPLG_TYPE_MANIFEST:
- tplg_elem_insert(elem, &tplg->manifest_list);
- obj_size = sizeof(struct snd_soc_tplg_manifest);
- break;
- case SND_TPLG_TYPE_TEXT:
- tplg_elem_insert(elem, &tplg->text_list);
- obj_size = sizeof(struct tplg_texts);
- break;
- case SND_TPLG_TYPE_TLV:
- tplg_elem_insert(elem, &tplg->tlv_list);
- elem->size = sizeof(struct snd_soc_tplg_ctl_tlv);
- break;
- case SND_TPLG_TYPE_BYTES:
- tplg_elem_insert(elem, &tplg->bytes_ext_list);
- obj_size = sizeof(struct snd_soc_tplg_bytes_control);
- break;
- case SND_TPLG_TYPE_ENUM:
- tplg_elem_insert(elem, &tplg->enum_list);
- obj_size = sizeof(struct snd_soc_tplg_enum_control);
- break;
- case SND_TPLG_TYPE_MIXER:
- tplg_elem_insert(elem, &tplg->mixer_list);
- obj_size = sizeof(struct snd_soc_tplg_mixer_control);
- break;
- case SND_TPLG_TYPE_DAPM_WIDGET:
- tplg_elem_insert(elem, &tplg->widget_list);
- obj_size = sizeof(struct snd_soc_tplg_dapm_widget);
- break;
- case SND_TPLG_TYPE_STREAM_CONFIG:
- tplg_elem_insert(elem, &tplg->pcm_config_list);
- obj_size = sizeof(struct snd_soc_tplg_stream);
+ for (index = 0; index < tplg_table_items; index++) {
+ tptr = &tplg_table[index];
+ if (!tptr->enew)
+ continue;
+ if ((int)type != tptr->type)
+ continue;
break;
- case SND_TPLG_TYPE_STREAM_CAPS:
- tplg_elem_insert(elem, &tplg->pcm_caps_list);
- obj_size = sizeof(struct snd_soc_tplg_stream_caps);
- break;
- case SND_TPLG_TYPE_PCM:
- tplg_elem_insert(elem, &tplg->pcm_list);
- obj_size = sizeof(struct snd_soc_tplg_pcm);
- break;
- case SND_TPLG_TYPE_DAI:
- tplg_elem_insert(elem, &tplg->dai_list);
- obj_size = sizeof(struct snd_soc_tplg_dai);
- break;
- case SND_TPLG_TYPE_BE:
- case SND_TPLG_TYPE_LINK:
- tplg_elem_insert(elem, &tplg->be_list);
- obj_size = sizeof(struct snd_soc_tplg_link_config);
- break;
- case SND_TPLG_TYPE_CC:
- tplg_elem_insert(elem, &tplg->cc_list);
- obj_size = sizeof(struct snd_soc_tplg_link_config);
- break;
- case SND_TPLG_TYPE_TOKEN:
- tplg_elem_insert(elem, &tplg->token_list);
- break;
- case SND_TPLG_TYPE_TUPLE:
- tplg_elem_insert(elem, &tplg->tuple_list);
- elem->free = tplg_free_tuples;
- break;
- case SND_TPLG_TYPE_HW_CONFIG:
- tplg_elem_insert(elem, &tplg->hw_cfg_list);
- obj_size = sizeof(struct snd_soc_tplg_hw_config);
- break;
- default:
+ }
+ if (index >= tplg_table_items) {
free(elem);
return NULL;
}
+ list = (struct list_head *)((void *)tplg + tptr->loff);
+ tplg_elem_insert(elem, list);
+ obj_size = tptr->size;
+ elem->free = tptr->free;
+
/* create new object too if required */
if (obj_size > 0) {
obj = calloc(1, obj_size);
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 77a68189..0987898f 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -196,6 +196,21 @@ struct map_elem {
int id;
};
+/* mapping table */
+struct tplg_table {
+ const char *name;
+ off_t loff;
+ size_t size;
+ int type;
+ int tsoc;
+ unsigned build: 1;
+ unsigned enew: 1;
+ void (*free)(void *);
+};
+
+extern struct tplg_table tplg_table[];
+extern unsigned int tplg_table_items;
+
int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
int (*fcn)(snd_tplg_t *, snd_config_t *, void *),
void *private);
--
2.24.1
From 4a0efdc87355d5789876e20b9530dc85224ad281 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 15 Dec 2019 17:24:50 +0100
Subject: [PATCH 42/69] topology: add parser to the tplg_table
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/elem.c | 35 +++++++++++++++
src/topology/parser.c | 90 ++++-----------------------------------
src/topology/tplg_local.h | 3 ++
3 files changed, 47 insertions(+), 81 deletions(-)
diff --git a/src/topology/elem.c b/src/topology/elem.c
index 92ca7da4..e79a68b7 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -23,112 +23,139 @@
struct tplg_table tplg_table[] = {
{
.name = "manifest",
+ .id = "SectionManifest",
.loff = offsetof(snd_tplg_t, manifest_list),
.type = SND_TPLG_TYPE_MANIFEST,
.tsoc = SND_SOC_TPLG_TYPE_MANIFEST,
.size = sizeof(struct snd_soc_tplg_manifest),
.enew = 1,
+ .parse = tplg_parse_manifest_data,
},
{
.name = "control mixer",
+ .id = "SectionControlMixer",
.loff = offsetof(snd_tplg_t, mixer_list),
.type = SND_TPLG_TYPE_MIXER,
.tsoc = SND_SOC_TPLG_TYPE_MIXER,
.size = sizeof(struct snd_soc_tplg_mixer_control),
.build = 1,
.enew = 1,
+ .parse = tplg_parse_control_mixer,
},
{
.name = "control enum",
+ .id = "SectionControlEnum",
.loff = offsetof(snd_tplg_t, enum_list),
.type = SND_TPLG_TYPE_ENUM,
.tsoc = SND_SOC_TPLG_TYPE_ENUM,
.size = sizeof(struct snd_soc_tplg_enum_control),
.build = 1,
.enew = 1,
+ .parse = tplg_parse_control_enum,
},
{
.name = "control extended (bytes)",
+ .id = "SectionControlBytes",
.loff = offsetof(snd_tplg_t, bytes_ext_list),
.type = SND_TPLG_TYPE_BYTES,
.tsoc = SND_SOC_TPLG_TYPE_BYTES,
.size = sizeof(struct snd_soc_tplg_bytes_control),
.build = 1,
.enew = 1,
+ .parse = tplg_parse_control_bytes,
},
{
.name = "dapm widget",
+ .id = "SectionWidget",
.loff = offsetof(snd_tplg_t, widget_list),
.type = SND_TPLG_TYPE_DAPM_WIDGET,
.tsoc = SND_SOC_TPLG_TYPE_DAPM_WIDGET,
.size = sizeof(struct snd_soc_tplg_dapm_widget),
.build = 1,
.enew = 1,
+ .parse = tplg_parse_dapm_widget,
},
{
.name = "pcm",
+ .id = "SectionPCM",
.loff = offsetof(snd_tplg_t, pcm_list),
.type = SND_TPLG_TYPE_PCM,
.tsoc = SND_SOC_TPLG_TYPE_PCM,
.size = sizeof(struct snd_soc_tplg_pcm),
.build = 1,
.enew = 1,
+ .parse = tplg_parse_pcm,
},
{
.name = "physical dai",
+ .id = "SectionDAI",
.loff = offsetof(snd_tplg_t, dai_list),
.type = SND_TPLG_TYPE_DAI,
.tsoc = SND_SOC_TPLG_TYPE_DAI,
.size = sizeof(struct snd_soc_tplg_dai),
.build = 1,
.enew = 1,
+ .parse = tplg_parse_dai,
},
{
.name = "be",
+ .id = "SectionBE",
+ .id2 = "SectionLink",
.loff = offsetof(snd_tplg_t, be_list),
.type = SND_TPLG_TYPE_BE,
.tsoc = SND_SOC_TPLG_TYPE_BACKEND_LINK,
.size = sizeof(struct snd_soc_tplg_link_config),
.build = 1,
.enew = 1,
+ .parse = tplg_parse_link,
},
{
.name = "cc",
+ .id = "SectionCC",
.loff = offsetof(snd_tplg_t, cc_list),
.type = SND_TPLG_TYPE_CC,
.tsoc = SND_SOC_TPLG_TYPE_CODEC_LINK,
.size = sizeof(struct snd_soc_tplg_link_config),
.build = 1,
.enew = 1,
+ .parse = tplg_parse_cc,
},
{
.name = "route (dapm graph)",
+ .id = "SectionGraph",
.loff = offsetof(snd_tplg_t, route_list),
.type = SND_TPLG_TYPE_DAPM_GRAPH,
.tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH,
.build = 1,
+ .parse = tplg_parse_dapm_graph,
},
{
.name = "private data",
+ .id = "SectionData",
.loff = offsetof(snd_tplg_t, pdata_list),
.type = SND_TPLG_TYPE_DATA,
.tsoc = SND_SOC_TPLG_TYPE_PDATA,
.build = 1,
.enew = 1,
+ .parse = tplg_parse_data,
},
{
.name = "text",
+ .id = "SectionText",
.loff = offsetof(snd_tplg_t, text_list),
.type = SND_TPLG_TYPE_TEXT,
.size = sizeof(struct tplg_texts),
.enew = 1,
+ .parse = tplg_parse_text,
},
{
.name = "tlv",
+ .id = "SectionTLV",
.loff = offsetof(snd_tplg_t, tlv_list),
.type = SND_TPLG_TYPE_TLV,
.size = sizeof(struct snd_soc_tplg_ctl_tlv),
.enew = 1,
+ .parse = tplg_parse_tlv,
},
{
.name = "stream config",
@@ -139,30 +166,38 @@ struct tplg_table tplg_table[] = {
},
{
.name = "stream capabilities",
+ .id = "SectionPCMCapabilities",
.loff = offsetof(snd_tplg_t, pcm_caps_list),
.type = SND_TPLG_TYPE_STREAM_CAPS,
.size = sizeof(struct snd_soc_tplg_stream_caps),
.enew = 1,
+ .parse = tplg_parse_stream_caps,
},
{
.name = "token",
+ .id = "SectionVendorTokens",
.loff = offsetof(snd_tplg_t, token_list),
.type = SND_TPLG_TYPE_TOKEN,
.enew = 1,
+ .parse = tplg_parse_tokens,
},
{
.name = "tuple",
+ .id = "SectionVendorTuples",
.loff = offsetof(snd_tplg_t, tuple_list),
.type = SND_TPLG_TYPE_TUPLE,
.free = tplg_free_tuples,
.enew = 1,
+ .parse = tplg_parse_tuples,
},
{
.name = "hw config",
+ .id = "SectionHWConfig",
.loff = offsetof(snd_tplg_t, hw_cfg_list),
.type = SND_TPLG_TYPE_HW_CONFIG,
.size = sizeof(struct snd_soc_tplg_hw_config),
.enew = 1,
+ .parse = tplg_parse_hw_config,
}
};
diff --git a/src/topology/parser.c b/src/topology/parser.c
index ed864d32..11202769 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -142,87 +142,11 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
{
- static struct _parser {
- const char *id;
- int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
- } *p, parsers[] = {
- {
- .id = "SectionTLV",
- .parser = tplg_parse_tlv
- },
- {
- .id = "SectionControlMixer",
- .parser = tplg_parse_control_mixer
- },
- {
- .id = "SectionControlEnum",
- .parser = tplg_parse_control_enum
- },
- {
- .id = "SectionControlBytes",
- .parser = tplg_parse_control_bytes
- },
- {
- .id = "SectionWidget",
- .parser = tplg_parse_dapm_widget
- },
- {
- .id = "SectionPCMCapabilities",
- .parser = tplg_parse_stream_caps
- },
- {
- .id = "SectionPCM",
- .parser = tplg_parse_pcm
- },
- {
- .id = "SectionDAI",
- .parser = tplg_parse_dai
- },
- {
- .id = "SectionHWConfig",
- .parser = tplg_parse_hw_config
- },
- {
- .id = "SectionLink",
- .parser = tplg_parse_link
- },
- {
- .id = "SectionBE",
- .parser = tplg_parse_link
- },
- {
- .id = "SectionCC",
- .parser = tplg_parse_cc
- },
- {
- .id = "SectionGraph",
- .parser = tplg_parse_dapm_graph
- },
- {
- .id = "SectionText",
- .parser = tplg_parse_text
- },
- {
- .id = "SectionData",
- .parser = tplg_parse_data
- },
- {
- .id = "SectionVendorTokens",
- .parser = tplg_parse_tokens
- },
- {
- .id = "SectionVendorTuples",
- .parser = tplg_parse_tuples
- },
- {
- .id = "SectionManifest",
- .parser = tplg_parse_manifest_data
- },
- };
int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id;
+ struct tplg_table *p;
unsigned int idx;
int err;
@@ -239,10 +163,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
continue;
parser = NULL;
- for (idx = 0; idx < ARRAY_SIZE(parsers); idx++) {
- p = &parsers[idx];
- if (strcmp(id, p->id) == 0) {
- parser = p->parser;
+ for (idx = 0; idx < tplg_table_items; idx++) {
+ p = &tplg_table[idx];
+ if (p->id && strcmp(id, p->id) == 0) {
+ parser = p->parse;
+ break;
+ }
+ if (p->id2 && strcmp(id, p->id2) == 0) {
+ parser = p->parse;
break;
}
}
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 0987898f..bea88ba3 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -199,6 +199,8 @@ struct map_elem {
/* mapping table */
struct tplg_table {
const char *name;
+ const char *id;
+ const char *id2;
off_t loff;
size_t size;
int type;
@@ -206,6 +208,7 @@ struct tplg_table {
unsigned build: 1;
unsigned enew: 1;
void (*free)(void *);
+ int (*parse)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
};
extern struct tplg_table tplg_table[];
--
2.24.1
From aa1bac2d04bd1fb4ccae96a1136e60454298a710 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 16 Dec 2019 14:26:31 +0100
Subject: [PATCH 43/69] topology: add snd_tplg_save()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/topology.h | 15 +
src/conf.c | 17 +
src/topology/Makefile.am | 3 +-
src/topology/channel.c | 45 +++
src/topology/ctl.c | 201 +++++++++++-
src/topology/dapm.c | 209 +++++++++----
src/topology/data.c | 601 +++++++++++++++++++++++++++++-------
src/topology/elem.c | 18 ++
src/topology/ops.c | 92 ++++++
src/topology/parser.c | 4 +
src/topology/pcm.c | 505 ++++++++++++++++++++++++++----
src/topology/save.c | 632 ++++++++++++++++++++++++++++++++++++++
src/topology/text.c | 19 ++
src/topology/tplg_local.h | 58 +++-
14 files changed, 2162 insertions(+), 257 deletions(-)
create mode 100644 src/topology/save.c
diff --git a/include/topology.h b/include/topology.h
index c9f4ffea..69aa5ed7 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -1124,6 +1124,21 @@ int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len);
*/
int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version);
+/*
+ * Flags for the snd_tplg_save()
+ */
+#define SND_TPLG_SAVE_SORT (1<<0) /*!< sort identifiers */
+#define SND_TPLG_SAVE_GROUPS (1<<1) /*!< create the structure by group index */
+#define SND_TPLG_SAVE_NOCHECK (1<<16) /*!< unchecked output for debugging */
+
+/**
+ * \brief Save the topology to the text configuration string.
+ * \param tplg Topology instance.
+ * \param dst A pointer to string with result (malloc).
+ * \return Zero on success, otherwise a negative error code
+ */
+int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags);
+
/* \} */
#ifdef __cplusplus
diff --git a/src/conf.c b/src/conf.c
index 3e753b26..c4db9f21 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -874,6 +874,21 @@ static int get_nonwhite(input_t *input)
}
}
+static inline int get_hexachar(input_t *input)
+{
+ int c, num = 0;
+
+ c = get_char(input);
+ if (c >= '0' && c <= '9') num |= (c - '0') << 4;
+ else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 4;
+ else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 4;
+ c = get_char(input);
+ if (c >= '0' && c <= '9') num |= (c - '0') << 0;
+ else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 0;
+ else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 0;
+ return c;
+}
+
static int get_quotedchar(input_t *input)
{
int c;
@@ -891,6 +906,8 @@ static int get_quotedchar(input_t *input)
return '\r';
case 'f':
return '\f';
+ case 'x':
+ return get_hexachar(input);
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
{
diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am
index 9dc472d6..a850ec4c 100644
--- a/src/topology/Makefile.am
+++ b/src/topology/Makefile.am
@@ -27,7 +27,8 @@ libatopology_la_SOURCES =\
text.c \
channel.c \
ops.c \
- elem.c
+ elem.c \
+ save.c
noinst_HEADERS = tplg_local.h
diff --git a/src/topology/channel.c b/src/topology/channel.c
index 4569eb31..b54a10c8 100644
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -73,6 +73,18 @@ static int lookup_channel(const char *c)
return -EINVAL;
}
+const char *tplg_channel_name(int type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(channel_map); i++) {
+ if (channel_map[i].id == type)
+ return channel_map[i].name;
+ }
+
+ return NULL;
+}
+
/* Parse a channel mapping. */
int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
void *private)
@@ -123,3 +135,36 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
tplg->channel_idx++;
return 0;
}
+
+int tplg_save_channels(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct snd_soc_tplg_channel *channel,
+ unsigned int count, char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_channel *c;
+ const char *s;
+ unsigned int index;
+ int err;
+
+ if (count == 0)
+ return 0;
+ err = tplg_save_printf(dst, pfx, "channel {\n");
+ for (index = 0; err >= 0 && index < count; index++) {
+ c = channel + index;
+ s = tplg_channel_name(c->id);
+ if (s == NULL)
+ err = tplg_save_printf(dst, pfx, "\t%u", c->id);
+ else
+ err = tplg_save_printf(dst, pfx, "\t%s", s);
+ if (err >= 0)
+ err = tplg_save_printf(dst, NULL, " {\n");
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "\t\treg %d\n", c->reg);
+ if (err >= 0 && c->shift > 0)
+ err = tplg_save_printf(dst, pfx, "\t\tshift %u\n", c->shift);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "\t}\n");
+ }
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 539329cd..979cc1b0 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -28,15 +28,16 @@ struct ctl_access_elem {
};
/* CTL access strings and codes */
+/* place the multi-bit values on top - like read_write - for save */
static const struct ctl_access_elem ctl_access[] = {
+ {"read_write", SNDRV_CTL_ELEM_ACCESS_READWRITE},
+ {"tlv_read_write", SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE},
{"read", SNDRV_CTL_ELEM_ACCESS_READ},
{"write", SNDRV_CTL_ELEM_ACCESS_WRITE},
- {"read_write", SNDRV_CTL_ELEM_ACCESS_READWRITE},
{"volatile", SNDRV_CTL_ELEM_ACCESS_VOLATILE},
{"timestamp", SNDRV_CTL_ELEM_ACCESS_TIMESTAMP},
{"tlv_read", SNDRV_CTL_ELEM_ACCESS_TLV_READ},
{"tlv_write", SNDRV_CTL_ELEM_ACCESS_TLV_WRITE},
- {"tlv_read_write", SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE},
{"tlv_command", SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
{"inactive", SNDRV_CTL_ELEM_ACCESS_INACTIVE},
{"lock", SNDRV_CTL_ELEM_ACCESS_LOCK},
@@ -103,6 +104,46 @@ int parse_access(snd_config_t *cfg,
return err;
}
+/* Save Access */
+static int tplg_save_access(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct snd_soc_tplg_ctl_hdr *hdr, char **dst,
+ const char *pfx)
+{
+ const char *last;
+ unsigned int j, count, access, cval;
+ int err;
+
+ if (hdr->access == 0)
+ return 0;
+
+ access = hdr->access;
+ for (j = 0, count = 0, last = NULL; j < ARRAY_SIZE(ctl_access); j++) {
+ cval = ctl_access[j].value;
+ if ((access & cval) == cval) {
+ access &= ~cval;
+ last = ctl_access[j].name;
+ count++;
+ }
+ }
+ if (count == 1)
+ return tplg_save_printf(dst, pfx, "access.0 %s\n", last);
+ err = tplg_save_printf(dst, pfx, "access [\n");
+ if (err < 0)
+ return err;
+ access = hdr->access;
+ for (j = 0; j < ARRAY_SIZE(ctl_access); j++) {
+ cval = ctl_access[j].value;
+ if ((access & cval) == cval) {
+ err = tplg_save_printf(dst, pfx, "\t%s\n",
+ ctl_access[j].name);
+ if (err < 0)
+ return err;
+ access &= ~cval;
+ }
+ }
+ return tplg_save_printf(dst, pfx, "]\n");
+}
+
/* copy referenced TLV to the mixer control */
static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
{
@@ -358,6 +399,37 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
return err;
}
+/* save TLV data */
+int tplg_save_tlv(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_ctl_tlv *tlv = elem->tlv;
+ struct snd_soc_tplg_tlv_dbscale *scale;
+ int err;
+
+ if (tlv->type != SNDRV_CTL_TLVT_DB_SCALE) {
+ SNDERR("unknown TLV type");
+ return -EINVAL;
+ }
+
+ scale = &tlv->scale;
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "\tscale {\n");
+ if (err >= 0 && scale->min)
+ err = tplg_save_printf(dst, pfx, "\t\tmin %i\n", scale->min);
+ if (err >= 0 && scale->step > 0)
+ err = tplg_save_printf(dst, pfx, "\t\tstep %i\n", scale->step);
+ if (err >= 0 && scale->mute > 0)
+ err = tplg_save_printf(dst, pfx, "\t\tmute %i\n", scale->mute);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "\t}\n");
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* Parse Control Bytes */
int tplg_parse_control_bytes(snd_tplg_t *tplg,
snd_config_t *cfg,
@@ -430,7 +502,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
}
if (strcmp(id, "data") == 0) {
- err = tplg_parse_data_refs(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
if (err < 0)
return err;
continue;
@@ -485,6 +557,49 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
return 0;
}
+/* save control bytes */
+int tplg_save_control_bytes(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_bytes_control *be = elem->bytes_ext;
+ char pfx2[16];
+ int err;
+
+ if (!be)
+ return 0;
+
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err < 0)
+ return err;
+ if (err >= 0 && elem->index > 0)
+ err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index);
+ if (err >= 0 && be->base > 0)
+ err = tplg_save_printf(dst, pfx, "\tbase %u\n", be->base);
+ if (err >= 0 && be->num_regs > 0)
+ err = tplg_save_printf(dst, pfx, "\tnum_regs %u\n", be->num_regs);
+ if (err >= 0 && be->max > 0)
+ err = tplg_save_printf(dst, pfx, "\tmax %u\n", be->max);
+ if (err >= 0 && be->mask > 0)
+ err = tplg_save_printf(dst, pfx, "\tmask %u\n", be->mask);
+ if (err >= 0)
+ err = tplg_save_ops(tplg, &be->hdr, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_ext_ops(tplg, be, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_access(tplg, &be->hdr, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TLV,
+ "tlv", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
+ "data", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* Parse Control Enums. */
int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
void *private ATTRIBUTE_UNUSED)
@@ -559,7 +674,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
}
if (strcmp(id, "data") == 0) {
- err = tplg_parse_data_refs(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
if (err < 0)
return err;
continue;
@@ -582,6 +697,42 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
return 0;
}
+/* save control eunm */
+int tplg_save_control_enum(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_enum_control *ec = elem->enum_ctrl;
+ char pfx2[16];
+ int err;
+
+ if (!ec)
+ return 0;
+
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err < 0)
+ return err;
+ if (err >= 0 && elem->index > 0)
+ err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TEXT,
+ "texts", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_channels(tplg, ec->channel, ec->num_channels,
+ dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_ops(tplg, &ec->hdr, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_access(tplg, &ec->hdr, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
+ "data", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* Parse Controls.
*
* Mixer control. Supports multiple channels.
@@ -683,7 +834,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
}
if (strcmp(id, "data") == 0) {
- err = tplg_parse_data_refs(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
if (err < 0)
return err;
continue;
@@ -709,6 +860,46 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
return 0;
}
+int tplg_save_control_mixer(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem, char **dst,
+ const char *pfx)
+{
+ struct snd_soc_tplg_mixer_control *mc = elem->mixer_ctrl;
+ char pfx2[16];
+ int err;
+
+ if (!mc)
+ return 0;
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err < 0)
+ return err;
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ if (err >= 0 && elem->index > 0)
+ err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index);
+ if (err >= 0)
+ err = tplg_save_channels(tplg, mc->channel, mc->num_channels,
+ dst, pfx2);
+ if (err >= 0 && mc->max > 0)
+ err = tplg_save_printf(dst, pfx, "\tmax %u\n", mc->max);
+ if (err >= 0 && mc->invert > 0)
+ err = tplg_save_printf(dst, pfx, "\tinvert 1\n", mc->max);
+ if (err >= 0 && mc->invert > 0)
+ err = tplg_save_printf(dst, pfx, "\tinvert 1\n", mc->max);
+ if (err >= 0)
+ err = tplg_save_ops(tplg, &mc->hdr, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_access(tplg, &mc->hdr, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TLV,
+ "tlv", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
+ "data", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
struct snd_tplg_ctl_template *t)
{
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index ad709210..2bdacedc 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -43,7 +43,6 @@ static const struct map_elem widget_map[] = {
{"effect", SND_SOC_TPLG_DAPM_EFFECT},
{"siggen", SND_SOC_TPLG_DAPM_SIGGEN},
{"src", SND_SOC_TPLG_DAPM_SRC},
- {"asrc", SND_SOC_TPLG_DAPM_ASRC},
{"encoder", SND_SOC_TPLG_DAPM_ENCODER},
{"decoder", SND_SOC_TPLG_DAPM_DECODER},
};
@@ -60,70 +59,16 @@ static int lookup_widget(const char *w)
return -EINVAL;
}
-static int tplg_parse_dapm_mixers(snd_config_t *cfg, struct tplg_elem *elem)
+static const char *get_widget_name(unsigned int type)
{
- snd_config_iterator_t i, next;
- snd_config_t *n;
- const char *value = NULL;
-
- tplg_dbg(" DAPM Mixer Controls: %s\n", elem->id);
-
- snd_config_for_each(i, next, cfg) {
- n = snd_config_iterator_entry(i);
-
- /* get value */
- if (snd_config_get_string(n, &value) < 0)
- continue;
-
- tplg_ref_add(elem, SND_TPLG_TYPE_MIXER, value);
- tplg_dbg("\t\t %s\n", value);
- }
-
- return 0;
-}
-
-static int tplg_parse_dapm_enums(snd_config_t *cfg, struct tplg_elem *elem)
-{
- snd_config_iterator_t i, next;
- snd_config_t *n;
- const char *value = NULL;
-
- tplg_dbg(" DAPM Enum Controls: %s\n", elem->id);
-
- snd_config_for_each(i, next, cfg) {
- n = snd_config_iterator_entry(i);
-
- /* get value */
- if (snd_config_get_string(n, &value) < 0)
- continue;
-
- tplg_ref_add(elem, SND_TPLG_TYPE_ENUM, value);
- tplg_dbg("\t\t %s\n", value);
- }
-
- return 0;
-}
-
-static int tplg_parse_dapm_bytes(snd_config_t *cfg, struct tplg_elem *elem)
-{
- snd_config_iterator_t i, next;
- snd_config_t *n;
- const char *value = NULL;
-
- tplg_dbg(" DAPM Bytes Controls: %s\n", elem->id);
-
- snd_config_for_each(i, next, cfg) {
- n = snd_config_iterator_entry(i);
-
- /* get value */
- if (snd_config_get_string(n, &value) < 0)
- continue;
+ unsigned int i;
- tplg_ref_add(elem, SND_TPLG_TYPE_BYTES, value);
- tplg_dbg("\t\t %s\n", value);
+ for (i = 0; i < ARRAY_SIZE(widget_map); i++) {
+ if ((unsigned int)widget_map[i].id == type)
+ return widget_map[i].name;
}
- return 0;
+ return NULL;
}
/* move referenced controls to the widget */
@@ -340,7 +285,7 @@ struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg, int index)
#define LINE_SIZE 1024
-/* line is defined as '"source, control, sink"' */
+/* line is defined as '"sink, control, source"' */
static int tplg_parse_line(const char *text,
struct snd_soc_tplg_dapm_graph_elem *line)
{
@@ -470,6 +415,77 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
return 0;
}
+/* save DAPM graph */
+int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_dapm_graph_elem *route;
+ struct list_head *pos;
+ struct tplg_elem *elem;
+ int err, first = 1, old_index = -1;
+ unsigned block = -1, count = 0;
+
+ list_for_each(pos, &tplg->route_list) {
+ elem = list_entry(pos, struct tplg_elem, list);
+ if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH)
+ continue;
+ if (index >= 0 && elem->index != index)
+ continue;
+ count++;
+ }
+ if (count == 0)
+ return 0;
+ err = tplg_save_printf(dst, pfx, "SectionGraph {\n");
+ list_for_each(pos, &tplg->route_list) {
+ elem = list_entry(pos, struct tplg_elem, list);
+ if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH)
+ continue;
+ if (index >= 0 && elem->index != index)
+ continue;
+ if (old_index != elem->index) {
+ if (old_index >= 0) {
+ err = tplg_save_printf(dst, pfx, "\t\t]\n");
+ if (err < 0)
+ return err;
+ err = tplg_save_printf(dst, pfx, "\t}\n");
+ if (err < 0)
+ return err;
+ }
+ old_index = elem->index;
+ block++;
+ first = 1;
+ err = tplg_save_printf(dst, pfx, "\tset%u {\n", block);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "\t\tindex %u\n",
+ elem->index);
+ if (err < 0)
+ return err;
+ }
+ if (first) {
+ first = 0;
+ err = tplg_save_printf(dst, pfx, "\t\tlines [\n", elem->index);
+ if (err < 0)
+ return err;
+ }
+ route = elem->route;
+ err = tplg_save_printf(dst, pfx, "\t\t\t'%s, %s, %s'\n",
+ route->sink, route->control,
+ route->source);
+ if (err < 0)
+ return err;
+ }
+
+ if (!first) {
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "\t\t]\n");
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "\t}\n");
+ }
+
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* DAPM Widget */
int tplg_parse_dapm_widget(snd_tplg_t *tplg,
snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
@@ -595,7 +611,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
}
if (strcmp(id, "enum") == 0) {
- err = tplg_parse_dapm_enums(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_ENUM);
if (err < 0)
return err;
@@ -603,7 +619,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
}
if (strcmp(id, "mixer") == 0) {
- err = tplg_parse_dapm_mixers(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_MIXER);
if (err < 0)
return err;
@@ -611,7 +627,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
}
if (strcmp(id, "bytes") == 0) {
- err = tplg_parse_dapm_bytes(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_BYTES);
if (err < 0)
return err;
@@ -619,7 +635,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
}
if (strcmp(id, "data") == 0) {
- err = tplg_parse_data_refs(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
if (err < 0)
return err;
continue;
@@ -629,6 +645,66 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
return 0;
}
+/* save DAPM widget */
+int tplg_save_dapm_widget(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_dapm_widget *widget = elem->widget;
+ const char *s;
+ char pfx2[16];
+ int err;
+
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0 && elem->index)
+ err = tplg_save_printf(dst, pfx, "\tindex %u\n",
+ elem->index);
+ if (err >= 0) {
+ s = get_widget_name(widget->id);
+ if (s)
+ err = tplg_save_printf(dst, pfx, "\ttype %s\n", s);
+ else
+ err = tplg_save_printf(dst, pfx, "\ttype %u\n",
+ widget->id);
+ }
+ if (err >= 0 && widget->sname[0])
+ err = tplg_save_printf(dst, pfx, "\tstream_name '%s'\n",
+ widget->sname);
+ if (err >= 0 && widget->reg)
+ err = tplg_save_printf(dst, pfx, "\tno_pm 1\n");
+ if (err >= 0 && widget->shift)
+ err = tplg_save_printf(dst, pfx, "\tshift %u\n",
+ widget->shift);
+ if (err >= 0 && widget->invert)
+ err = tplg_save_printf(dst, pfx, "\tinvert %u\n",
+ widget->invert);
+ if (err >= 0 && widget->subseq)
+ err = tplg_save_printf(dst, pfx, "\tsubseq %u\n",
+ widget->subseq);
+ if (err >= 0 && widget->event_type)
+ err = tplg_save_printf(dst, pfx, "\tevent_type %u\n",
+ widget->event_type);
+ if (err >= 0 && widget->event_flags)
+ err = tplg_save_printf(dst, pfx, "\tevent_flags %u\n",
+ widget->event_flags);
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_ENUM,
+ "enum", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_MIXER,
+ "mixer", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_BYTES,
+ "bytes", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
+ "data", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
int tplg_add_route(snd_tplg_t *tplg, struct snd_tplg_graph_elem *t, int index)
{
struct tplg_elem *elem;
@@ -744,7 +820,6 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
default:
SNDERR("error: widget %s: invalid type %d for ctl %d\n",
wt->name, ct->type, i);
- ret = -EINVAL;
break;
}
diff --git a/src/topology/data.c b/src/topology/data.c
index 9807445e..11cd73f5 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -21,6 +21,10 @@
#include "tplg_local.h"
#include <ctype.h>
+#define UUID_FORMAT "\
+0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, \
+0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x"
+
/* Get private data buffer of an element */
struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem)
{
@@ -64,6 +68,96 @@ struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem)
return priv;
}
+/* Parse references for the element, either a single data section
+ * or a list of data sections.
+ */
+int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem,
+ unsigned int type)
+{
+ snd_config_type_t cfg_type;
+ snd_config_iterator_t i, next;
+ snd_config_t *n;
+ const char *val = NULL;
+ int err, count;
+
+ cfg_type = snd_config_get_type(cfg);
+
+ /* refer to a single data section */
+ if (cfg_type == SND_CONFIG_TYPE_STRING) {
+ if (snd_config_get_string(cfg, &val) < 0)
+ return -EINVAL;
+
+ tplg_dbg("\tref data: %s\n", val);
+ err = tplg_ref_add(elem, type, val);
+ if (err < 0)
+ return err;
+ return 1;
+ }
+
+ if (cfg_type != SND_CONFIG_TYPE_COMPOUND) {
+ SNDERR("error: compound type expected for %s", elem->id);
+ return -EINVAL;
+ }
+
+ /* refer to a list of data sections */
+ count = 0;
+ snd_config_for_each(i, next, cfg) {
+ const char *val;
+
+ n = snd_config_iterator_entry(i);
+ if (snd_config_get_string(n, &val) < 0)
+ continue;
+
+ tplg_dbg("\tref data: %s\n", val);
+ err = tplg_ref_add(elem, type, val);
+ if (err < 0)
+ return err;
+ count++;
+ }
+
+ return count;
+}
+
+/* save references */
+int tplg_save_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem, unsigned int type,
+ const char *id, char **dst, const char *pfx)
+{
+ struct tplg_ref *ref, *last;
+ struct list_head *pos;
+ int err, count;
+
+ count = 0;
+ last = NULL;
+ list_for_each(pos, &elem->ref_list) {
+ ref = list_entry(pos, struct tplg_ref, list);
+ if (ref->type == type) {
+ last = ref;
+ count++;
+ }
+ }
+
+ if (count == 0)
+ return 0;
+
+ if (count == 1)
+ return tplg_save_printf(dst, pfx, "%s '%s'\n", id, last->id);
+
+ err = tplg_save_printf(dst, pfx, "%s [\n", id);
+ if (err < 0)
+ return err;
+ list_for_each(pos, &elem->ref_list) {
+ ref = list_entry(pos, struct tplg_ref, list);
+ if (ref->type == type) {
+ err = tplg_save_printf(dst, pfx, "\t'%s'\n", ref->id);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return tplg_save_printf(dst, pfx, "]\n");
+}
+
/* Get Private data from a file. */
static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)
{
@@ -140,58 +234,98 @@ err:
static void dump_priv_data(struct tplg_elem *elem)
{
struct snd_soc_tplg_private *priv = elem->data;
- unsigned int i, j = 0;
+ unsigned int i;
tplg_dbg(" elem size = %d, priv data size = %d\n",
elem->size, priv->size);
for (i = 0; i < priv->size; i++) {
- if (j++ % 8 == 0)
+ if (i > 0 && (i % 16) == 0)
tplg_dbg("\n");
- tplg_dbg(" 0x%x", *p++);
+ tplg_dbg(" %02x:", *p++);
}
tplg_dbg("\n\n");
}
+static inline int check_nibble(unsigned char c)
+{
+ return (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F');
+}
+
/* get number of hex value elements in CSV list */
static int get_hex_num(const char *str)
{
- int commas = 0, values = 0, len = strlen(str);
- const char *end = str + len;
+ int delims, values, len = strlen(str);
+ const char *s, *end = str + len;
+
+ /* check "aa:bb:00" syntax */
+ s = str;
+ delims = values = 0;
+ while (s < end) {
+ /* skip white space */
+ if (isspace(*s)) {
+ s++;
+ continue;
+ }
+ /* find delimeters */
+ if (*s == ':') {
+ delims++;
+ s++;
+ continue;
+ }
+ /* check 00 hexadecimal value */
+ if (s + 1 <= end) {
+ if (check_nibble(s[0]) && check_nibble(s[1])) {
+ values++;
+ } else {
+ goto format2;
+ }
+ s++;
+ }
+ s++;
+ }
+ goto end;
+format2:
/* we expect "0x0, 0x0, 0x0" */
- while (str < end) {
+ s = str;
+ delims = values = 0;
+ while (s < end) {
/* skip white space */
- if (isspace(*str)) {
- str++;
+ if (isspace(*s)) {
+ s++;
continue;
}
/* find delimeters */
- if (*str == ',') {
- commas++;
- str++;
+ if (*s == ',') {
+ delims++;
+ s++;
continue;
}
/* find 0x[0-9] values */
- if (*str == '0' && str + 2 <= end) {
- if (str[1] == 'x' && str[2] >= '0' && str[2] <= 'f') {
+ if (*s == '0' && s + 2 <= end) {
+ if (s[1] == 'x' && check_nibble(s[2])) {
+ if (check_nibble(s[3]))
+ s++;
values++;
- str += 3;
- } else {
- str++;
+ s += 2;
}
+ s++;
}
- str++;
+ s++;
}
+end:
/* there should always be one less comma than value */
- if (values -1 != commas)
+ if (values - 1 != delims)
return -EINVAL;
return values;
@@ -547,6 +681,71 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)
return 0;
}
+struct tuple_type {
+ unsigned int type;
+ const char *name;
+ unsigned int size;
+};
+
+static struct tuple_type tuple_types[] = {
+ {
+ .type = SND_SOC_TPLG_TUPLE_TYPE_UUID,
+ .name = "uuid",
+ .size = 4,
+ },
+ {
+ .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
+ .name = "string",
+ .size = 6,
+ },
+ {
+ .type = SND_SOC_TPLG_TUPLE_TYPE_BOOL,
+ .name = "bool",
+ .size = 4,
+ },
+ {
+ .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
+ .name = "byte",
+ .size = 4,
+ },
+ {
+ .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
+ .name = "short",
+ .size = 5,
+ },
+ {
+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ .name = "word",
+ .size = 4
+ },
+};
+
+static int get_tuple_type(const char *name)
+{
+ struct tuple_type *t;
+ unsigned int i;
+
+ /* skip initial index for sorting */
+ while ((*name >= '0' && *name <= '9') || *name == '_')
+ name++;
+ for (i = 0; i < ARRAY_SIZE(tuple_types); i++) {
+ t = &tuple_types[i];
+ if (strncasecmp(t->name, name, t->size) == 0)
+ return t->type;
+ }
+ return -EINVAL;
+}
+
+static const char *get_tuple_type_name(unsigned int type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(tuple_types); i++)
+ if (tuple_types[i].type == type)
+ return tuple_types[i].name;
+ return NULL;
+}
+
static int parse_tuple_set(snd_config_t *cfg,
struct tplg_tuple_set **s)
{
@@ -554,28 +753,17 @@ static int parse_tuple_set(snd_config_t *cfg,
snd_config_t *n;
const char *id, *value;
struct tplg_tuple_set *set;
- unsigned int type, num_tuples = 0;
+ unsigned int num_tuples = 0;
struct tplg_tuple *tuple;
unsigned int tuple_val;
- int ival;
+ int type, ival;
snd_config_get_id(cfg, &id);
- if (strncmp(id, "uuid", 4) == 0)
- type = SND_SOC_TPLG_TUPLE_TYPE_UUID;
- else if (strncmp(id, "string", 5) == 0)
- type = SND_SOC_TPLG_TUPLE_TYPE_STRING;
- else if (strncmp(id, "bool", 4) == 0)
- type = SND_SOC_TPLG_TUPLE_TYPE_BOOL;
- else if (strncmp(id, "byte", 4) == 0)
- type = SND_SOC_TPLG_TUPLE_TYPE_BYTE;
- else if (strncmp(id, "short", 5) == 0)
- type = SND_SOC_TPLG_TUPLE_TYPE_SHORT;
- else if (strncmp(id, "word", 4) == 0)
- type = SND_SOC_TPLG_TUPLE_TYPE_WORD;
- else {
- SNDERR("error: invalid tuple type '%s'\n", id);
- return -EINVAL;
+ type = get_tuple_type(id);
+ if (type < 0) {
+ SNDERR("error: invalid tuple type '%s'", id);
+ return type;
}
snd_config_for_each(i, next, cfg)
@@ -664,6 +852,84 @@ err:
return -EINVAL;
}
+/* save tuple set */
+static int tplg_save_tuple_set(struct tplg_vendor_tuples *tuples,
+ unsigned int set_index,
+ char **dst, const char *pfx)
+{
+ struct tplg_tuple_set *set;
+ struct tplg_tuple *tuple;
+ const char *s, *fmt;
+ char buf[32];
+ unsigned int i;
+ int err;
+
+ set = tuples->set[set_index];
+ if (set->num_tuples == 0)
+ return 0;
+ s = get_tuple_type_name(set->type);
+ if (s == NULL)
+ return -EINVAL;
+ if (tuples->num_sets < 10)
+ fmt = "%u_";
+ else if (tuples->num_sets < 100)
+ fmt = "%02u_";
+ else if (tuples->num_sets < 1000)
+ fmt = "%03u_";
+ else
+ return -EINVAL;
+ if (set->num_tuples > 1) {
+ snprintf(buf, sizeof(buf), "tuples.%s%%s {\n", fmt);
+ err = tplg_save_printf(dst, NULL, buf, set_index, s);
+ if (err < 0)
+ return err;
+ }
+ for (i = 0; i < set->num_tuples; i++) {
+ tuple = &set->tuple[i];
+ if (set->num_tuples == 1) {
+ snprintf(buf, sizeof(buf), "tuples.%s%%s.'%%s' ", fmt);
+ err = tplg_save_printf(dst, NULL, buf,
+ set_index, s, tuple->token);
+ } else {
+ err = tplg_save_printf(dst, pfx, "\t'%s' ",
+ tuple->token);
+ }
+ switch (set->type) {
+ case SND_SOC_TPLG_TUPLE_TYPE_UUID:
+ err = tplg_save_printf(dst, NULL, "'" UUID_FORMAT "'\n",
+ tuple->uuid[0], tuple->uuid[1],
+ tuple->uuid[2], tuple->uuid[3],
+ tuple->uuid[4], tuple->uuid[5],
+ tuple->uuid[6], tuple->uuid[7],
+ tuple->uuid[8], tuple->uuid[9],
+ tuple->uuid[10], tuple->uuid[11],
+ tuple->uuid[12], tuple->uuid[13],
+ tuple->uuid[14], tuple->uuid[15]);
+ break;
+ case SND_SOC_TPLG_TUPLE_TYPE_STRING:
+ err = tplg_save_printf(dst, NULL, "'%s'\n",
+ tuple->string);
+ break;
+ case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
+ case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
+ case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
+ err = tplg_save_printf(dst, NULL, "%u\n", tuple->value);
+ break;
+ case SND_SOC_TPLG_TUPLE_TYPE_WORD:
+ tplg_nice_value_format(buf, sizeof(buf), tuple->value);
+ err = tplg_save_printf(dst, NULL, "%s\n", buf);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (err < 0)
+ return err;
+ }
+ if (set->num_tuples > 1)
+ return tplg_save_printf(dst, pfx, "}\n");
+ return 0;
+}
+
static int parse_tuple_sets(snd_config_t *cfg,
struct tplg_vendor_tuples *tuples)
{
@@ -710,87 +976,24 @@ static int parse_tuple_sets(snd_config_t *cfg,
return 0;
}
-/* Parse tuples references for a data element, either a single tuples section
- * or a list of tuples sections.
- */
-static int parse_tuples_refs(snd_config_t *cfg,
- struct tplg_elem *elem)
-{
- snd_config_type_t type;
- snd_config_iterator_t i, next;
- snd_config_t *n;
- const char *val = NULL;
-
- type = snd_config_get_type(cfg);
-
- /* refer to a single tuples section */
- if (type == SND_CONFIG_TYPE_STRING) {
- if (snd_config_get_string(cfg, &val) < 0)
- return -EINVAL;
- tplg_dbg("\ttuples: %s\n", val);
- return tplg_ref_add(elem, SND_TPLG_TYPE_TUPLE, val);
- }
-
- if (type != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound type expected for %s", elem->id);
- return -EINVAL;
- }
-
- /* refer to a list of data sections */
- snd_config_for_each(i, next, cfg) {
- const char *val;
-
- n = snd_config_iterator_entry(i);
- if (snd_config_get_string(n, &val) < 0)
- continue;
-
- tplg_dbg("\ttuples: %s\n", val);
- tplg_ref_add(elem, SND_TPLG_TYPE_TUPLE, val);
- }
-
- return 0;
-}
-
-/* Parse private data references for the element, either a single data section
- * or a list of data sections.
- */
-int tplg_parse_data_refs(snd_config_t *cfg,
- struct tplg_elem *elem)
+/* save tuple sets */
+int tplg_save_tuple_sets(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
{
- snd_config_type_t type;
- snd_config_iterator_t i, next;
- snd_config_t *n;
- const char *val = NULL;
-
- type = snd_config_get_type(cfg);
-
- /* refer to a single data section */
- if (type == SND_CONFIG_TYPE_STRING) {
- if (snd_config_get_string(cfg, &val) < 0)
- return -EINVAL;
-
- tplg_dbg("\tdata: %s\n", val);
- return tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
- }
-
- if (type != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound type expected for %s", elem->id);
- return -EINVAL;
- }
-
- /* refer to a list of data sections */
- snd_config_for_each(i, next, cfg) {
- const char *val;
-
- n = snd_config_iterator_entry(i);
- if (snd_config_get_string(n, &val) < 0)
- continue;
+ struct tplg_vendor_tuples *tuples = elem->tuples;
+ unsigned int i;
+ int err = 0;
- tplg_dbg("\tdata: %s\n", val);
- tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
+ for (i = 0; i < tuples->num_sets; i++) {
+ err = tplg_save_printf(dst, pfx, "");
+ if (err < 0)
+ break;
+ err = tplg_save_tuple_set(tuples, i, dst, pfx);
+ if (err < 0)
+ break;
}
-
- return 0;
+ return err;
}
/* Parse vendor tokens
@@ -844,6 +1047,31 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
return 0;
}
+/* save vendor tokens */
+int tplg_save_tokens(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct tplg_vendor_tokens *tokens = elem->tokens;
+ unsigned int i;
+ int err;
+
+ if (!tokens || tokens->num_tokens == 0)
+ return 0;
+
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err < 0)
+ return err;
+ for (i = 0; err >= 0 && i < tokens->num_tokens; i++)
+ err = tplg_save_printf(dst, pfx, "\t'%s' %u\n",
+ tokens->token[i].id,
+ tokens->token[i].value);
+ err = tplg_save_printf(dst, pfx, "}\n");
+ if (err < 0)
+ return err;
+ return 0;
+}
+
/* Parse vendor tuples.
*/
int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
@@ -890,6 +1118,29 @@ int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
return 0;
}
+/* save vendor tuples */
+int tplg_save_tuples(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ char pfx2[16];
+ int err;
+
+ if (!elem->tuples)
+ return 0;
+
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TOKEN,
+ "tokens", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_tuple_sets(tplg, elem, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return 0;
+}
+
/* Free handler of tuples */
void tplg_free_tuples(void *obj)
{
@@ -944,7 +1195,7 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "data") == 0) {
- err = tplg_parse_data_refs(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
if (err < 0)
return err;
continue;
@@ -954,6 +1205,51 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg,
return 0;
}
+/* save manifest data */
+int tplg_save_manifest_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem, char **dst,
+ const char *pfx)
+{
+ struct list_head *pos;
+ struct tplg_ref *ref;
+ int err, index, count;
+
+ /* for each ref in this manifest elem */
+ count = 0;
+ list_for_each(pos, &elem->ref_list) {
+ ref = list_entry(pos, struct tplg_ref, list);
+ if (ref->type != SND_TPLG_TYPE_DATA)
+ continue;
+ count++;
+ }
+ if (count > 1) {
+ err = tplg_save_printf(dst, NULL, "'%s'.data [\n", elem->id);
+ if (err < 0)
+ return err;
+ }
+ index = 0;
+ list_for_each(pos, &elem->ref_list) {
+ ref = list_entry(pos, struct tplg_ref, list);
+ if (ref->type != SND_TPLG_TYPE_DATA)
+ continue;
+ if (count == 1) {
+ err = tplg_save_printf(dst, NULL, "'%s'.data.%u '%s'\n",
+ elem->id, index, ref->id);
+ } else {
+ err = tplg_save_printf(dst, pfx, "\t'%s'\n", ref->id);
+ if (err < 0)
+ return err;
+ }
+ index++;
+ }
+ if (count > 1) {
+ err = tplg_save_printf(dst, pfx, "]\n");
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
/* merge private data of manifest */
int tplg_build_manifest_data(snd_tplg_t *tplg)
{
@@ -1064,7 +1360,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
}
if (strcmp(id, "tuples") == 0) {
- err = parse_tuples_refs(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_TUPLE);
if (err < 0)
return err;
continue;
@@ -1083,6 +1379,81 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
return err;
}
+/* save data element */
+int tplg_save_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_private *priv = elem->data;
+ struct list_head *pos;
+ struct tplg_ref *ref;
+ char pfx2[16];
+ unsigned int i, count;
+ int err;
+
+ count = 0;
+ if (priv && priv->size > 0)
+ count++;
+ list_for_each(pos, &elem->ref_list) {
+ ref = list_entry(pos, struct tplg_ref, list);
+ if (ref->type == SND_TPLG_TYPE_TUPLE)
+ count++;
+ }
+ if (elem->vendor_type > 0)
+ count++;
+
+ if (count > 1) {
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0)
+ err = tplg_save_printf(dst, NULL, "");
+ } else {
+ err = tplg_save_printf(dst, NULL, "'%s'.", elem->id);
+ }
+ if (err >= 0 && priv && priv->size > 0) {
+ if (count > 1) {
+ err = tplg_save_printf(dst, pfx, "");
+ if (err < 0)
+ return err;
+ }
+ if (priv->size > 8) {
+ err = tplg_save_printf(dst, NULL, "bytes\n");
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "\t'");
+ } else {
+ err = tplg_save_printf(dst, NULL, "bytes '");
+ }
+ if (err < 0)
+ return err;
+ for (i = 0; i < priv->size; i++) {
+ if (i > 0 && (i % 8) == 0) {
+ err = tplg_save_printf(dst, NULL, ":\n");
+ if (err < 0)
+ return err;
+ err = tplg_save_printf(dst, pfx, "\t ");
+ if (err < 0)
+ return err;
+ }
+ err = tplg_save_printf(dst, NULL, "%s%02x",
+ (i % 8) == 0 ? "" : ":",
+ (unsigned char)priv->data[i]);
+ if (err < 0)
+ return err;
+ }
+ err = tplg_save_printf(dst, NULL, "'\n");
+ }
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TUPLE,
+ "tuples", dst,
+ count > 1 ? pfx2 : NULL);
+ if (err >= 0 && elem->vendor_type > 0)
+ err = tplg_save_printf(dst, pfx, "type %u",
+ elem->vendor_type);
+ if (err >= 0 && count > 1)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* Find a referenced data element and copy its data to the parent
* element's private data buffer.
* An element can refer to multiple data sections. Data of these sections
diff --git a/src/topology/elem.c b/src/topology/elem.c
index e79a68b7..89aed1fc 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -30,6 +30,7 @@ struct tplg_table tplg_table[] = {
.size = sizeof(struct snd_soc_tplg_manifest),
.enew = 1,
.parse = tplg_parse_manifest_data,
+ .save = tplg_save_manifest_data,
},
{
.name = "control mixer",
@@ -41,6 +42,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_control_mixer,
+ .save = tplg_save_control_mixer,
},
{
.name = "control enum",
@@ -52,6 +54,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_control_enum,
+ .save = tplg_save_control_enum,
},
{
.name = "control extended (bytes)",
@@ -63,6 +66,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_control_bytes,
+ .save = tplg_save_control_bytes,
},
{
.name = "dapm widget",
@@ -74,6 +78,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_dapm_widget,
+ .save = tplg_save_dapm_widget,
},
{
.name = "pcm",
@@ -85,6 +90,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_pcm,
+ .save = tplg_save_pcm,
},
{
.name = "physical dai",
@@ -96,6 +102,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_dai,
+ .save = tplg_save_dai,
},
{
.name = "be",
@@ -108,6 +115,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_link,
+ .save = tplg_save_link,
},
{
.name = "cc",
@@ -119,6 +127,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_cc,
+ .save = tplg_save_cc,
},
{
.name = "route (dapm graph)",
@@ -128,6 +137,7 @@ struct tplg_table tplg_table[] = {
.tsoc = SND_SOC_TPLG_TYPE_DAPM_GRAPH,
.build = 1,
.parse = tplg_parse_dapm_graph,
+ .gsave = tplg_save_dapm_graph,
},
{
.name = "private data",
@@ -138,6 +148,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.enew = 1,
.parse = tplg_parse_data,
+ .save = tplg_save_data,
},
{
.name = "text",
@@ -147,6 +158,7 @@ struct tplg_table tplg_table[] = {
.size = sizeof(struct tplg_texts),
.enew = 1,
.parse = tplg_parse_text,
+ .save = tplg_save_text,
},
{
.name = "tlv",
@@ -156,6 +168,7 @@ struct tplg_table tplg_table[] = {
.size = sizeof(struct snd_soc_tplg_ctl_tlv),
.enew = 1,
.parse = tplg_parse_tlv,
+ .save = tplg_save_tlv,
},
{
.name = "stream config",
@@ -172,6 +185,7 @@ struct tplg_table tplg_table[] = {
.size = sizeof(struct snd_soc_tplg_stream_caps),
.enew = 1,
.parse = tplg_parse_stream_caps,
+ .save = tplg_save_stream_caps,
},
{
.name = "token",
@@ -180,6 +194,7 @@ struct tplg_table tplg_table[] = {
.type = SND_TPLG_TYPE_TOKEN,
.enew = 1,
.parse = tplg_parse_tokens,
+ .save = tplg_save_tokens,
},
{
.name = "tuple",
@@ -189,6 +204,7 @@ struct tplg_table tplg_table[] = {
.free = tplg_free_tuples,
.enew = 1,
.parse = tplg_parse_tuples,
+ .save = tplg_save_tuples,
},
{
.name = "hw config",
@@ -198,6 +214,7 @@ struct tplg_table tplg_table[] = {
.size = sizeof(struct snd_soc_tplg_hw_config),
.enew = 1,
.parse = tplg_parse_hw_config,
+ .save = tplg_save_hw_config,
}
};
@@ -394,6 +411,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
tplg_elem_insert(elem, list);
obj_size = tptr->size;
elem->free = tptr->free;
+ elem->table = tptr;
/* create new object too if required */
if (obj_size > 0) {
diff --git a/src/topology/ops.c b/src/topology/ops.c
index 073acdcb..ad72ef1b 100644
--- a/src/topology/ops.c
+++ b/src/topology/ops.c
@@ -45,6 +45,18 @@ static int lookup_ops(const char *c)
return strtol(c, NULL, 0);
}
+const char *tplg_ops_name(int type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(control_map); i++) {
+ if (control_map[i].id == type)
+ return control_map[i].name;
+ }
+
+ return NULL;
+}
+
/* Parse Control operations. Ops can come from standard names above or
* bespoke driver controls with numbers >= 256
*/
@@ -84,6 +96,46 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
return 0;
}
+/* save control operations */
+int tplg_save_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct snd_soc_tplg_ctl_hdr *hdr, char **dst,
+ const char *pfx)
+{
+ const char *s;
+ int err;
+
+ if (hdr->ops.info + hdr->ops.get + hdr->ops.put == 0)
+ return 0;
+ err = tplg_save_printf(dst, pfx, "ops.0 {\n");
+ if (err >= 0 && hdr->ops.info > 0) {
+ s = tplg_ops_name(hdr->ops.info);
+ if (s == NULL)
+ err = tplg_save_printf(dst, pfx, "\tinfo %u\n",
+ hdr->ops.info);
+ else
+ err = tplg_save_printf(dst, pfx, "\tinfo %s\n", s);
+ }
+ if (err >= 0 && hdr->ops.get > 0) {
+ s = tplg_ops_name(hdr->ops.get);
+ if (s == NULL)
+ err = tplg_save_printf(dst, pfx, "\tget %u\n",
+ hdr->ops.get);
+ else
+ err = tplg_save_printf(dst, pfx, "\tget %s\n", s);
+ }
+ if (err >= 0 && hdr->ops.put > 0) {
+ s = tplg_ops_name(hdr->ops.put);
+ if (s == NULL)
+ err = tplg_save_printf(dst, pfx, "\tput %u\n",
+ hdr->ops.put);
+ else
+ err = tplg_save_printf(dst, pfx, "\tput %s\n", s);
+ }
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* Parse External Control operations. Ops can come from standard names above or
* bespoke driver controls with numbers >= 256
*/
@@ -121,3 +173,43 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
return 0;
}
+
+/* save external control operations */
+int tplg_save_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct snd_soc_tplg_bytes_control *be,
+ char **dst, const char *pfx)
+{
+ const char *s;
+ int err;
+
+ if (be->ext_ops.info + be->ext_ops.get + be->ext_ops.put == 0)
+ return 0;
+ err = tplg_save_printf(dst, pfx, "extops.0 {\n");
+ if (err >= 0 && be->ext_ops.info > 0) {
+ s = tplg_ops_name(be->ext_ops.info);
+ if (s == NULL)
+ err = tplg_save_printf(dst, pfx, "\tinfo %u\n",
+ be->ext_ops.info);
+ else
+ err = tplg_save_printf(dst, pfx, "\tinfo %s\n", s);
+ }
+ if (err >= 0 && be->ext_ops.get > 0) {
+ s = tplg_ops_name(be->ext_ops.get);
+ if (s == NULL)
+ err = tplg_save_printf(dst, pfx, "\tget %u\n",
+ be->ext_ops.get);
+ else
+ err = tplg_save_printf(dst, pfx, "\tget %s\n", s);
+ }
+ if (err >= 0 && be->ext_ops.put > 0) {
+ s = tplg_ops_name(be->ext_ops.put);
+ if (s == NULL)
+ err = tplg_save_printf(dst, pfx, "\tput %u\n",
+ be->ext_ops.put);
+ else
+ err = tplg_save_printf(dst, pfx, "\tput %s\n", s);
+ }
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 11202769..de5edd1b 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -71,6 +71,8 @@ int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base)
err = snd_config_get_integer(n, &lval);
if (err < 0)
return err;
+ if (lval < 0 && lval >= INT_MIN)
+ lval = UINT_MAX + lval + 1;
if (lval < 0 || lval > UINT_MAX)
return -ERANGE;
*val = lval;
@@ -79,6 +81,8 @@ int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base)
err = snd_config_get_integer64(n, &llval);
if (err < 0)
return err;
+ if (llval < 0 && llval >= INT_MIN)
+ llval = UINT_MAX + llval + 1;
if (llval < 0 || llval > UINT_MAX)
return -ERANGE;
*val = llval;
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 9b87549c..d09fbe42 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -345,6 +345,13 @@ static int get_rate_value(const char* name)
return SND_PCM_RATE_UNKNOWN;
}
+static const char *get_rate_name(int rate)
+{
+ if (rate >= 0 && rate <= SND_PCM_RATE_LAST)
+ return snd_pcm_rate_names[rate];
+ return NULL;
+}
+
static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str)
{
char *s = NULL;
@@ -527,6 +534,80 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
return 0;
}
+/* save stream caps */
+int tplg_save_stream_caps(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_stream_caps *sc = elem->stream_caps;
+ const char *s;
+ unsigned int i;
+ int err, first;
+
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0 && sc->formats) {
+ err = tplg_save_printf(dst, pfx, "\tformats '");
+ first = 1;
+ for (i = 0; err >= 0 && i < SND_PCM_FORMAT_LAST; i++) {
+ if (sc->formats & (1ULL << i)) {
+ s = snd_pcm_format_name(i);
+ err = tplg_save_printf(dst, NULL, "%s%s",
+ !first ? ", " : "", s);
+ first = 0;
+ }
+ }
+ if (err >= 0)
+ err = tplg_save_printf(dst, NULL, "'\n");
+ }
+ if (err >= 0 && sc->rates) {
+ err = tplg_save_printf(dst, pfx, "\trates '");
+ first = 1;
+ for (i = 0; err >= 0 && i < SND_PCM_RATE_LAST; i++) {
+ if (sc->rates & (1ULL << i)) {
+ s = get_rate_name(i);
+ err = tplg_save_printf(dst, NULL, "%s%s",
+ !first ? ", " : "", s);
+ first = 0;
+ }
+ }
+ if (err >= 0)
+ err = tplg_save_printf(dst, NULL, "'\n");
+ }
+ if (err >= 0 && sc->rate_min)
+ err = tplg_save_printf(dst, pfx, "\trate_min %u\n",
+ sc->rate_min);
+ if (err >= 0 && sc->rate_max)
+ err = tplg_save_printf(dst, pfx, "\trate_max %u\n",
+ sc->rate_max);
+ if (err >= 0 && sc->channels_min)
+ err = tplg_save_printf(dst, pfx, "\tchannels_min %u\n",
+ sc->channels_min);
+ if (err >= 0 && sc->channels_max)
+ err = tplg_save_printf(dst, pfx, "\tchannels_max %u\n",
+ sc->channels_max);
+ if (err >= 0 && sc->periods_min)
+ err = tplg_save_printf(dst, pfx, "\tperiods_min %u\n",
+ sc->periods_min);
+ if (err >= 0 && sc->periods_max)
+ err = tplg_save_printf(dst, pfx, "\tperiods_max %u\n",
+ sc->periods_max);
+ if (err >= 0 && sc->period_size_min)
+ err = tplg_save_printf(dst, pfx, "\tperiod_size_min %u\n",
+ sc->period_size_min);
+ if (err >= 0 && sc->period_size_max)
+ err = tplg_save_printf(dst, pfx, "\tperiod_size_max %u\n",
+ sc->period_size_max);
+ if (err >= 0 && sc->buffer_size_min)
+ err = tplg_save_printf(dst, pfx, "\tbuffer_size_min %u\n",
+ sc->buffer_size_min);
+ if (err >= 0 && sc->buffer_size_max)
+ err = tplg_save_printf(dst, pfx, "\tbuffer_size_max %u\n",
+ sc->buffer_size_max);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* Parse the caps and config of a pcm stream */
static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_t *cfg, void *private)
@@ -598,6 +679,61 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
return 0;
}
+/* Save the caps and config of a pcm stream */
+int tplg_save_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ static const char *stream_ids[2] = {
+ "playback",
+ "capture"
+ };
+ static unsigned int stream_types[2] = {
+ SND_SOC_TPLG_STREAM_PLAYBACK,
+ SND_SOC_TPLG_STREAM_CAPTURE
+ };
+ struct snd_soc_tplg_stream_caps *caps;
+ unsigned int streams[2], stream;
+ const char *s;
+ int err;
+
+ switch (elem->type) {
+ case SND_TPLG_TYPE_PCM:
+ streams[0] = elem->pcm->playback;
+ streams[1] = elem->pcm->capture;
+ caps = elem->pcm->caps;
+ break;
+ case SND_TPLG_TYPE_DAI:
+ streams[0] = elem->dai->playback;
+ streams[1] = elem->dai->capture;
+ caps = elem->dai->caps;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (stream = 0; stream < 2; stream++) {
+ if (streams[stream] == 0)
+ continue;
+ if (!caps)
+ continue;
+ s = caps[stream_types[stream]].name;
+ if (s[0] == '\0')
+ continue;
+ err = tplg_save_printf(dst, pfx, "pcm.%s {\n", stream_ids[stream]);
+ if (err < 0)
+ return err;
+ err = tplg_save_printf(dst, pfx, "\tcapabilities '%s'\n", s);
+ if (err < 0)
+ return err;
+ err = tplg_save_printf(dst, pfx, "}\n");
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
/* Parse name and id of a front-end DAI (ie. cpu dai of a FE DAI link) */
static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_t *cfg, void *private)
@@ -633,6 +769,19 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
return 0;
}
+/* Save the caps and config of a pcm stream */
+int tplg_save_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_pcm *pcm = elem->pcm;
+ int err = 0;
+
+ if (pcm->dai_id > 0)
+ err = tplg_save_printf(dst, pfx, "dai.0.id %u\n", pcm->dai_id);
+ return err;
+}
+
/* parse a flag bit of the given mask */
static int parse_flag(snd_config_t *n, unsigned int mask_in,
unsigned int *mask, unsigned int *flags)
@@ -652,6 +801,32 @@ static int parse_flag(snd_config_t *n, unsigned int mask_in,
return 0;
}
+static int save_flags(unsigned int flags, unsigned int mask,
+ char **dst, const char *pfx)
+{
+ static unsigned int flag_masks[3] = {
+ SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES,
+ SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS,
+ SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS,
+ };
+ static const char *flag_ids[3] = {
+ "symmetric_rates",
+ "symmetric_channels",
+ "symmetric_sample_bits",
+ };
+ unsigned int i;
+ int err = 0;
+
+ for (i = 0; err >= 0 && i < ARRAY_SIZE(flag_masks); i++) {
+ if (mask & flag_masks[i]) {
+ unsigned int v = (flags & flag_masks[i]) ? 1 : 0;
+ err = tplg_save_printf(dst, pfx, "%s %u\n",
+ flag_ids[i], v);
+ }
+ }
+ return err;
+}
+
/* Parse PCM (for front end DAI & DAI link) in text conf file */
int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
void *private ATTRIBUTE_UNUSED)
@@ -748,7 +923,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
/* private data */
if (strcmp(id, "data") == 0) {
- err = tplg_parse_data_refs(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
if (err < 0)
return err;
continue;
@@ -758,6 +933,40 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
return 0;
}
+/* save PCM */
+int tplg_save_pcm(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_pcm *pcm = elem->pcm;
+ char pfx2[16];
+ int err;
+
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0 && elem->index)
+ err = tplg_save_printf(dst, pfx, "\tindex %u\n",
+ elem->index);
+ if (err >= 0 && pcm->pcm_id)
+ err = tplg_save_printf(dst, pfx, "\tid %u\n",
+ pcm->pcm_id);
+ if (err >= 0 && pcm->compress)
+ err = tplg_save_printf(dst, pfx, "\tcompress 1\n");
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ if (err >= 0)
+ err = tplg_save_fe_dai(tplg, elem, dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_streams(tplg, elem, dst, pfx2);
+ if (err >= 0)
+ err = save_flags(pcm->flags, pcm->flag_mask, dst, pfx);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
+ "data", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* Parse physical DAI */
int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
void *private ATTRIBUTE_UNUSED)
@@ -766,7 +975,7 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
struct tplg_elem *elem;
snd_config_iterator_t i, next;
snd_config_t *n;
- const char *id, *val = NULL;
+ const char *id;
int err;
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DAI);
@@ -851,11 +1060,9 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
/* private data */
if (strcmp(id, "data") == 0) {
- if (snd_config_get_string(n, &val) < 0)
- return -EINVAL;
-
- tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
- tplg_dbg("\t%s: %s\n", id, val);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
+ if (err < 0)
+ return err;
continue;
}
}
@@ -863,55 +1070,55 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
return 0;
}
+/* save DAI */
+int tplg_save_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_dai *dai = elem->dai;
+ char pfx2[16];
+ int err;
+
+ if (!dai)
+ return 0;
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0 && elem->index)
+ err = tplg_save_printf(dst, pfx, "\tindex %u\n",
+ elem->index);
+ if (err >= 0 && dai->dai_id)
+ err = tplg_save_printf(dst, pfx, "\tid %u\n",
+ dai->dai_id);
+ if (err >= 0 && dai->playback)
+ err = tplg_save_printf(dst, pfx, "\tplayback %u\n",
+ dai->playback);
+ if (err >= 0 && dai->capture)
+ err = tplg_save_printf(dst, pfx, "\tcapture %u\n",
+ dai->capture);
+ if (err >= 0)
+ err = tplg_save_streams(tplg, elem, dst, pfx2);
+ if (err >= 0)
+ err = save_flags(dai->flags, dai->flag_mask, dst, pfx);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
+ "data", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* parse physical link runtime supported HW configs in text conf file */
static int parse_hw_config_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_t *cfg,
struct tplg_elem *elem)
{
struct snd_soc_tplg_link_config *link = elem->link;
- snd_config_type_t type;
- snd_config_iterator_t i, next;
- snd_config_t *n;
- const char *id, *val = NULL;
-
- if (snd_config_get_id(cfg, &id) < 0)
- return -EINVAL;
- type = snd_config_get_type(cfg);
-
- /* refer to a single HW config */
- if (type == SND_CONFIG_TYPE_STRING) {
- if (snd_config_get_string(cfg, &val) < 0)
- return -EINVAL;
-
- link->num_hw_configs = 1;
- return tplg_ref_add(elem, SND_TPLG_TYPE_HW_CONFIG, val);
- }
-
- if (type != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound type expected for %s", id);
- return -EINVAL;
- }
-
- /* refer to a list of HW configs */
- snd_config_for_each(i, next, cfg) {
- const char *val;
- int err;
-
- n = snd_config_iterator_entry(i);
- if (snd_config_get_string(n, &val) < 0)
- continue;
-
- if (link->num_hw_configs >= SND_SOC_TPLG_HW_CONFIG_MAX) {
- SNDERR("error: exceed max hw configs for link %s", id);
- return -EINVAL;
- }
-
- link->num_hw_configs++;
- err = tplg_ref_add(elem, SND_TPLG_TYPE_HW_CONFIG, val);
- if (err < 0)
- return err;
- }
+ int err;
+ err = tplg_parse_refs(cfg, elem, SND_TPLG_TYPE_HW_CONFIG);
+ if (err < 0)
+ return err;
+ link->num_hw_configs = err;
return 0;
}
@@ -1007,7 +1214,7 @@ int tplg_parse_link(snd_tplg_t *tplg,
/* private data */
if (strcmp(id, "data") == 0) {
- err = tplg_parse_data_refs(n, elem);
+ err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
if (err < 0)
return err;
continue;
@@ -1017,6 +1224,44 @@ int tplg_parse_link(snd_tplg_t *tplg,
return 0;
}
+/* save physical link */
+int tplg_save_link(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_link_config *link = elem->link;
+ char pfx2[16];
+ int err;
+
+ if (!link)
+ return 0;
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0 && elem->index)
+ err = tplg_save_printf(dst, pfx, "\tindex %u\n",
+ elem->index);
+ if (err >= 0 && link->id)
+ err = tplg_save_printf(dst, pfx, "\tid %u\n",
+ link->id);
+ if (err >= 0 && link->stream_name[0])
+ err = tplg_save_printf(dst, pfx, "\tstream_name '%s'\n",
+ link->stream_name);
+ if (err >= 0 && link->default_hw_config_id)
+ err = tplg_save_printf(dst, pfx, "\tdefault_hw_conf_id %u\n",
+ link->default_hw_config_id);
+ if (err >= 0)
+ err = save_flags(link->flags, link->flag_mask, dst, pfx);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_HW_CONFIG,
+ "hw_configs", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
+ "data", dst, pfx2);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* Parse cc */
int tplg_parse_cc(snd_tplg_t *tplg,
snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
@@ -1059,36 +1304,95 @@ int tplg_parse_cc(snd_tplg_t *tplg,
return 0;
}
-static int get_audio_hw_format(const char *val)
+/* save CC */
+int tplg_save_cc(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
{
- if (!strlen(val))
- return -EINVAL;
-
- if (!strcmp(val, "I2S"))
- return SND_SOC_DAI_FORMAT_I2S;
+ struct snd_soc_tplg_link_config *link = elem->link;
+ char pfx2[16];
+ int err;
- if (!strcmp(val, "RIGHT_J"))
- return SND_SOC_DAI_FORMAT_RIGHT_J;
+ if (!link)
+ return 0;
+ snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0 && elem->index)
+ err = tplg_save_printf(dst, pfx, "\tindex %u\n",
+ elem->index);
+ if (err >= 0 && link->id)
+ err = tplg_save_printf(dst, pfx, "\tid %u\n",
+ link->id);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
- if (!strcmp(val, "LEFT_J"))
- return SND_SOC_DAI_FORMAT_LEFT_J;
+struct audio_hw_format {
+ unsigned int type;
+ const char *name;
+};
- if (!strcmp(val, "DSP_A"))
- return SND_SOC_DAI_FORMAT_DSP_A;
+static struct audio_hw_format audio_hw_formats[] = {
+ {
+ .type = SND_SOC_DAI_FORMAT_I2S,
+ .name = "I2S",
+ },
+ {
+ .type = SND_SOC_DAI_FORMAT_RIGHT_J,
+ .name = "RIGHT_J",
+ },
+ {
+ .type = SND_SOC_DAI_FORMAT_LEFT_J,
+ .name = "LEFT_J",
+ },
+ {
+ .type = SND_SOC_DAI_FORMAT_DSP_A,
+ .name = "DSP_A",
+ },
+ {
+ .type = SND_SOC_DAI_FORMAT_DSP_B,
+ .name = "DSP_B",
+ },
+ {
+ .type = SND_SOC_DAI_FORMAT_AC97,
+ .name = "AC97",
+ },
+ {
+ .type = SND_SOC_DAI_FORMAT_AC97,
+ .name = "AC97",
+ },
+ {
+ .type = SND_SOC_DAI_FORMAT_PDM,
+ .name = "PDM",
+ },
+};
- if (!strcmp(val, "DSP_B"))
- return SND_SOC_DAI_FORMAT_DSP_B;
+static int get_audio_hw_format(const char *val)
+{
+ unsigned int i;
- if (!strcmp(val, "AC97"))
- return SND_SOC_DAI_FORMAT_AC97;
+ if (val[0] == '\0')
+ return -EINVAL;
- if (!strcmp(val, "PDM"))
- return SND_SOC_DAI_FORMAT_PDM;
+ for (i = 0; i < ARRAY_SIZE(audio_hw_formats); i++)
+ if (strcasecmp(audio_hw_formats[i].name, val) == 0)
+ return audio_hw_formats[i].type;
SNDERR("error: invalid audio HW format %s\n", val);
return -EINVAL;
}
+static const char *get_audio_hw_format_name(unsigned int type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(audio_hw_formats); i++)
+ if (audio_hw_formats[i].type == type)
+ return audio_hw_formats[i].name;
+ return NULL;
+}
+
int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
void *private ATTRIBUTE_UNUSED)
{
@@ -1299,6 +1603,71 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
return 0;
}
+/* save hw config */
+int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct snd_soc_tplg_hw_config *hc = elem->hw_cfg;
+ int err;
+
+ err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
+ if (err >= 0 && hc->id)
+ err = tplg_save_printf(dst, pfx, "\tid %u\n",
+ hc->id);
+ if (err >= 0 && hc->fmt)
+ err = tplg_save_printf(dst, pfx, "\tformat '%s'\n",
+ get_audio_hw_format_name(hc->fmt));
+ if (err >= 0 && hc->bclk_master)
+ err = tplg_save_printf(dst, pfx, "\tbclk '%s'\n",
+ hc->bclk_master == SND_SOC_TPLG_BCLK_CS ?
+ "codec_slave" : "codec_master");
+ if (err >= 0 && hc->bclk_rate)
+ err = tplg_save_printf(dst, pfx, "\tbclk_freq %u\n",
+ hc->bclk_rate);
+ if (err >= 0 && hc->invert_bclk)
+ err = tplg_save_printf(dst, pfx, "\tbclk_invert 1\n");
+ if (err >= 0 && hc->fsync_master)
+ err = tplg_save_printf(dst, pfx, "\tfsync_master '%s'\n",
+ hc->fsync_master == SND_SOC_TPLG_FSYNC_CS ?
+ "codec_slave" : "codec_master");
+ if (err >= 0 && hc->fsync_rate)
+ err = tplg_save_printf(dst, pfx, "\tfsync_freq %u\n",
+ hc->fsync_rate);
+ if (err >= 0 && hc->invert_fsync)
+ err = tplg_save_printf(dst, pfx, "\tfsync_invert 1\n");
+ if (err >= 0 && hc->mclk_rate)
+ err = tplg_save_printf(dst, pfx, "\tmclk_freq %u\n",
+ hc->mclk_rate);
+ if (err >= 0 && hc->mclk_direction)
+ err = tplg_save_printf(dst, pfx, "\tmclk '%s'\n",
+ hc->mclk_direction == SND_SOC_TPLG_MCLK_CI ?
+ "codec_mclk_in" : "codec_mclk_out");
+ if (err >= 0 && hc->clock_gated)
+ err = tplg_save_printf(dst, pfx, "\tpm_gate_clocks 1\n");
+ if (err >= 0 && hc->tdm_slots)
+ err = tplg_save_printf(dst, pfx, "\ttdm_slots %u\n",
+ hc->tdm_slots);
+ if (err >= 0 && hc->tdm_slot_width)
+ err = tplg_save_printf(dst, pfx, "\ttdm_slot_width %u\n",
+ hc->tdm_slot_width);
+ if (err >= 0 && hc->tx_slots)
+ err = tplg_save_printf(dst, pfx, "\ttx_slots %u\n",
+ hc->tx_slots);
+ if (err >= 0 && hc->rx_slots)
+ err = tplg_save_printf(dst, pfx, "\trx_slots %u\n",
+ hc->rx_slots);
+ if (err >= 0 && hc->tx_channels)
+ err = tplg_save_printf(dst, pfx, "\ttx_channels %u\n",
+ hc->tx_channels);
+ if (err >= 0 && hc->rx_channels)
+ err = tplg_save_printf(dst, pfx, "\trx_channels %u\n",
+ hc->rx_channels);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "}\n");
+ return err;
+}
+
/* copy stream object */
static void tplg_add_stream_object(struct snd_soc_tplg_stream *strm,
struct snd_tplg_stream_template *strm_tpl)
diff --git a/src/topology/save.c b/src/topology/save.c
new file mode 100644
index 00000000..0498911f
--- /dev/null
+++ b/src/topology/save.c
@@ -0,0 +1,632 @@
+/*
+ Copyright(c) 2019 Red Hat Inc.
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ Authors: Jaroslav Kysela <perex@perex.cz>
+*/
+
+#include "list.h"
+#include "tplg_local.h"
+
+#define SAVE_ALLOC_SHIFT (13) /* 8192 bytes */
+
+int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...)
+{
+ va_list va;
+ char buf[1024], *s;
+ size_t n, l, t, pl;
+
+ if (pfx == NULL)
+ pfx = "";
+
+ va_start(va, fmt);
+ n = vsnprintf(buf, sizeof(buf), fmt, va);
+ va_end(va);
+
+ if (n >= sizeof(buf))
+ return -EOVERFLOW;
+
+ pl = strlen(pfx);
+ l = *dst ? strlen(*dst) : 0;
+ t = l + pl + n + 1;
+ /* allocate chunks */
+ if (*dst == NULL ||
+ (l >> SAVE_ALLOC_SHIFT) != (t >> SAVE_ALLOC_SHIFT)) {
+ s = realloc(*dst, ((t >> SAVE_ALLOC_SHIFT) + 1) <<
+ SAVE_ALLOC_SHIFT);
+ if (s == NULL) {
+ free(*dst);
+ *dst = NULL;
+ return -ENOMEM;
+ }
+ } else {
+ s = *dst;
+ }
+
+ if (pl > 0)
+ strcpy(s + l, pfx);
+ strcpy(s + l + pl, buf);
+ *dst = s;
+ return 0;
+}
+
+int tplg_nice_value_format(char *dst, size_t dst_size, unsigned int value)
+{
+ if ((value % 1000) != 0) {
+ if (value > 0xfffffff0)
+ return snprintf(dst, dst_size, "%d", (int)value);
+ if (value >= 0xffff0000)
+ return snprintf(dst, dst_size, "0x%x", value);
+ }
+ return snprintf(dst, dst_size, "%u", value);
+}
+
+static int tplg_pprint_integer(snd_config_t *n, char **ret)
+{
+ long lval;
+ int err, type;
+ char buf[16];
+
+ type = snd_config_get_type(n);
+ if (type == SND_CONFIG_TYPE_INTEGER) {
+ err = snd_config_get_integer(n, &lval);
+ if (err < 0)
+ return err;
+ if (lval < INT_MIN || lval > UINT_MAX)
+ return snd_config_get_ascii(n, ret);
+ } else if (type == SND_CONFIG_TYPE_INTEGER64) {
+ long long llval;
+ err = snd_config_get_integer64(n, &llval);
+ if (err < 0)
+ return err;
+ if (llval < INT_MIN || llval > UINT_MAX)
+ return snd_config_get_ascii(n, ret);
+ lval = llval;
+ }
+ err = tplg_nice_value_format(buf, sizeof(buf), (unsigned int)lval);
+ if (err < 0)
+ return err;
+ *ret = strdup(buf);
+ if (*ret == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static int tplg_check_array_item(const char *id, int index)
+{
+ const char *p;
+ long int val;
+
+ for (p = id; *p; p++) {
+ if (*p < '0' || *p > '9')
+ return 0;
+ }
+
+ errno = 0;
+ val = strtol(id, NULL, 10);
+ return errno == 0 && val == index;
+}
+
+static int _compar(const void *a, const void *b)
+{
+ const snd_config_t *c1 = *(snd_config_t **)a;
+ const snd_config_t *c2 = *(snd_config_t **)b;
+ const char *id1, *id2;
+ if (snd_config_get_id(c1, &id1)) return 0;
+ if (snd_config_get_id(c2, &id2)) return 0;
+ return strcmp(id1, id2);
+}
+
+static snd_config_t *sort_config(const char *id, snd_config_t *src)
+{
+ snd_config_t *dst, **a;
+ snd_config_iterator_t i, next;
+ int index, array, count;
+
+ if (snd_config_get_type(src) != SND_CONFIG_TYPE_COMPOUND) {
+
+ if (snd_config_copy(&dst, src) >= 0)
+ return dst;
+ return NULL;
+ }
+ count = 0;
+ snd_config_for_each(i, next, src)
+ count++;
+ a = malloc(sizeof(dst) * count);
+ if (a == NULL)
+ return NULL;
+ index = array = 0;
+ snd_config_for_each(i, next, src) {
+ snd_config_t *s = snd_config_iterator_entry(i);
+ const char *id2;
+ a[index++] = s;
+ if (array < 0)
+ continue;
+ if (snd_config_get_id(s, &id2)) {
+ free(a);
+ return NULL;
+ }
+ if (array >= 0 && tplg_check_array_item(id2, array))
+ array++;
+ else
+ array = -1;
+ }
+ if (array < 0)
+ qsort(a, count, sizeof(a[0]), _compar);
+ if (snd_config_make_compound(&dst, id, count == 1)) {
+ free(a);
+ return NULL;
+ }
+ for (index = 0; index < count; index++) {
+ snd_config_t *s = a[index];
+ const char *id2;
+ if (snd_config_get_id(s, &id2)) {
+ snd_config_delete(dst);
+ free(a);
+ return NULL;
+ }
+ s = sort_config(id2, s);
+ if (s == NULL || snd_config_add(dst, s)) {
+ if (s)
+ snd_config_delete(s);
+ snd_config_delete(dst);
+ free(a);
+ return NULL;
+ }
+ }
+ free(a);
+ return dst;
+}
+
+static int tplg_check_quoted(const unsigned char *p)
+{
+ for ( ; *p != '\0'; p++) {
+ switch (*p) {
+ case ' ':
+ case '=':
+ case ';':
+ case ',':
+ case '.':
+ case '{':
+ case '}':
+ case '\'':
+ case '"':
+ return 1;
+ default:
+ if (*p <= 31 || *p >= 127)
+ return 1;
+
+ }
+ }
+ return 0;
+}
+
+static int tplg_save_quoted(char **dst, const char *str)
+{
+ static const char nibble[16] = "0123456789abcdef";
+ unsigned char *p, *d, *t;
+ int c;
+
+ d = t = alloca(strlen(str) * 5 + 1 + 1);
+ for (p = (unsigned char *)str; *p != '\0'; p++) {
+ c = *p;
+ switch (c) {
+ case '\n':
+ *t++ = '\\';
+ *t++ = 'n';
+ break;
+ case '\t':
+ *t++ = '\\';
+ *t++ = 't';
+ break;
+ case '\v':
+ *t++ = '\\';
+ *t++ = 'v';
+ break;
+ case '\b':
+ *t++ = '\\';
+ *t++ = 'b';
+ break;
+ case '\r':
+ *t++ = '\\';
+ *t++ = 'r';
+ break;
+ case '\f':
+ *t++ = '\\';
+ *t++ = 'f';
+ break;
+ case '\'':
+ *t++ = '\\';
+ *t++ = c;
+ break;
+ default:
+ if (c >= 32 && c <= 126) {
+ *t++ = c;
+ } else {
+ *t++ = '\\';
+ *t++ = 'x';
+ *t++ = nibble[(c >> 4) & 0x0f];
+ *t++ = nibble[(c >> 0) & 0x0f];
+ }
+ break;
+ }
+ }
+ *t = '\0';
+ return tplg_save_printf(dst, NULL, "'%s'", d);
+}
+
+static int tplg_save_string(char **dst, const char *str, int id)
+{
+ const unsigned char *p = (const unsigned char *)str;
+
+ if (!p || !*p)
+ return tplg_save_printf(dst, NULL, "''");
+
+ if (!id && ((*p >= '0' && *p <= '9') || *p == '-'))
+ return tplg_save_quoted(dst, str);
+
+ if (tplg_check_quoted(p))
+ return tplg_save_quoted(dst, str);
+
+ return tplg_save_printf(dst, NULL, "%s", str);
+}
+
+static int save_config(char **dst, int level, const char *delim, snd_config_t *src)
+{
+ snd_config_iterator_t i, next;
+ snd_config_t *s;
+ const char *id;
+ char *pfx;
+ unsigned int count;
+ int type, err, quoted, array;
+
+ if (delim == NULL)
+ delim = "";
+
+ type = snd_config_get_type(src);
+ if (type != SND_CONFIG_TYPE_COMPOUND) {
+ char *val;
+ if (type == SND_CONFIG_TYPE_INTEGER ||
+ type == SND_CONFIG_TYPE_INTEGER64) {
+ err = tplg_pprint_integer(src, &val);
+ } else {
+ err = snd_config_get_ascii(src, &val);
+ }
+ if (err < 0)
+ return err;
+ if (type == SND_CONFIG_TYPE_STRING) {
+ /* hexa array pretty print */
+ id = strchr(val, '\n');
+ if (id) {
+ err = tplg_save_printf(dst, NULL, "\n");
+ if (err < 0)
+ goto retval;
+ for (id++; *id == '\t'; id++) {
+ err = tplg_save_printf(dst, NULL, "\t");
+ if (err < 0)
+ goto retval;
+ }
+ delim = "";
+ }
+ err = tplg_save_printf(dst, NULL, "%s'%s'\n", delim, val);
+ } else {
+ err = tplg_save_printf(dst, NULL, "%s%s\n", delim, val);
+ }
+retval:
+ free(val);
+ return err;
+ }
+
+ count = 0;
+ quoted = 0;
+ array = 0;
+ s = NULL;
+ snd_config_for_each(i, next, src) {
+ s = snd_config_iterator_entry(i);
+ err = snd_config_get_id(s, &id);
+ if (err < 0)
+ return err;
+ if (!quoted && tplg_check_quoted((unsigned char *)id))
+ quoted = 1;
+ if (array >= 0 && tplg_check_array_item(id, array))
+ array++;
+ else
+ array = -1;
+ count++;
+ }
+ if (count == 0)
+ return 0;
+
+ if (count == 1) {
+ err = snd_config_get_id(s, &id);
+ if (err >= 0 && level > 0)
+ err = tplg_save_printf(dst, NULL, ".");
+ if (err >= 0)
+ err = tplg_save_string(dst, id, 1);
+ if (err >= 0)
+ err = save_config(dst, level, " ", s);
+ return err;
+ }
+
+ pfx = alloca(level + 1);
+ memset(pfx, '\t', level);
+ pfx[level] = '\0';
+
+ if (level > 0) {
+ err = tplg_save_printf(dst, NULL, "%s%s\n", delim,
+ array >= 0 ? "[" : "{");
+ if (err < 0)
+ return err;
+ }
+
+ snd_config_for_each(i, next, src) {
+ s = snd_config_iterator_entry(i);
+ const char *id;
+ err = snd_config_get_id(s, &id);
+ if (err < 0)
+ return err;
+ err = tplg_save_printf(dst, pfx, "");
+ if (err < 0)
+ return err;
+ if (array < 0) {
+ delim = " ";
+ if (quoted) {
+ err = tplg_save_quoted(dst, id);
+ } else {
+ err = tplg_save_string(dst, id, 1);
+ if (err < 0)
+ return err;
+ }
+ } else {
+ delim = "";
+ }
+ err = save_config(dst, level + 1, delim, s);
+ if (err < 0)
+ return err;
+ }
+
+ if (level > 0) {
+ pfx[level - 1] = '\0';
+ err = tplg_save_printf(dst, pfx, "%s\n",
+ array >= 0 ? "]" : "}");
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int tplg_save(snd_tplg_t *tplg, char **dst, int gindex, const char *prefix)
+{
+ struct tplg_table *tptr;
+ struct tplg_elem *elem;
+ struct list_head *list, *pos;
+ char pfx2[16];
+ unsigned int index;
+ int err, count;
+
+ snprintf(pfx2, sizeof(pfx2), "%s\t", prefix ?: "");
+
+ /* write all blocks */
+ for (index = 0; index < tplg_table_items; index++) {
+ tptr = &tplg_table[index];
+ list = (struct list_head *)((void *)tplg + tptr->loff);
+
+ /* count elements */
+ count = 0;
+ list_for_each(pos, list) {
+ elem = list_entry(pos, struct tplg_elem, list);
+ if (gindex >= 0 && elem->index != gindex)
+ continue;
+ if (tptr->save == NULL && tptr->gsave == NULL) {
+ SNDERR("unable to create %s block (no callback)",
+ tptr->id);
+ err = -ENXIO;
+ goto _err;
+ }
+ if (tptr->save)
+ count++;
+ }
+
+ if (count == 0)
+ continue;
+
+ if (count > 1) {
+ err = tplg_save_printf(dst, prefix, "%s {\n",
+ elem->table ?
+ elem->table->id : "_NOID_");
+ } else {
+ err = tplg_save_printf(dst, prefix, "%s.",
+ elem->table ?
+ elem->table->id : "_NOID_");
+ }
+
+ if (err < 0)
+ goto _err;
+
+ list_for_each(pos, list) {
+ elem = list_entry(pos, struct tplg_elem, list);
+ if (gindex >= 0 && elem->index != gindex)
+ continue;
+ if (count > 1) {
+ err = tplg_save_printf(dst, pfx2, "");
+ if (err < 0)
+ goto _err;
+ }
+ err = tptr->save(tplg, elem, dst, count > 1 ? pfx2 : prefix);
+ if (err < 0) {
+ SNDERR("failed to save %s elements: %s",
+ tptr->id, snd_strerror(-err));
+ goto _err;
+ }
+ }
+ if (count > 1) {
+ err = tplg_save_printf(dst, prefix, "}\n");
+ if (err < 0)
+ goto _err;
+ }
+ }
+
+ /* save globals */
+ for (index = 0; index < tplg_table_items; index++) {
+ tptr = &tplg_table[index];
+ if (tptr->gsave) {
+ err = tptr->gsave(tplg, gindex, dst, prefix);
+ if (err < 0)
+ goto _err;
+ }
+ }
+
+ return 0;
+
+_err:
+ free(*dst);
+ *dst = NULL;
+ return err;
+}
+
+static int tplg_index_compar(const void *a, const void *b)
+{
+ const int *a1 = a, *b1 = b;
+ return *a1 - *b1;
+}
+
+static int tplg_index_groups(snd_tplg_t *tplg, int **indexes)
+{
+ struct tplg_table *tptr;
+ struct tplg_elem *elem;
+ struct list_head *list, *pos;
+ unsigned int index, j, count, size;
+ int *a, *b;
+
+ count = 0;
+ size = 16;
+ a = malloc(size * sizeof(a[0]));
+
+ for (index = 0; index < tplg_table_items; index++) {
+ tptr = &tplg_table[index];
+ list = (struct list_head *)((void *)tplg + tptr->loff);
+ list_for_each(pos, list) {
+ elem = list_entry(pos, struct tplg_elem, list);
+ for (j = 0; j < count; j++) {
+ if (a[j] == elem->index)
+ break;
+ }
+ if (j < count)
+ continue;
+ if (count + 1 >= size) {
+ size += 8;
+ b = realloc(a, size * sizeof(a[0]));
+ if (b == NULL) {
+ free(a);
+ return -ENOMEM;
+ }
+ a = b;
+ }
+ a[count++] = elem->index;
+ }
+ }
+ a[count] = -1;
+
+ qsort(a, count, sizeof(a[0]), tplg_index_compar);
+
+ *indexes = a;
+ return 0;
+}
+
+int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags)
+{
+ snd_input_t *in;
+ snd_config_t *top, *top2;
+ char *dst2;
+ int *indexes, *a;
+ int err;
+
+ assert(tplg);
+ assert(dst);
+ *dst = NULL;
+
+ if (flags & SND_TPLG_SAVE_GROUPS) {
+ err = tplg_index_groups(tplg, &indexes);
+ if (err < 0)
+ return err;
+ for (a = indexes; err >= 0 && *a >= 0; a++) {
+ err = tplg_save_printf(dst, NULL,
+ "IndexGroup.%d {\n",
+ *a);
+ if (err >= 0)
+ err = tplg_save(tplg, dst, *a, "\t");
+ if (err >= 0)
+ err = tplg_save_printf(dst, NULL, "}\n");
+ }
+ free(indexes);
+ } else {
+ err = tplg_save(tplg, dst, -1, NULL);
+ }
+
+ if (err < 0)
+ goto _err;
+
+ if (flags & SND_TPLG_SAVE_NOCHECK)
+ return 0;
+
+ /* always load configuration - check */
+ err = snd_input_buffer_open(&in, *dst, strlen(*dst));
+ if (err < 0) {
+ SNDERR("could not create input buffer");
+ goto _err;
+ }
+
+ err = snd_config_top(&top);
+ if (err < 0) {
+ snd_input_close(in);
+ goto _err;
+ }
+
+ err = snd_config_load(top, in);
+ snd_input_close(in);
+ if (err < 0) {
+ SNDERR("could not load configuration");
+ snd_config_delete(top);
+ goto _err;
+ }
+
+ if (flags & SND_TPLG_SAVE_SORT) {
+ top2 = sort_config(NULL, top);
+ if (top2 == NULL) {
+ SNDERR("could not sort configuration");
+ snd_config_delete(top);
+ err = -EINVAL;
+ goto _err;
+ }
+ snd_config_delete(top);
+ top = top2;
+ }
+
+ dst2 = NULL;
+ err = save_config(&dst2, 0, NULL, top);
+ snd_config_delete(top);
+ if (err < 0) {
+ SNDERR("could not save configuration");
+ goto _err;
+ }
+
+ free(*dst);
+ *dst = dst2;
+ return 0;
+
+_err:
+ free(*dst);
+ *dst = NULL;
+ return err;
+}
diff --git a/src/topology/text.c b/src/topology/text.c
index f301a4de..e9386e7d 100644
--- a/src/topology/text.c
+++ b/src/topology/text.c
@@ -89,3 +89,22 @@ int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
return err;
}
+
+/* save text data */
+int tplg_save_text(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
+{
+ struct tplg_texts *texts = elem->texts;
+ unsigned int i;
+ int err;
+
+ if (!texts || texts->num_items == 0)
+ return 0;
+ err = tplg_save_printf(dst, pfx, "'%s'.values [\n", elem->id);
+ for (i = 0; err >= 0 && i < texts->num_items; i++)
+ err = tplg_save_printf(dst, pfx, "\t'%s'\n", texts->items[i][0]);
+ if (err >= 0)
+ err = tplg_save_printf(dst, pfx, "]\n");
+ return err;
+}
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index bea88ba3..42a3aa96 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -37,6 +37,7 @@
struct tplg_ref;
struct tplg_elem;
+struct tplg_table;
typedef enum _snd_pcm_rates {
SND_PCM_RATE_UNKNOWN = -1,
@@ -147,6 +148,8 @@ struct tplg_vendor_tuples {
/* topology element */
struct tplg_elem {
+ struct tplg_table *table;
+
char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
int index;
@@ -209,6 +212,10 @@ struct tplg_table {
unsigned enew: 1;
void (*free)(void *);
int (*parse)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+ int (*save)(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *prefix);
+ int (*gsave)(snd_tplg_t *tplg, int index,
+ char **dst, const char *prefix);
};
extern struct tplg_table tplg_table[];
@@ -250,7 +257,8 @@ int tplg_build_pcm_dai(snd_tplg_t *tplg, unsigned int type);
int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem,
struct tplg_ref *ref);
-int tplg_parse_data_refs(snd_config_t *cfg, struct tplg_elem *elem);
+int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem,
+ unsigned int type);
int tplg_ref_add(struct tplg_elem *elem, int type, const char* id);
int tplg_ref_add_elem(struct tplg_elem *elem, struct tplg_elem *elem_ref);
@@ -269,9 +277,11 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
int tplg_get_integer(snd_config_t *n, int *val, int base);
int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base);
+const char *tplg_channel_name(int type);
int tplg_parse_channel(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_t *cfg, void *private);
+const char *tplg_ops_name(int type);
int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_t *cfg, void *private);
int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
@@ -299,3 +309,49 @@ int tplg_build_links(snd_tplg_t *tplg, unsigned int type);
int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
+
+int tplg_nice_value_format(char *dst, size_t dst_size, unsigned int value);
+
+int tplg_save_printf(char **dst, const char *prefix, const char *fmt, ...);
+int tplg_save_refs(snd_tplg_t *tplg, struct tplg_elem *elem, unsigned int type,
+ const char *id, char **dst, const char *pfx);
+int tplg_save_channels(snd_tplg_t *tplg, struct snd_soc_tplg_channel *channel,
+ unsigned int channel_count, char **dst, const char *pfx);
+int tplg_save_ops(snd_tplg_t *tplg, struct snd_soc_tplg_ctl_hdr *hdr,
+ char **dst, const char *pfx);
+int tplg_save_ext_ops(snd_tplg_t *tplg, struct snd_soc_tplg_bytes_control *be,
+ char **dst, const char *pfx);
+int tplg_save_manifest_data(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_control_mixer(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_control_enum(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_control_bytes(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_tlv(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_data(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_text(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_tokens(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_tuples(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_dapm_graph(snd_tplg_t *tplg, int index,
+ char **dst, const char *pfx);
+int tplg_save_dapm_widget(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_link(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_cc(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_pcm(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_hw_config(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_stream_caps(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
+int tplg_save_dai(snd_tplg_t *tplg, struct tplg_elem *elem,
+ char **dst, const char *pfx);
--
2.24.1
From b336aea507b80493cdae439f09f710eec4bcd4ae Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 20 Dec 2019 14:59:00 +0100
Subject: [PATCH 44/69] topology: add snd_tplg_create() with flags
Add SND_TPLG_CREATE_VERBOSE and SND_TPLG_CREATE_DAPM_NOSORT
flags for the special operations.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/topology.h | 10 ++++++++++
src/topology/dapm.c | 5 ++++-
src/topology/parser.c | 10 +++++++++-
src/topology/tplg_local.h | 1 +
4 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/include/topology.h b/include/topology.h
index 69aa5ed7..63c13a98 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -771,12 +771,22 @@ enum snd_tplg_type {
/** Fit for all user cases */
#define SND_TPLG_INDEX_ALL 0
+/** Flags for the snd_tplg_create */
+#define SND_TPLG_CREATE_VERBOSE (1<<0) /*!< Verbose output */
+#define SND_TPLG_CREATE_DAPM_NOSORT (1<<1) /*!< Do not sort DAPM objects by index */
+
/**
* \brief Create a new topology parser instance.
* \return New topology parser instance
*/
snd_tplg_t *snd_tplg_new(void);
+/**
+ * \brief Create a new topology parser instance.
+ * \return New topology parser instance
+ */
+snd_tplg_t *snd_tplg_create(int flags);
+
/**
* \brief Free a topology parser instance.
* \param tplg Topology parser instance
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index 2bdacedc..d6c15fc1 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -268,7 +268,10 @@ struct tplg_elem *tplg_elem_new_route(snd_tplg_t *tplg, int index)
return NULL;
elem->index = index;
- tplg_elem_insert(elem, &tplg->route_list);
+ if (tplg->dapm_sort)
+ tplg_elem_insert(elem, &tplg->route_list);
+ else
+ list_add_tail(&elem->list, &tplg->route_list);
strcpy(elem->id, "line");
elem->type = SND_TPLG_TYPE_DAPM_GRAPH;
elem->size = sizeof(*line);
diff --git a/src/topology/parser.c b/src/topology/parser.c
index de5edd1b..8f810f75 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -432,7 +432,7 @@ static bool is_little_endian(void)
return false;
}
-snd_tplg_t *snd_tplg_new(void)
+snd_tplg_t *snd_tplg_create(int flags)
{
snd_tplg_t *tplg;
@@ -445,6 +445,9 @@ snd_tplg_t *snd_tplg_new(void)
if (!tplg)
return NULL;
+ tplg->verbose = !!(flags & SND_TPLG_CREATE_VERBOSE);
+ tplg->dapm_sort = (flags & SND_TPLG_CREATE_DAPM_NOSORT) == 0;
+
tplg->manifest.size = sizeof(struct snd_soc_tplg_manifest);
INIT_LIST_HEAD(&tplg->tlv_list);
@@ -469,6 +472,11 @@ snd_tplg_t *snd_tplg_new(void)
return tplg;
}
+snd_tplg_t *snd_tplg_new(void)
+{
+ return snd_tplg_create(0);
+}
+
void snd_tplg_free(snd_tplg_t *tplg)
{
free(tplg->bin);
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 42a3aa96..74b3a55c 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -66,6 +66,7 @@ struct snd_tplg {
size_t bin_size;
int verbose;
+ unsigned int dapm_sort: 1;
unsigned int version;
/* runtime state */
--
2.24.1
From 0793ef064a97afd0b1335af0d187ede227b90582 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 20 Dec 2019 21:28:30 +0100
Subject: [PATCH 45/69] topology: add snd_tplg_version() function
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/topology.h | 6 ++++++
src/topology/parser.c | 5 +++++
2 files changed, 11 insertions(+)
diff --git a/include/topology.h b/include/topology.h
index 63c13a98..37bced1a 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -775,6 +775,12 @@ enum snd_tplg_type {
#define SND_TPLG_CREATE_VERBOSE (1<<0) /*!< Verbose output */
#define SND_TPLG_CREATE_DAPM_NOSORT (1<<1) /*!< Do not sort DAPM objects by index */
+/**
+ * \brief Return the version of the topology library.
+ * \return A static string with the version number.
+ */
+const char *snd_tplg_version(void);
+
/**
* \brief Create a new topology parser instance.
* \return New topology parser instance
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 8f810f75..1eaa24bd 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -503,3 +503,8 @@ void snd_tplg_free(snd_tplg_t *tplg)
free(tplg);
}
+
+const char *snd_tplg_version(void)
+{
+ return SND_LIB_VERSION_STR;
+}
--
2.24.1
From f42b2c088a23e1c6156c0d5710efd7689b8c15be Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 20 Dec 2019 23:48:40 +0100
Subject: [PATCH 46/69] topology: cleanup the SNDERR() calls
- remove the wrong new lines
- remove error/warning prefixes (error is error)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 16 ++++++-------
src/topology/channel.c | 2 +-
src/topology/ctl.c | 36 +++++++++++++---------------
src/topology/dapm.c | 40 ++++++++++++++-----------------
src/topology/data.c | 53 +++++++++++++++++++++---------------------
src/topology/parser.c | 33 +++++++++++++-------------
src/topology/pcm.c | 29 +++++++++++------------
src/topology/text.c | 2 +-
8 files changed, 99 insertions(+), 112 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index cadb5583..74c44405 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -65,8 +65,8 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type,
/* make sure file offset is aligned with the calculated HDR offset */
if (tplg->bin_pos != tplg->next_hdr_pos) {
- SNDERR("error: New header is at offset 0x%zx but file"
- " offset 0x%zx is %s by %ld bytes\n",
+ SNDERR("New header is at offset 0x%zx but file"
+ " offset 0x%zx is %s by %ld bytes",
tplg->next_hdr_pos, tplg->bin_pos,
tplg->bin_pos > tplg->next_hdr_pos ? "ahead" : "behind",
labs(tplg->bin_pos - tplg->next_hdr_pos));
@@ -108,7 +108,7 @@ static int write_elem_block(snd_tplg_t *tplg,
ret = write_block_header(tplg, tplg_type, elem->vendor_type,
tplg->version, elem->index, block_size, count);
if (ret < 0) {
- SNDERR("error: failed to write %s block %d\n",
+ SNDERR("failed to write %s block %d",
obj_name, ret);
return ret;
}
@@ -148,7 +148,7 @@ static int write_elem_block(snd_tplg_t *tplg,
/* make sure we have written the correct size */
if (total_size != size) {
- SNDERR("error: size mismatch. Expected %zu wrote %zu\n",
+ SNDERR("size mismatch. Expected %zu wrote %zu",
size, total_size);
return -EIO;
}
@@ -221,7 +221,7 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg)
tplg->version, 0,
sizeof(tplg->manifest) + tplg->manifest.priv.size, 1);
if (ret < 0) {
- SNDERR("error: failed to write manifest block\n");
+ SNDERR("failed to write manifest block");
return ret;
}
@@ -266,7 +266,7 @@ int tplg_write_data(snd_tplg_t *tplg)
/* write manifest */
ret = write_manifest_data(tplg);
if (ret < 0) {
- SNDERR("failed to write manifest %d\n", ret);
+ SNDERR("failed to write manifest %d", ret);
return ret;
}
@@ -286,7 +286,7 @@ int tplg_write_data(snd_tplg_t *tplg)
ret = write_elem_block(tplg, list, size,
tptr->tsoc, tptr->name);
if (ret < 0) {
- SNDERR("failed to write %s elements: %s\n",
+ SNDERR("failed to write %s elements: %s",
tptr->name, snd_strerror(-ret));
return ret;
}
@@ -295,7 +295,7 @@ int tplg_write_data(snd_tplg_t *tplg)
verbose(tplg, "total size is 0x%zx/%zd\n", tplg->bin_pos, tplg->bin_pos);
if (total_size != tplg->bin_pos) {
- SNDERR("total size mismatch (%zd != %zd)\n",
+ SNDERR("total size mismatch (%zd != %zd)",
total_size, tplg->bin_pos);
return -EINVAL;
}
diff --git a/src/topology/channel.c b/src/topology/channel.c
index b54a10c8..110775a8 100644
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -104,7 +104,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
channel_id = lookup_channel(id);
if (channel_id < 0) {
- SNDERR("error: invalid channel %s\n", id);
+ SNDERR("invalid channel %s", id);
return -EINVAL;
}
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 979cc1b0..03874b27 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -94,7 +94,7 @@ int parse_access(snd_config_t *cfg,
if (strcmp(id, "access") == 0) {
err = parse_access_values(n, hdr);
if (err < 0) {
- SNDERR("error: failed to parse access");
+ SNDERR("failed to parse access");
return err;
}
continue;
@@ -187,8 +187,8 @@ static int tplg_build_mixer_control(snd_tplg_t *tplg,
}
if (!ref->elem) {
- SNDERR("error: cannot find '%s' referenced by"
- " control '%s'\n", ref->id, elem->id);
+ SNDERR("cannot find '%s' referenced by"
+ " control '%s'", ref->id, elem->id);
return -EINVAL;
} else if (err < 0)
return err;
@@ -236,8 +236,8 @@ static int tplg_build_enum_control(snd_tplg_t *tplg,
return err;
}
if (!ref->elem) {
- SNDERR("error: cannot find '%s' referenced by"
- " control '%s'\n", ref->id, elem->id);
+ SNDERR("cannot find '%s' referenced by"
+ " control '%s'", ref->id, elem->id);
return -EINVAL;
}
}
@@ -341,10 +341,8 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
n = snd_config_iterator_entry(i);
/* get ID */
- if (snd_config_get_id(n, &id) < 0) {
- SNDERR("error: cant get ID\n");
+ if (snd_config_get_id(n, &id) < 0)
return -EINVAL;
- }
/* get value */
if (tplg_get_integer(n, &val, 0))
@@ -360,7 +358,7 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
else if (strcmp(id, "mute") == 0)
scale->mute = val;
else
- SNDERR("error: unknown key %s\n", id);
+ SNDERR("unknown id '%s'", id);
}
return 0;
@@ -389,7 +387,7 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "scale") == 0) {
err = tplg_parse_tlv_dbscale(n, elem);
if (err < 0) {
- SNDERR("error: failed to DBScale");
+ SNDERR("failed to DBScale");
return err;
}
continue;
@@ -651,8 +649,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "channel") == 0) {
if (ec->num_channels >= SND_SOC_TPLG_MAX_CHAN) {
- SNDERR("error: too many channels %s\n",
- elem->id);
+ SNDERR("too many channels %s", elem->id);
return -EINVAL;
}
@@ -779,8 +776,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
if (strcmp(id, "channel") == 0) {
if (mc->num_channels >= SND_SOC_TPLG_MAX_CHAN) {
- SNDERR("error: too many channels %s\n",
- elem->id);
+ SNDERR("too many channels %s", elem->id);
return -EINVAL;
}
@@ -933,7 +929,7 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
struct snd_soc_tplg_tlv_dbscale *scale;
if (!tlvt) {
- SNDERR("error: missing TLV data\n");
+ SNDERR("missing TLV data");
return -EINVAL;
}
@@ -952,7 +948,7 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
/* TODO: add support for other TLV types */
default:
- SNDERR("error: unsupported TLV type %d\n", tlv->type);
+ SNDERR("unsupported TLV type %d", tlv->type);
break;
}
}
@@ -971,7 +967,7 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
tplg_dbg(" Control Mixer: %s\n", mixer->hdr.name);
if (mixer->hdr.type != SND_SOC_TPLG_TYPE_MIXER) {
- SNDERR("error: invalid mixer type %d\n", mixer->hdr.type);
+ SNDERR("invalid mixer type %d", mixer->hdr.type);
return -EINVAL;
}
@@ -1039,7 +1035,7 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
tplg_dbg(" Control Enum: %s\n", enum_ctl->hdr.name);
if (enum_ctl->hdr.type != SND_SOC_TPLG_TYPE_ENUM) {
- SNDERR("error: invalid enum type %d\n", enum_ctl->hdr.type);
+ SNDERR("invalid enum type %d", enum_ctl->hdr.type);
return -EINVAL;
}
@@ -1113,7 +1109,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
tplg_dbg(" Control Bytes: %s\n", bytes_ctl->hdr.name);
if (bytes_ctl->hdr.type != SND_SOC_TPLG_TYPE_BYTES) {
- SNDERR("error: invalid bytes type %d\n", bytes_ctl->hdr.type);
+ SNDERR("invalid bytes type %d", bytes_ctl->hdr.type);
return -EINVAL;
}
@@ -1157,7 +1153,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
if ((be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)
!= SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
- SNDERR("error: Invalid TLV bytes control access 0x%x\n",
+ SNDERR("Invalid TLV bytes control access 0x%x",
be->hdr.access);
tplg_elem_free(elem);
return -EINVAL;
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index d6c15fc1..f61fe071 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -154,8 +154,7 @@ static int tplg_build_widget(snd_tplg_t *tplg, struct tplg_elem *elem)
}
if (!ref->elem) {
- SNDERR("error: cannot find '%s'"
- " referenced by widget '%s'\n",
+ SNDERR("cannot find '%s' referenced by widget '%s'",
ref->id, elem->id);
return -EINVAL;
}
@@ -179,8 +178,7 @@ int tplg_build_widgets(snd_tplg_t *tplg)
elem = list_entry(pos, struct tplg_elem, list);
if (!elem->widget || elem->type != SND_TPLG_TYPE_DAPM_WIDGET) {
- SNDERR("error: invalid widget '%s'\n",
- elem->id);
+ SNDERR("invalid widget '%s'", elem->id);
return -EINVAL;
}
@@ -207,8 +205,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
elem = list_entry(pos, struct tplg_elem, list);
if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH) {
- SNDERR("error: invalid route '%s'\n",
- elem->id);
+ SNDERR("invalid route '%s'", elem->id);
return -EINVAL;
}
@@ -218,14 +215,13 @@ int tplg_build_routes(snd_tplg_t *tplg)
/* validate sink */
if (strlen(route->sink) <= 0) {
- SNDERR("error: no sink\n");
+ SNDERR("no sink");
return -EINVAL;
}
if (!tplg_elem_lookup(&tplg->widget_list, route->sink,
SND_TPLG_TYPE_DAPM_WIDGET, SND_TPLG_INDEX_ALL)) {
- SNDERR("warning: undefined sink widget/stream '%s'\n",
- route->sink);
+ SNDERR("undefined sink widget/stream '%s'", route->sink);
}
/* validate control name */
@@ -234,21 +230,21 @@ int tplg_build_routes(snd_tplg_t *tplg)
SND_TPLG_TYPE_MIXER, elem->index) &&
!tplg_elem_lookup(&tplg->enum_list, route->control,
SND_TPLG_TYPE_ENUM, elem->index)) {
- SNDERR("warning: Undefined mixer/enum control '%s'\n",
- route->control);
+ SNDERR("Undefined mixer/enum control '%s'",
+ route->control);
}
}
/* validate source */
if (strlen(route->source) <= 0) {
- SNDERR("error: no source\n");
+ SNDERR("no source");
return -EINVAL;
}
if (!tplg_elem_lookup(&tplg->widget_list, route->source,
SND_TPLG_TYPE_DAPM_WIDGET, SND_TPLG_INDEX_ALL)) {
- SNDERR("warning: Undefined source widget/stream '%s'\n",
- route->source);
+ SNDERR("Undefined source widget/stream '%s'",
+ route->source);
}
/* add graph to manifest */
@@ -300,7 +296,7 @@ static int tplg_parse_line(const char *text,
len = strlen(buf);
if (len <= 2) {
- SNDERR("error: invalid route \"%s\"\n", buf);
+ SNDERR("invalid route \"%s\"", buf);
return -EINVAL;
}
@@ -309,7 +305,7 @@ static int tplg_parse_line(const char *text,
if (buf[i] == ',')
goto second;
}
- SNDERR("error: invalid route \"%s\"\n", buf);
+ SNDERR("invalid route \"%s\"", buf);
return -EINVAL;
second:
@@ -323,7 +319,7 @@ second:
goto done;
}
- SNDERR("error: invalid route \"%s\"\n", buf);
+ SNDERR("invalid route \"%s\"", buf);
return -EINVAL;
done:
@@ -378,7 +374,7 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
int index = -1;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound is expected for dapm graph definition\n");
+ SNDERR("compound is expected for dapm graph definition");
return -EINVAL;
}
@@ -401,13 +397,13 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "lines") == 0) {
if (index < 0) {
- SNDERR("error: failed to parse dapm graph %s, missing index\n",
+ SNDERR("failed to parse dapm graph %s, missing index",
graph_id);
return -EINVAL;
}
err = tplg_parse_routes(tplg, n, index);
if (err < 0) {
- SNDERR("error: failed to parse dapm graph %s\n",
+ SNDERR("failed to parse dapm graph %s",
graph_id);
return err;
}
@@ -528,7 +524,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
widget_type = lookup_widget(val);
if (widget_type < 0){
- SNDERR("Widget '%s': Unsupported widget type %s\n",
+ SNDERR("widget '%s': Unsupported widget type %s",
elem->id, val);
return -EINVAL;
}
@@ -821,7 +817,7 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
break;
default:
- SNDERR("error: widget %s: invalid type %d for ctl %d\n",
+ SNDERR("widget %s: invalid type %d for ctl %d",
wt->name, ct->type, i);
break;
}
diff --git a/src/topology/data.c b/src/topology/data.c
index 11cd73f5..f00ed301 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -61,7 +61,7 @@ struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem)
priv = &elem->pcm->priv;
break;
default:
- SNDERR("error: '%s': no support for private data for type %d\n",
+ SNDERR("'%s': no support for private data for type %d",
elem->id, elem->type);
}
@@ -95,7 +95,7 @@ int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem,
}
if (cfg_type != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound type expected for %s", elem->id);
+ SNDERR("compound type expected for %s", elem->id);
return -EINVAL;
}
@@ -183,8 +183,7 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)
fp = fopen(filename, "r");
if (fp == NULL) {
- SNDERR("error: invalid data file path '%s'\n",
- filename);
+ SNDERR("invalid data file path '%s'", filename);
return -errno;
}
@@ -192,12 +191,12 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
if (size <= 0) {
- SNDERR("error: invalid data file size %zu\n", size);
+ SNDERR("invalid data file size %zu", size);
ret = -EINVAL;
goto err;
}
if (size > TPLG_MAX_PRIV_SIZE) {
- SNDERR("error: data file too big %zu\n", size);
+ SNDERR("data file too big %zu", size);
ret = -EINVAL;
goto err;
}
@@ -350,7 +349,7 @@ static int get_uuid(const char *str, unsigned char *uuid_le)
if ((errno == ERANGE && val == ULONG_MAX)
|| (errno != 0 && val == 0)
|| (val > UCHAR_MAX)) {
- SNDERR("error: invalid value for uuid\n");
+ SNDERR("invalid value for uuid");
ret = -EINVAL;
goto out;
}
@@ -365,7 +364,7 @@ static int get_uuid(const char *str, unsigned char *uuid_le)
}
if (values < 16) {
- SNDERR("error: less than 16 integers for uuid\n");
+ SNDERR("less than 16 integers for uuid");
ret = -EINVAL;
}
@@ -446,7 +445,7 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
num = get_hex_num(value);
if (num <= 0) {
- SNDERR("error: malformed hex variable list %s\n", value);
+ SNDERR("malformed hex variable list %s", value);
return -EINVAL;
}
@@ -454,7 +453,7 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
priv = elem->data;
if (size > TPLG_MAX_PRIV_SIZE) {
- SNDERR("error: data too big %d\n", size);
+ SNDERR("data too big %d", size);
return -EINVAL;
}
@@ -492,7 +491,7 @@ static int get_token_value(const char *token_id,
return tokens->token[i].value;
}
- SNDERR("error: cannot find token id '%s'\n", token_id);
+ SNDERR("cannot find token id '%s'", token_id);
return -1;
}
@@ -579,7 +578,7 @@ static int copy_tuples(struct tplg_elem *elem,
* tuple_set->num_tuples;
size += set_size;
if (size > TPLG_MAX_PRIV_SIZE) {
- SNDERR("error: data too big %d\n", size);
+ SNDERR("data too big %d", size);
return -EINVAL;
}
@@ -662,13 +661,13 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)
ref->id, SND_TPLG_TYPE_TUPLE, elem->index);
tuples = ref->elem;
if (!tuples) {
- SNDERR("error: cannot find tuples %s\n", ref->id);
+ SNDERR("cannot find tuples %s", ref->id);
return -EINVAL;
}
tokens = get_tokens(tplg, tuples);
if (!tokens) {
- SNDERR("error: cannot find token for %s\n", ref->id);
+ SNDERR("cannot find token for %s", ref->id);
return -EINVAL;
}
@@ -762,7 +761,7 @@ static int parse_tuple_set(snd_config_t *cfg,
type = get_tuple_type(id);
if (type < 0) {
- SNDERR("error: invalid tuple type '%s'", id);
+ SNDERR("invalid tuple type '%s'", id);
return type;
}
@@ -819,7 +818,7 @@ static int parse_tuple_set(snd_config_t *cfg,
case SND_SOC_TPLG_TUPLE_TYPE_WORD:
ival = tplg_get_unsigned(n, &tuple_val, 0);
if (ival < 0) {
- SNDERR("error: tuple %s: %s\n", id, snd_strerror(ival));
+ SNDERR("tuple %s: %s", id, snd_strerror(ival));
goto err;
}
@@ -829,7 +828,7 @@ static int parse_tuple_set(snd_config_t *cfg,
&& tuple_val > USHRT_MAX)
|| (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE
&& tuple_val > UCHAR_MAX)) {
- SNDERR("error: tuple %s: invalid value\n", id);
+ SNDERR("tuple %s: invalid value", id);
goto err;
}
@@ -941,7 +940,7 @@ static int parse_tuple_sets(snd_config_t *cfg,
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
if (snd_config_get_id(cfg, &id) >= 0)
- SNDERR("error: compound type expected for %s", id);
+ SNDERR("compound type expected for %s", id);
return -EINVAL;
}
@@ -959,8 +958,8 @@ static int parse_tuple_sets(snd_config_t *cfg,
snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i);
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound type expected for %s, is %d",
- id, snd_config_get_type(n));
+ SNDERR("compound type expected for %s, is %d",
+ id, snd_config_get_type(n));
return -EINVAL;
}
@@ -1169,7 +1168,7 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg,
int err;
if (!list_empty(&tplg->manifest_list)) {
- SNDERR("error: already has manifest data\n");
+ SNDERR("already has manifest data");
return -EINVAL;
}
@@ -1326,7 +1325,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "file") == 0) {
err = tplg_parse_data_file(n, elem);
if (err < 0) {
- SNDERR("error: failed to parse data file\n");
+ SNDERR("failed to parse data file");
return err;
}
continue;
@@ -1335,7 +1334,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "bytes") == 0) {
err = tplg_parse_data_hex(n, elem, 1);
if (err < 0) {
- SNDERR("error: failed to parse data bytes\n");
+ SNDERR("failed to parse data bytes");
return err;
}
continue;
@@ -1344,7 +1343,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "shorts") == 0) {
err = tplg_parse_data_hex(n, elem, 2);
if (err < 0) {
- SNDERR("error: failed to parse data shorts\n");
+ SNDERR("failed to parse data shorts");
return err;
}
continue;
@@ -1353,7 +1352,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
if (strcmp(id, "words") == 0) {
err = tplg_parse_data_hex(n, elem, 4);
if (err < 0) {
- SNDERR("error: failed to parse data words\n");
+ SNDERR("failed to parse data words");
return err;
}
continue;
@@ -1470,8 +1469,8 @@ int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem,
ref_elem = tplg_elem_lookup(&tplg->pdata_list,
ref->id, SND_TPLG_TYPE_DATA, elem->index);
if (!ref_elem) {
- SNDERR("error: cannot find data '%s' referenced by"
- " element '%s'\n", ref->id, elem->id);
+ SNDERR("cannot find data '%s' referenced by"
+ " element '%s'", ref->id, elem->id);
return -EINVAL;
}
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 1eaa24bd..5a5dd14f 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -122,7 +122,7 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
return -EINVAL;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound type expected for %s", id);
+ SNDERR("compound type expected for %s", id);
return -EINVAL;
}
@@ -131,7 +131,7 @@ int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
n = snd_config_iterator_entry(i);
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound type expected for %s, is %d",
+ SNDERR("compound type expected for %s, is %d",
id, snd_config_get_type(cfg));
return -EINVAL;
}
@@ -155,7 +155,7 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
int err;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("error: compound type expected at top level");
+ SNDERR("compound type expected at top level");
return -EINVAL;
}
@@ -180,7 +180,7 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)
}
if (parser == NULL) {
- SNDERR("error: unknown section %s\n", id);
+ SNDERR("unknown section %s", id);
continue;
}
@@ -202,7 +202,7 @@ static int tplg_load_config(snd_tplg_t *tplg, snd_input_t *in)
ret = snd_config_load(top, in);
if (ret < 0) {
- SNDERR("error: could not load configuration");
+ SNDERR("could not load configuration");
snd_config_delete(top);
return ret;
}
@@ -210,7 +210,7 @@ static int tplg_load_config(snd_tplg_t *tplg, snd_input_t *in)
ret = tplg_parse_config(tplg, top);
snd_config_delete(top);
if (ret < 0) {
- SNDERR("error: failed to parse topology");
+ SNDERR("failed to parse topology");
return ret;
}
@@ -267,7 +267,7 @@ int snd_tplg_load(snd_tplg_t *tplg, const char *buf, size_t size)
err = snd_input_buffer_open(&in, buf, size);
if (err < 0) {
- SNDERR("error: could not create input buffer");
+ SNDERR("could not create input buffer");
return err;
}
@@ -282,13 +282,13 @@ static int tplg_build(snd_tplg_t *tplg)
err = tplg_build_integ(tplg);
if (err < 0) {
- SNDERR("error: failed to check topology integrity\n");
+ SNDERR("failed to check topology integrity");
return err;
}
err = tplg_write_data(tplg);
if (err < 0) {
- SNDERR("error: failed to write data %d\n", err);
+ SNDERR("failed to write data %d", err);
return err;
}
return 0;
@@ -304,15 +304,14 @@ int snd_tplg_build_file(snd_tplg_t *tplg,
fp = fopen(infile, "r");
if (fp == NULL) {
- SNDERR("error: could not open configuration file %s",
- infile);
+ SNDERR("could not open configuration file %s", infile);
return -errno;
}
err = snd_input_stdio_attach(&in, fp, 1);
if (err < 0) {
fclose(fp);
- SNDERR("error: could not attach stdio %s", infile);
+ SNDERR("could not attach stdio %s", infile);
return err;
}
@@ -346,7 +345,7 @@ int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
case SND_TPLG_TYPE_CC:
return tplg_add_link_object(tplg, t);
default:
- SNDERR("error: invalid object type %d\n", t->type);
+ SNDERR("invalid object type %d", t->type);
return -EINVAL;
};
}
@@ -362,18 +361,18 @@ int snd_tplg_build(snd_tplg_t *tplg, const char *outfile)
fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd < 0) {
- SNDERR("error: failed to open %s err %d\n", outfile, -errno);
+ SNDERR("failed to open %s err %d", outfile, -errno);
return -errno;
}
r = write(fd, tplg->bin, tplg->bin_size);
close(fd);
if (r < 0) {
err = -errno;
- SNDERR("error: write error: %s\n", strerror(errno));
+ SNDERR("write error: %s", strerror(errno));
return err;
}
if ((size_t)r != tplg->bin_size) {
- SNDERR("error: partial write (%zd != %zd)\n", r, tplg->bin_size);
+ SNDERR("partial write (%zd != %zd)", r, tplg->bin_size);
return -EIO;
}
return 0;
@@ -437,7 +436,7 @@ snd_tplg_t *snd_tplg_create(int flags)
snd_tplg_t *tplg;
if (!is_little_endian()) {
- SNDERR("error: cannot support big-endian machines\n");
+ SNDERR("cannot support big-endian machines");
return NULL;
}
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index d09fbe42..bc307081 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -116,8 +116,8 @@ static int build_pcm(snd_tplg_t *tplg, struct tplg_elem *elem)
return err;
}
if (!ref->elem) {
- SNDERR("error: cannot find '%s' referenced by"
- " PCM '%s'\n", ref->id, elem->id);
+ SNDERR("cannot find '%s' referenced by"
+ " PCM '%s'", ref->id, elem->id);
return -EINVAL;
}
}
@@ -137,7 +137,7 @@ int tplg_build_pcms(snd_tplg_t *tplg, unsigned int type)
elem = list_entry(pos, struct tplg_elem, list);
if (elem->type != type) {
- SNDERR("error: invalid elem '%s'\n", elem->id);
+ SNDERR("invalid elem '%s'", elem->id);
return -EINVAL;
}
@@ -196,7 +196,7 @@ int tplg_build_dais(snd_tplg_t *tplg, unsigned int type)
elem = list_entry(pos, struct tplg_elem, list);
if (elem->type != type) {
- SNDERR("error: invalid elem '%s'\n", elem->id);
+ SNDERR("invalid elem '%s'", elem->id);
return -EINVAL;
}
@@ -251,8 +251,8 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem)
ref->elem = tplg_elem_lookup(&tplg->hw_cfg_list,
ref->id, SND_TPLG_TYPE_HW_CONFIG, elem->index);
if (!ref->elem) {
- SNDERR("error: cannot find HW config '%s'"
- " referenced by link '%s'\n",
+ SNDERR("cannot find HW config '%s'"
+ " referenced by link '%s'",
ref->id, elem->id);
return -EINVAL;
}
@@ -320,7 +320,7 @@ static int split_format(struct snd_soc_tplg_stream_caps *caps, char *str)
while ((s != NULL) && (i < SND_SOC_TPLG_MAX_FORMATS)) {
format = snd_pcm_format_value(s);
if (format == SND_PCM_FORMAT_UNKNOWN) {
- SNDERR("error: unsupported stream format %s\n", s);
+ SNDERR("unsupported stream format %s", s);
return -EINVAL;
}
@@ -363,7 +363,7 @@ static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str)
rate = get_rate_value(s);
if (rate == SND_PCM_RATE_UNKNOWN) {
- SNDERR("error: unsupported stream rate %s\n", s);
+ SNDERR("unsupported stream rate %s", s);
return -EINVAL;
}
@@ -758,7 +758,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
if (strcmp(id, "id") == 0) {
if (tplg_get_unsigned(n, &pcm->dai_id, 0)) {
- SNDERR("error: invalid fe dai ID\n");
+ SNDERR("invalid fe dai ID");
return -EINVAL;
}
@@ -1379,7 +1379,7 @@ static int get_audio_hw_format(const char *val)
if (strcasecmp(audio_hw_formats[i].name, val) == 0)
return audio_hw_formats[i].type;
- SNDERR("error: invalid audio HW format %s\n", val);
+ SNDERR("invalid audio HW format %s", val);
return -EINVAL;
}
@@ -1452,8 +1452,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
/* For backwards capability,
* "master" == "codec is slave"
*/
- SNDERR("warning: deprecated bclk value '%s'\n",
- val);
+ SNDERR("deprecated bclk value '%s'", val);
hw_cfg->bclk_master = SND_SOC_TPLG_BCLK_CS;
} else if (!strcmp(val, "codec_slave")) {
@@ -1490,8 +1489,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
/* For backwards capability,
* "master" == "codec is slave"
*/
- SNDERR("warning: deprecated fsync value '%s'\n",
- val);
+ SNDERR("deprecated fsync value '%s'", val);
hw_cfg->fsync_master = SND_SOC_TPLG_FSYNC_CS;
} else if (!strcmp(val, "codec_slave")) {
@@ -1535,8 +1533,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
/* For backwards capability,
* "master" == "for codec, mclk is input"
*/
- SNDERR("warning: deprecated mclk value '%s'\n",
- val);
+ SNDERR("deprecated mclk value '%s'", val);
hw_cfg->mclk_direction = SND_SOC_TPLG_MCLK_CI;
} else if (!strcmp(val, "codec_mclk_in")) {
diff --git a/src/topology/text.c b/src/topology/text.c
index e9386e7d..6dbf2230 100644
--- a/src/topology/text.c
+++ b/src/topology/text.c
@@ -38,7 +38,7 @@ static int parse_text_values(snd_config_t *cfg, struct tplg_elem *elem)
n = snd_config_iterator_entry(i);
if (j == SND_SOC_TPLG_NUM_TEXTS) {
- tplg_dbg("error: text string number exceeds %d\n", j);
+ tplg_dbg("text string number exceeds %d\n", j);
return -ENOMEM;
}
--
2.24.1
From 712fbacf160f899582a9adc3f30f297211b063bb Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 27 Dec 2019 19:32:03 +0100
Subject: [PATCH 47/69] topology: dapm - fix the SNDERR() - Undefined
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/dapm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index f61fe071..88bddca3 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -230,7 +230,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
SND_TPLG_TYPE_MIXER, elem->index) &&
!tplg_elem_lookup(&tplg->enum_list, route->control,
SND_TPLG_TYPE_ENUM, elem->index)) {
- SNDERR("Undefined mixer/enum control '%s'",
+ SNDERR("undefined mixer/enum control '%s'",
route->control);
}
}
@@ -243,7 +243,7 @@ int tplg_build_routes(snd_tplg_t *tplg)
}
if (!tplg_elem_lookup(&tplg->widget_list, route->source,
SND_TPLG_TYPE_DAPM_WIDGET, SND_TPLG_INDEX_ALL)) {
- SNDERR("Undefined source widget/stream '%s'",
+ SNDERR("undefined source widget/stream '%s'",
route->source);
}
--
2.24.1
From 07d779143bfd24448034cd55945b46c46407247c Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 28 Dec 2019 10:18:34 +0100
Subject: [PATCH 48/69] topology: fix the unitialized tuples
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/data.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/topology/data.c b/src/topology/data.c
index f00ed301..4e43fcc9 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -601,6 +601,7 @@ static int copy_tuples(struct tplg_elem *elem,
elem->data = priv;
array = (struct snd_soc_tplg_vendor_array *)(priv->data + off);
+ memset(array, 0, set_size);
array->size = set_size;
array->type = tuple_set->type;
array->num_elems = tuple_set->num_tuples;
--
2.24.1
From 2947d83c1322bcdb31c1da180acb0f779a63dcdd Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 28 Dec 2019 21:44:03 +0100
Subject: [PATCH 49/69] topology: implement shorter hexa uuid 00:00 parser
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/data.c | 37 +++++++++++++++++++++++++++++++------
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/src/topology/data.c b/src/topology/data.c
index 4e43fcc9..1ddd3c50 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -22,8 +22,8 @@
#include <ctype.h>
#define UUID_FORMAT "\
-0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, \
-0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x"
+%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:\
+%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
/* Get private data buffer of an element */
struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem)
@@ -316,7 +316,6 @@ format2:
values++;
s += 2;
}
- s++;
}
s++;
@@ -341,6 +340,32 @@ static int get_uuid(const char *str, unsigned char *uuid_le)
if (tmp == NULL)
return -ENOMEM;
+ if (strchr(tmp, ':') == NULL)
+ goto data2;
+
+ s = strtok(tmp, ":");
+ while (s != NULL) {
+ errno = 0;
+ val = strtoul(s, NULL, 16);
+ if ((errno == ERANGE && val == ULONG_MAX)
+ || (errno != 0 && val == 0)
+ || (val > UCHAR_MAX)) {
+ SNDERR("invalid value for uuid");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ *(uuid_le + values) = (unsigned char)val;
+
+ values++;
+ if (values >= 16)
+ break;
+
+ s = strtok(NULL, ":");
+ }
+ goto out;
+
+data2:
s = strtok(tmp, ",");
while (s != NULL) {
@@ -354,7 +379,7 @@ static int get_uuid(const char *str, unsigned char *uuid_le)
goto out;
}
- *(uuid_le + values) = (unsigned char)val;
+ *(uuid_le + values) = (unsigned char)val;
values++;
if (values >= 16)
@@ -413,7 +438,7 @@ static int copy_data_hex(char *data, int off, const char *str, int width)
return -ENOMEM;
p += off;
- s = strtok(tmp, ",");
+ s = strtok(tmp, ",:");
while (s != NULL) {
ret = write_hex(p, s, width);
@@ -422,7 +447,7 @@ static int copy_data_hex(char *data, int off, const char *str, int width)
return ret;
}
- s = strtok(NULL, ",");
+ s = strtok(NULL, ",:");
p += width;
}
--
2.24.1
From 1482d1f254fe42d83d904e52c911df8693b62653 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 29 Dec 2019 20:05:14 +0100
Subject: [PATCH 50/69] topology: fix the TPLG_DEBUG compilation
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/channel.c | 2 +-
src/topology/data.c | 5 ++++-
src/topology/pcm.c | 2 +-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/topology/channel.c b/src/topology/channel.c
index 110775a8..390c3f16 100644
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -129,7 +129,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
else if (strcmp(id, "shift") == 0)
channel->shift = value;
- tplg_dbg("\t\t%s = %s\n", id, value);
+ tplg_dbg("\t\t%s = %d\n", id, value);
}
tplg->channel_idx++;
diff --git a/src/topology/data.c b/src/topology/data.c
index 1ddd3c50..7b4bdccd 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -230,9 +230,11 @@ err:
return ret;
}
-static void dump_priv_data(struct tplg_elem *elem)
+static void dump_priv_data(struct tplg_elem *elem ATTRIBUTE_UNUSED)
{
+#ifdef TPLG_DEBUG
struct snd_soc_tplg_private *priv = elem->data;
+ unsigned char *p = (unsigned char *)priv->data;
unsigned int i;
tplg_dbg(" elem size = %d, priv data size = %d\n",
@@ -246,6 +248,7 @@ static void dump_priv_data(struct tplg_elem *elem)
}
tplg_dbg("\n\n");
+#endif
}
static inline int check_nibble(unsigned char c)
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index bc307081..8e5afbe6 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -881,7 +881,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
pcm->compress = ival;
- tplg_dbg("\t%s: %s\n", id, val);
+ tplg_dbg("\t%s: %d\n", id, ival);
continue;
}
--
2.24.1
From c765615bce7903a0f3e3d5e7826483708398c184 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 31 Dec 2019 15:27:58 +0100
Subject: [PATCH 51/69] topology: fix the ops parser (accept integer/hexa
values)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/ops.c | 36 +++++++++++++++++++++++++-----------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/src/topology/ops.c b/src/topology/ops.c
index ad72ef1b..2885c781 100644
--- a/src/topology/ops.c
+++ b/src/topology/ops.c
@@ -67,6 +67,7 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
snd_config_t *n;
struct snd_soc_tplg_ctl_hdr *hdr = private;
const char *id, *value;
+ int ival;
tplg_dbg("\tOps\n");
hdr->size = sizeof(*hdr);
@@ -80,17 +81,23 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
continue;
/* get value - try strings then ints */
- if (snd_config_get_string(n, &value) < 0)
- continue;
+ if (snd_config_get_type(n) == SND_CONFIG_TYPE_STRING) {
+ if (snd_config_get_string(n, &value) < 0)
+ continue;
+ ival = lookup_ops(value);
+ } else {
+ if (tplg_get_integer(n, &ival, 0))
+ continue;
+ }
if (strcmp(id, "info") == 0)
- hdr->ops.info = lookup_ops(value);
+ hdr->ops.info = ival;
else if (strcmp(id, "put") == 0)
- hdr->ops.put = lookup_ops(value);
+ hdr->ops.put = ival;
else if (strcmp(id, "get") == 0)
- hdr->ops.get = lookup_ops(value);
+ hdr->ops.get = ival;
- tplg_dbg("\t\t%s = %s\n", id, value);
+ tplg_dbg("\t\t%s = %d\n", id, ival);
}
return 0;
@@ -146,6 +153,7 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_t *n;
struct snd_soc_tplg_bytes_control *be = private;
const char *id, *value;
+ int ival;
tplg_dbg("\tExt Ops\n");
@@ -158,15 +166,21 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
continue;
/* get value - try strings then ints */
- if (snd_config_get_string(n, &value) < 0)
- continue;
+ if (snd_config_get_type(n) == SND_CONFIG_TYPE_STRING) {
+ if (snd_config_get_string(n, &value) < 0)
+ continue;
+ ival = lookup_ops(value);
+ } else {
+ if (tplg_get_integer(n, &ival, 0))
+ continue;
+ }
if (strcmp(id, "info") == 0)
- be->ext_ops.info = lookup_ops(value);
+ be->ext_ops.info = ival;
else if (strcmp(id, "put") == 0)
- be->ext_ops.put = lookup_ops(value);
+ be->ext_ops.put = ival;
else if (strcmp(id, "get") == 0)
- be->ext_ops.get = lookup_ops(value);
+ be->ext_ops.get = ival;
tplg_dbg("\t\t%s = %s\n", id, value);
}
--
2.24.1
From 0ba4d6d9c0ae4576f35724d2a5735990f09ceeb0 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 1 Jan 2020 19:10:20 +0100
Subject: [PATCH 52/69] topology: fix the wrong memory access (object realloc)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/pcm.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 8e5afbe6..bd728959 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -252,8 +252,8 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem)
ref->id, SND_TPLG_TYPE_HW_CONFIG, elem->index);
if (!ref->elem) {
SNDERR("cannot find HW config '%s'"
- " referenced by link '%s'",
- ref->id, elem->id);
+ " referenced by link '%s'",
+ ref->id, elem->id);
return -EINVAL;
}
@@ -267,6 +267,7 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem)
err = tplg_copy_data(tplg, elem, ref);
if (err < 0)
return err;
+ link = elem->link; /* realloc */
break;
default:
--
2.24.1
From b6c9afb4f59bb678dc834028680d579f47dc273b Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sun, 15 Dec 2019 15:24:57 +0100
Subject: [PATCH 53/69] topology: implement snd_tplg_decode
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
include/topology.h | 14 +-
src/topology/Makefile.am | 3 +-
src/topology/ctl.c | 450 +++++++++++++++++++++++++++++++++-----
src/topology/dapm.c | 253 +++++++++++++++++++--
src/topology/data.c | 440 ++++++++++++++++++++++++++++++++++++-
src/topology/decoder.c | 136 ++++++++++++
src/topology/elem.c | 80 +++++++
src/topology/parser.c | 20 +-
src/topology/pcm.c | 396 ++++++++++++++++++++++++++++-----
src/topology/save.c | 3 +
src/topology/tplg_local.h | 71 +++++-
11 files changed, 1727 insertions(+), 139 deletions(-)
create mode 100644 src/topology/decoder.c
diff --git a/include/topology.h b/include/topology.h
index 37bced1a..1f52e66e 100644
--- a/include/topology.h
+++ b/include/topology.h
@@ -885,7 +885,10 @@ struct snd_tplg_ctl_template {
const char *name; /*!< Control name */
int access; /*!< Control access */
struct snd_tplg_io_ops_template ops; /*!< operations */
- struct snd_tplg_tlv_template *tlv; /*!< non NULL means we have TLV data */
+ union {
+ struct snd_tplg_tlv_template *tlv; /*!< non NULL means we have TLV data */
+ struct snd_tplg_tlv_dbscale_template *tlv_scale; /*!< scale TLV data */
+ };
};
/** \struct snd_tplg_mixer_template
@@ -1155,6 +1158,15 @@ int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version);
*/
int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags);
+/**
+ * \brief Decode the binary topology contents.
+ * \param tplg Topology instance.
+ * \param bin Binary topology input buffer.
+ * \param size Binary topology input buffer size.
+ * \return Zero on success, otherwise a negative error code
+ */
+int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags);
+
/* \} */
#ifdef __cplusplus
diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am
index a850ec4c..12d1d445 100644
--- a/src/topology/Makefile.am
+++ b/src/topology/Makefile.am
@@ -28,7 +28,8 @@ libatopology_la_SOURCES =\
channel.c \
ops.c \
elem.c \
- save.c
+ save.c \
+ decoder.c
noinst_HEADERS = tplg_local.h
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 03874b27..24d437aa 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -621,8 +621,9 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
tplg->channel_idx = 0;
/* set channel reg to default state */
- for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++)
+ for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++) {
ec->channel[j].reg = -1;
+ }
tplg_dbg(" Control Enum: %s\n", elem->id);
@@ -896,9 +897,14 @@ int tplg_save_control_mixer(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
return err;
}
-static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
- struct snd_tplg_ctl_template *t)
+static int init_ctl_hdr(snd_tplg_t *tplg,
+ struct tplg_elem *parent,
+ struct snd_soc_tplg_ctl_hdr *hdr,
+ struct snd_tplg_ctl_template *t)
{
+ struct tplg_elem *elem;
+ int err;
+
hdr->size = sizeof(struct snd_soc_tplg_ctl_hdr);
hdr->type = t->type;
@@ -924,7 +930,7 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
&& !(hdr->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
struct snd_tplg_tlv_template *tlvt = t->tlv;
- struct snd_soc_tplg_ctl_tlv *tlv = &hdr->tlv;
+ struct snd_soc_tplg_ctl_tlv *tlv;
struct snd_tplg_tlv_dbscale_template *scalet;
struct snd_soc_tplg_tlv_dbscale *scale;
@@ -933,6 +939,17 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
return -EINVAL;
}
+ elem = tplg_elem_new_common(tplg, NULL, parent->id,
+ SND_TPLG_TYPE_TLV);
+ if (!elem)
+ return -ENOMEM;
+
+ tlv = elem->tlv;
+
+ err = tplg_ref_add(parent, SND_TPLG_TYPE_TLV, parent->id);
+ if (err < 0)
+ return err;
+
tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
tlv->type = tlvt->type;
@@ -957,10 +974,10 @@ static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
}
int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
- struct tplg_elem **e)
+ struct tplg_elem **e)
{
- struct snd_soc_tplg_private *priv = mixer->priv;
struct snd_soc_tplg_mixer_control *mc;
+ struct snd_soc_tplg_private *priv;
struct tplg_elem *elem;
int ret, i, num_channels;
@@ -979,7 +996,7 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
/* init new mixer */
mc = elem->mixer_ctrl;
mc->size = elem->size;
- ret = init_ctl_hdr(&mc->hdr, &mixer->hdr);
+ ret = init_ctl_hdr(tplg, elem, &mc->hdr, &mixer->hdr);
if (ret < 0) {
tplg_elem_free(elem);
return ret;
@@ -1000,25 +1017,20 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
for (i = 0; i < num_channels; i++) {
struct snd_tplg_channel_elem *channel = &mixer->map->channel[i];
- mc->channel[i].size = channel->size;
+ mc->channel[i].size = sizeof(mc->channel[0]);
mc->channel[i].reg = channel->reg;
mc->channel[i].shift = channel->shift;
mc->channel[i].id = channel->id;
}
/* priv data */
- if (priv) {
- mc = realloc(mc, elem->size + priv->size);
- if (!mc) {
- tplg_elem_free(elem);
- return -ENOMEM;
- }
-
- elem->mixer_ctrl = mc;
- elem->size += priv->size;
- mc->priv.size = priv->size;
- memcpy(mc->priv.data, priv->data, priv->size);
- }
+ priv = mixer->priv;
+ if (priv && priv->size > 0) {
+ ret = tplg_add_data(tplg, elem, priv,
+ sizeof(*priv) + priv->size);
+ if (ret < 0)
+ return ret;
+ }
if (e)
*e = elem;
@@ -1026,11 +1038,12 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
}
int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
- struct tplg_elem **e)
+ struct tplg_elem **e)
{
struct snd_soc_tplg_enum_control *ec;
+ struct snd_soc_tplg_private *priv;
struct tplg_elem *elem;
- int ret, i, num_items;
+ int ret, i, num_items, num_channels;
tplg_dbg(" Control Enum: %s\n", enum_ctl->hdr.name);
@@ -1046,7 +1059,7 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
ec = elem->enum_ctrl;
ec->size = elem->size;
- ret = init_ctl_hdr(&ec->hdr, &enum_ctl->hdr);
+ ret = init_ctl_hdr(tplg, elem, &ec->hdr, &enum_ctl->hdr);
if (ret < 0) {
tplg_elem_free(elem);
return ret;
@@ -1058,6 +1071,22 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
ec->mask = enum_ctl->mask;
ec->count = enum_ctl->items;
+ /* set channel reg to default state */
+ for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++)
+ ec->channel[i].reg = -1;
+
+ num_channels = enum_ctl->map ? enum_ctl->map->num_channels : 0;
+ ec->num_channels = num_channels;
+
+ for (i = 0; i < num_channels; i++) {
+ struct snd_tplg_channel_elem *channel = &enum_ctl->map->channel[i];
+
+ ec->channel[i].size = sizeof(ec->channel[0]);
+ ec->channel[i].reg = channel->reg;
+ ec->channel[i].shift = channel->shift;
+ ec->channel[i].id = channel->id;
+ }
+
if (enum_ctl->texts != NULL) {
for (i = 0; i < num_items; i++) {
if (enum_ctl->texts[i] != NULL)
@@ -1077,21 +1106,13 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
}
}
- if (enum_ctl->priv != NULL) {
- ec = realloc(ec,
- elem->size + enum_ctl->priv->size);
- if (!ec) {
- tplg_elem_free(elem);
- return -ENOMEM;
- }
-
- elem->enum_ctrl = ec;
- elem->size += enum_ctl->priv->size;
-
- memcpy(ec->priv.data, enum_ctl->priv->data,
- enum_ctl->priv->size);
-
- ec->priv.size = enum_ctl->priv->size;
+ /* priv data */
+ priv = enum_ctl->priv;
+ if (priv && priv->size > 0) {
+ ret = tplg_add_data(tplg, elem, priv,
+ sizeof(*priv) + priv->size);
+ if (ret < 0)
+ return ret;
}
if (e)
@@ -1100,9 +1121,10 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
}
int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
- struct tplg_elem **e)
+ struct tplg_elem **e)
{
struct snd_soc_tplg_bytes_control *be;
+ struct snd_soc_tplg_private *priv;
struct tplg_elem *elem;
int ret;
@@ -1120,7 +1142,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
be = elem->bytes_ext;
be->size = elem->size;
- ret = init_ctl_hdr(&be->hdr, &bytes_ctl->hdr);
+ ret = init_ctl_hdr(tplg, elem, &be->hdr, &bytes_ctl->hdr);
if (ret < 0) {
tplg_elem_free(elem);
return ret;
@@ -1133,20 +1155,13 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
be->ext_ops.put = bytes_ctl->ext_ops.put;
be->ext_ops.get = bytes_ctl->ext_ops.get;
- if (bytes_ctl->priv != NULL) {
- be = realloc(be,
- elem->size + bytes_ctl->priv->size);
- if (!be) {
- tplg_elem_free(elem);
- return -ENOMEM;
- }
- elem->bytes_ext = be;
- elem->size += bytes_ctl->priv->size;
-
- memcpy(be->priv.data, bytes_ctl->priv->data,
- bytes_ctl->priv->size);
-
- be->priv.size = bytes_ctl->priv->size;
+ /* priv data */
+ priv = bytes_ctl->priv;
+ if (priv && priv->size > 0) {
+ ret = tplg_add_data(tplg, elem, priv,
+ sizeof(*priv) + priv->size);
+ if (ret < 0)
+ return ret;
}
/* check on TLV bytes control */
@@ -1184,3 +1199,330 @@ int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
{
return tplg_add_bytes(tplg, t->bytes_ctl, NULL);
}
+
+int tplg_decode_control_mixer1(snd_tplg_t *tplg,
+ struct list_head *heap,
+ struct snd_tplg_mixer_template *mt,
+ size_t pos,
+ void *bin, size_t size)
+{
+ struct snd_soc_tplg_mixer_control *mc = bin;
+ struct snd_tplg_channel_map_template *map;
+ struct snd_tplg_tlv_dbscale_template *db;
+ int i;
+
+ if (size < sizeof(*mc)) {
+ SNDERR("mixer: small size %d", size);
+ return -EINVAL;
+ }
+
+ tplg_dv(tplg, pos, "mixer: size %d TLV size %d private size %d",
+ mc->size, mc->hdr.tlv.size, mc->priv.size);
+ if (size != mc->size + mc->priv.size) {
+ SNDERR("mixer: unexpected element size %d", size);
+ return -EINVAL;
+ }
+
+ memset(mt, 0, sizeof(*mt));
+ mt->hdr.type = mc->hdr.type;
+ mt->hdr.name = mc->hdr.name;
+ mt->hdr.access = mc->hdr.access;
+ mt->hdr.ops.get = mc->hdr.ops.get;
+ mt->hdr.ops.put = mc->hdr.ops.put;
+ mt->hdr.ops.info = mc->hdr.ops.info;
+ mt->min = mc->min;
+ mt->max = mc->max;
+ mt->platform_max = mc->platform_max;
+ tplg_dv(tplg, pos, "mixer: name '%s' access 0x%x",
+ mt->hdr.name, mt->hdr.access);
+ if (mc->num_channels > 0) {
+ map = tplg_calloc(heap, sizeof(*map));
+ map->num_channels = mc->num_channels;
+ for (i = 0; i < map->num_channels; i++) {
+ map->channel[i].reg = mc->channel[i].reg;
+ map->channel[i].shift = mc->channel[i].shift;
+ map->channel[i].id = mc->channel[i].id;
+ }
+ mt->map = map;
+ }
+ if (mc->hdr.tlv.size == 0) {
+ /* nothing */
+ } else if (mc->hdr.tlv.size == sizeof(struct snd_soc_tplg_ctl_tlv)) {
+ if (mc->hdr.tlv.type != SNDRV_CTL_TLVT_DB_SCALE) {
+ SNDERR("mixer: unknown TLV type %d",
+ mc->hdr.tlv.type);
+ return -EINVAL;
+ }
+ db = tplg_calloc(heap, sizeof(*db));
+ if (db == NULL)
+ return -ENOMEM;
+ mt->hdr.tlv_scale = db;
+ db->hdr.type = mc->hdr.tlv.type;
+ db->min = mc->hdr.tlv.scale.min;
+ db->step = mc->hdr.tlv.scale.step;
+ db->mute = mc->hdr.tlv.scale.mute;
+ tplg_dv(tplg, pos, "mixer: dB scale TLV: min %d step %d mute %d",
+ db->min, db->step, db->mute);
+ } else {
+ SNDERR("mixer: wrong TLV size %d", mc->hdr.tlv.size);
+ return -EINVAL;
+ }
+
+ mt->priv = &mc->priv;
+ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_mixer_control, priv),
+ "mixer: private start");
+ return 0;
+}
+
+int tplg_decode_control_mixer(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ struct list_head heap;
+ snd_tplg_obj_template_t t;
+ struct snd_tplg_mixer_template mt;
+ struct snd_soc_tplg_mixer_control *mc;
+ size_t size2;
+ int err;
+
+ err = tplg_decode_template(tplg, pos, hdr, &t);
+ if (err < 0)
+ return err;
+
+next:
+ if (size < sizeof(*mc)) {
+ SNDERR("mixer: small size %d", size);
+ return -EINVAL;
+ }
+ INIT_LIST_HEAD(&heap);
+ mc = bin;
+ size2 = mc->size + mc->priv.size;
+ if (size2 > size) {
+ SNDERR("mixer: wrong element size (%d, priv %d)",
+ mc->size, mc->priv.size);
+ return -EINVAL;
+ }
+
+ err = tplg_decode_control_mixer1(tplg, &heap, &mt, pos, bin, size2);
+ if (err >= 0) {
+ t.mixer = &mt;
+ err = snd_tplg_add_object(tplg, &t);
+ }
+ tplg_free(&heap);
+ if (err < 0)
+ return err;
+
+ bin += size2;
+ size -= size2;
+ pos += size2;
+
+ if (size > 0)
+ goto next;
+
+ return 0;
+}
+
+int tplg_decode_control_enum1(snd_tplg_t *tplg,
+ struct list_head *heap,
+ struct snd_tplg_enum_template *et,
+ size_t pos,
+ void *bin, size_t size)
+{
+ struct snd_soc_tplg_enum_control *ec = bin;
+ struct snd_tplg_channel_map_template cmt;
+ int i;
+
+ if (size < sizeof(*ec)) {
+ SNDERR("enum: small size %d", size);
+ return -EINVAL;
+ }
+
+ tplg_dv(tplg, pos, "enum: size %d private size %d",
+ ec->size, ec->priv.size);
+ if (size != ec->size + ec->priv.size) {
+ SNDERR("enum: unexpected element size %d", size);
+ return -EINVAL;
+ }
+ if (ec->num_channels > SND_TPLG_MAX_CHAN ||
+ ec->num_channels > SND_SOC_TPLG_MAX_CHAN) {
+ SNDERR("enum: unexpected channel count %d", ec->num_channels);
+ return -EINVAL;
+ }
+ if (ec->items > SND_SOC_TPLG_NUM_TEXTS) {
+ SNDERR("enum: unexpected texts count %d", ec->items);
+ return -EINVAL;
+ }
+
+ memset(et, 0, sizeof(*et));
+ et->hdr.type = ec->hdr.type;
+ et->hdr.name = ec->hdr.name;
+ et->hdr.access = ec->hdr.access;
+ et->hdr.ops.get = ec->hdr.ops.get;
+ et->hdr.ops.put = ec->hdr.ops.put;
+ et->hdr.ops.info = ec->hdr.ops.info;
+ et->mask = ec->mask;
+
+ if (ec->items > 0) {
+ et->items = ec->items;
+ et->texts = tplg_calloc(heap, sizeof(char *) * ec->items);
+ if (!et->texts)
+ return -ENOMEM;
+ for (i = 0; ec->items; i++) {
+ unsigned int j = i * sizeof(int) * ENUM_VAL_SIZE;
+ et->texts[i] = ec->texts[i];
+ et->values[i] = (int *)&ec->values[j];
+ }
+ }
+
+ et->map = &cmt;
+ memset(&cmt, 0, sizeof(cmt));
+ cmt.num_channels = ec->num_channels;
+ for (i = 0; i < cmt.num_channels; i++) {
+ struct snd_tplg_channel_elem *channel = &cmt.channel[i];
+ tplg_dv(tplg, pos + ((void *)&ec->channel[i] - (void *)ec),
+ "enum: channel size %d", ec->channel[i].size);
+ channel->reg = ec->channel[i].reg;
+ channel->shift = ec->channel[i].shift;
+ channel->id = ec->channel[i].id;
+ }
+
+ et->priv = &ec->priv;
+ return 0;
+}
+
+int tplg_decode_control_enum(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ struct list_head heap;
+ snd_tplg_obj_template_t t;
+ struct snd_tplg_enum_template et;
+ struct snd_soc_tplg_enum_control *ec;
+ size_t size2;
+ int err;
+
+ err = tplg_decode_template(tplg, pos, hdr, &t);
+ if (err < 0)
+ return err;
+
+next:
+ if (size < sizeof(*ec)) {
+ SNDERR("enum: small size %d", size);
+ return -EINVAL;
+ }
+ INIT_LIST_HEAD(&heap);
+ ec = bin;
+ size2 = ec->size + ec->priv.size;
+ if (size2 > size) {
+ SNDERR("enum: wrong element size (%d, priv %d)",
+ ec->size, ec->priv.size);
+ return -EINVAL;
+ }
+
+ err = tplg_decode_control_enum1(tplg, &heap, &et, pos, bin, size);
+ if (err >= 0) {
+ t.enum_ctl = &et;
+ err = snd_tplg_add_object(tplg, &t);
+ }
+ tplg_free(&heap);
+ if (err < 0)
+ return err;
+
+ bin += size2;
+ size -= size2;
+ pos += size2;
+
+ if (size > 0)
+ goto next;
+
+ return 0;
+}
+
+int tplg_decode_control_bytes1(snd_tplg_t *tplg,
+ struct snd_tplg_bytes_template *bt,
+ size_t pos,
+ void *bin, size_t size)
+{
+ struct snd_soc_tplg_bytes_control *bc = bin;
+
+ if (size < sizeof(*bc)) {
+ SNDERR("bytes: small size %d", size);
+ return -EINVAL;
+ }
+
+ tplg_dv(tplg, pos, "control bytes: size %d private size %d",
+ bc->size, bc->priv.size);
+ if (size != bc->size + bc->priv.size) {
+ SNDERR("bytes: unexpected element size %d", size);
+ return -EINVAL;
+ }
+
+ memset(bt, 0, sizeof(*bt));
+ bt->hdr.type = bc->hdr.type;
+ bt->hdr.name = bc->hdr.name;
+ bt->hdr.access = bc->hdr.access;
+ bt->hdr.ops.get = bc->hdr.ops.get;
+ bt->hdr.ops.put = bc->hdr.ops.put;
+ bt->hdr.ops.info = bc->hdr.ops.info;
+ bt->max = bc->max;
+ bt->mask = bc->mask;
+ bt->base = bc->base;
+ bt->num_regs = bc->num_regs;
+ bt->ext_ops.get = bc->ext_ops.get;
+ bt->ext_ops.put = bc->ext_ops.put;
+ bt->ext_ops.info = bc->ext_ops.info;
+ tplg_dv(tplg, pos, "control bytes: name '%s' access 0x%x",
+ bt->hdr.name, bt->hdr.access);
+
+ bt->priv = &bc->priv;
+ return 0;
+}
+
+int tplg_decode_control_bytes(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ snd_tplg_obj_template_t t;
+ struct snd_tplg_bytes_template bt;
+ struct snd_soc_tplg_bytes_control *bc;
+ size_t size2;
+ int err;
+
+ err = tplg_decode_template(tplg, pos, hdr, &t);
+ if (err < 0)
+ return err;
+
+next:
+ if (size < sizeof(*bc)) {
+ SNDERR("bytes: small size %d", size);
+ return -EINVAL;
+ }
+ bc = bin;
+ size2 = bc->size + bc->priv.size;
+ if (size2 > size) {
+ SNDERR("bytes: wrong element size (%d, priv %d)",
+ bc->size, bc->priv.size);
+ return -EINVAL;
+ }
+
+ err = tplg_decode_control_bytes1(tplg, &bt, pos, bin, size);
+ if (err < 0)
+ return err;
+
+ t.bytes_ctl = &bt;
+ err = snd_tplg_add_object(tplg, &t);
+ if (err < 0)
+ return err;
+
+ bin += size2;
+ size -= size2;
+ pos += size2;
+
+ if (size > 0)
+ goto next;
+
+ return 0;
+}
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index 88bddca3..9fab2d92 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -420,19 +420,39 @@ int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, char **dst, const char *pf
struct snd_soc_tplg_dapm_graph_elem *route;
struct list_head *pos;
struct tplg_elem *elem;
- int err, first = 1, old_index = -1;
- unsigned block = -1, count = 0;
+ int err, first, old_index;
+ unsigned block, count;
+ const char *fmt;
+ old_index = -1;
+ block = 0;
+ count = 0;
list_for_each(pos, &tplg->route_list) {
elem = list_entry(pos, struct tplg_elem, list);
if (!elem->route || elem->type != SND_TPLG_TYPE_DAPM_GRAPH)
continue;
if (index >= 0 && elem->index != index)
continue;
+ if (old_index != elem->index) {
+ block++;
+ old_index = elem->index;
+ }
count++;
}
if (count == 0)
return 0;
+ if (block < 10) {
+ fmt = "\tset%u {\n";
+ } else if (block < 100) {
+ fmt = "\tset%02u {\n";
+ } else if (block < 1000) {
+ fmt = "\tset%03u {\n";
+ } else {
+ return -EINVAL;
+ }
+ old_index = -1;
+ block = -1;
+ first = 1;
err = tplg_save_printf(dst, pfx, "SectionGraph {\n");
list_for_each(pos, &tplg->route_list) {
elem = list_entry(pos, struct tplg_elem, list);
@@ -452,7 +472,7 @@ int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, char **dst, const char *pf
old_index = elem->index;
block++;
first = 1;
- err = tplg_save_printf(dst, pfx, "\tset%u {\n", block);
+ err = tplg_save_printf(dst, pfx, fmt, block);
if (err >= 0)
err = tplg_save_printf(dst, pfx, "\t\tindex %u\n",
elem->index);
@@ -771,20 +791,14 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
w->event_flags = wt->event_flags;
w->event_type = wt->event_type;
- if (wt->priv != NULL) {
- w = realloc(w,
- elem->size + wt->priv->size);
- if (!w) {
+ /* add private data */
+ if (wt->priv != NULL && wt->priv->size > 0) {
+ ret = tplg_add_data(tplg, elem, wt->priv,
+ sizeof(*wt->priv) + wt->priv->size);
+ if (ret < 0) {
tplg_elem_free(elem);
- return -ENOMEM;
+ return ret;
}
-
- elem->widget = w;
- elem->size += wt->priv->size;
-
- memcpy(w->priv.data, wt->priv->data,
- wt->priv->size);
- w->priv.size = wt->priv->size;
}
/* add controls to the widget's reference list */
@@ -836,3 +850,212 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
return 0;
}
+
+/* decode dapm widget from the binary input */
+int tplg_decode_dapm_widget(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ struct list_head heap;
+ struct snd_soc_tplg_dapm_widget *w;
+ snd_tplg_obj_template_t t;
+ struct snd_tplg_widget_template *wt;
+ struct snd_tplg_mixer_template *mt;
+ struct snd_tplg_enum_template *et;
+ struct snd_tplg_bytes_template *bt;
+ struct snd_soc_tplg_ctl_hdr *chdr;
+ struct snd_soc_tplg_mixer_control *mc;
+ struct snd_soc_tplg_enum_control *ec;
+ struct snd_soc_tplg_bytes_control *bc;
+ size_t size2;
+ unsigned int index;
+ int err;
+
+ err = tplg_decode_template(tplg, pos, hdr, &t);
+ if (err < 0)
+ return err;
+
+next:
+ INIT_LIST_HEAD(&heap);
+ w = bin;
+
+ if (size < sizeof(*w)) {
+ SNDERR("dapm widget: small size %d", size);
+ return -EINVAL;
+ }
+ if (sizeof(*w) != w->size) {
+ SNDERR("dapm widget: unknown element size %d (expected %zd)",
+ w->size, sizeof(*w));
+ return -EINVAL;
+ }
+ if (w->num_kcontrols > 16) {
+ SNDERR("dapm widget: too many kcontrols %d",
+ w->num_kcontrols);
+ return -EINVAL;
+ }
+
+ tplg_dv(tplg, pos, "dapm widget: size %d private size %d kcontrols %d",
+ w->size, w->priv.size, w->num_kcontrols);
+
+ wt = tplg_calloc(&heap, sizeof(*wt) + sizeof(void *) * w->num_kcontrols);
+ if (wt == NULL)
+ return -ENOMEM;
+ wt->id = w->id;
+ wt->name = w->name;
+ wt->sname = w->sname;
+ wt->reg = w->reg;
+ wt->shift = w->shift;
+ wt->mask = w->mask;
+ wt->subseq = w->subseq;
+ wt->invert = w->invert;
+ wt->ignore_suspend = w->ignore_suspend;
+ wt->event_flags = w->event_flags;
+ wt->event_type = w->event_type;
+
+ tplg_dv(tplg, pos, "dapm widget: name '%s' sname '%s'", wt->name, wt->sname);
+
+ if (sizeof(*w) + w->priv.size > size) {
+ SNDERR("dapm widget: wrong private data size %d",
+ w->priv.size);
+ return -EINVAL;
+ }
+
+ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_dapm_widget, priv),
+ "dapm widget: private start");
+
+ wt->priv = &w->priv;
+ bin += sizeof(*w) + w->priv.size;
+ size -= sizeof(*w) + w->priv.size;
+ pos += sizeof(*w) + w->priv.size;
+
+ for (index = 0; index < w->num_kcontrols; index++) {
+ chdr = bin;
+ switch (chdr->type) {
+ case SND_SOC_TPLG_TYPE_MIXER:
+ mt = tplg_calloc(&heap, sizeof(*mt));
+ if (mt == NULL) {
+ err = -ENOMEM;
+ goto retval;
+ }
+ wt->ctl[index] = (void *)mt;
+ wt->num_ctls++;
+ mc = bin;
+ size2 = mc->size + mc->priv.size;
+ tplg_dv(tplg, pos, "kcontrol mixer size %zd", size2);
+ if (size2 > size) {
+ SNDERR("dapm widget: small mixer size %d",
+ size2);
+ err = -EINVAL;
+ goto retval;
+ }
+ err = tplg_decode_control_mixer1(tplg, &heap, mt, pos,
+ bin, size2);
+ break;
+ case SND_SOC_TPLG_TYPE_ENUM:
+ et = tplg_calloc(&heap, sizeof(*mt));
+ if (et == NULL) {
+ err = -ENOMEM;
+ goto retval;
+ }
+ wt->ctl[index] = (void *)et;
+ wt->num_ctls++;
+ ec = bin;
+ size2 = ec->size + ec->priv.size;
+ tplg_dv(tplg, pos, "kcontrol enum size %zd", size2);
+ if (size2 > size) {
+ SNDERR("dapm widget: small enum size %d",
+ size2);
+ err = -EINVAL;
+ goto retval;
+ }
+ err = tplg_decode_control_enum1(tplg, &heap, et, pos,
+ bin, size2);
+ break;
+ case SND_SOC_TPLG_TYPE_BYTES:
+ bt = tplg_calloc(&heap, sizeof(*bt));
+ if (bt == NULL) {
+ err = -ENOMEM;
+ goto retval;
+ }
+ wt->ctl[index] = (void *)bt;
+ wt->num_ctls++;
+ bc = bin;
+ size2 = bc->size + bc->priv.size;
+ tplg_dv(tplg, pos, "kcontrol bytes size %zd", size2);
+ if (size2 > size) {
+ SNDERR("dapm widget: small bytes size %d",
+ size2);
+ err = -EINVAL;
+ goto retval;
+ }
+ err = tplg_decode_control_bytes1(tplg, bt, pos,
+ bin, size2);
+ break;
+ default:
+ SNDERR("dapm widget: wrong control type %d",
+ chdr->type);
+ err = -EINVAL;
+ goto retval;
+ }
+ if (err < 0)
+ goto retval;
+ bin += size2;
+ size -= size2;
+ pos += size2;
+ }
+
+ t.widget = wt;
+ err = snd_tplg_add_object(tplg, &t);
+ tplg_free(&heap);
+ if (err < 0)
+ return err;
+ if (size > 0)
+ goto next;
+ return 0;
+
+retval:
+ tplg_free(&heap);
+ return err;
+}
+
+/* decode dapm link from the binary input */
+int tplg_decode_dapm_graph(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ struct snd_soc_tplg_dapm_graph_elem *g;
+ snd_tplg_obj_template_t t;
+ struct snd_tplg_graph_template *gt;
+ struct snd_tplg_graph_elem *ge;
+ size_t asize;
+ int err;
+
+ err = tplg_decode_template(tplg, pos, hdr, &t);
+ if (err < 0)
+ return err;
+
+ asize = sizeof(*gt) + (size / sizeof(*g)) * sizeof(*ge);
+ gt = alloca(asize);
+ memset(gt, 0, asize);
+ for (ge = gt->elem; size > 0; ge++) {
+ g = bin;
+ if (size < sizeof(*g)) {
+ SNDERR("dapm graph: small size %d", size);
+ return -EINVAL;
+ }
+ ge->src = g->source;
+ ge->ctl = g->control;
+ ge->sink = g->sink;
+ gt->count++;
+ tplg_dv(tplg, pos, "dapm graph: src='%s' ctl='%s' sink='%s'",
+ ge->src, ge->ctl, ge->sink);
+ bin += sizeof(*g);
+ size -= sizeof(*g);
+ pos += sizeof(*g);
+ }
+
+ t.graph = gt;
+ return snd_tplg_add_object(tplg, &t);
+}
diff --git a/src/topology/data.c b/src/topology/data.c
index 7b4bdccd..64563920 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -566,7 +566,7 @@ static bool has_tuples(struct tplg_elem *elem)
}
/* get size of a tuple element from its type */
-static unsigned int get_tuple_size(int type)
+unsigned int tplg_get_tuple_size(int type)
{
switch (type) {
@@ -602,7 +602,7 @@ static int copy_tuples(struct tplg_elem *elem,
for (i = 0; i < tuples->num_sets ; i++) {
tuple_set = tuples->set[i];
set_size = sizeof(struct snd_soc_tplg_vendor_array)
- + get_tuple_size(tuple_set->type)
+ + tplg_get_tuple_size(tuple_set->type)
* tuple_set->num_tuples;
size += set_size;
if (size > TPLG_MAX_PRIV_SIZE) {
@@ -1250,6 +1250,9 @@ int tplg_save_manifest_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
continue;
count++;
}
+ if (count == 0)
+ return tplg_save_printf(dst, NULL,
+ "'%s'.comment 'empty'\n", elem->id);
if (count > 1) {
err = tplg_save_printf(dst, NULL, "'%s'.data [\n", elem->id);
if (err < 0)
@@ -1557,3 +1560,436 @@ int tplg_build_data(snd_tplg_t *tplg)
return 0;
}
+
+/* decode manifest data */
+int tplg_decode_manifest_data(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ struct snd_soc_tplg_manifest *m = bin;
+ struct tplg_elem *elem;
+ size_t off;
+
+ if (hdr->index != 0) {
+ SNDERR("manifest - wrong index %d", hdr->index);
+ return -EINVAL;
+ }
+
+ if (sizeof(*m) > size) {
+ SNDERR("manifest - wrong size %zd (minimal %zd)",
+ size, sizeof(*m));
+ return -EINVAL;
+ }
+
+ if (m->size != sizeof(*m)) {
+ SNDERR("manifest - wrong sructure size %d", m->size);
+ return -EINVAL;
+ }
+
+ off = offsetof(struct snd_soc_tplg_manifest, priv);
+ if (off + m->priv.size > size) {
+ SNDERR("manifest - wrong private size %d", m->priv.size);
+ return -EINVAL;
+ }
+
+ tplg->manifest = *m;
+
+ bin += off;
+ size -= off;
+ pos += off;
+
+ elem = tplg_elem_new_common(tplg, NULL, "manifest",
+ SND_TPLG_TYPE_MANIFEST);
+ if (!elem)
+ return -ENOMEM;
+
+ tplg_dv(tplg, pos, "manifest: private size %d", size);
+ return tplg_add_data(tplg, elem, bin, size);
+}
+
+int tplg_add_token(snd_tplg_t *tplg, struct tplg_elem *parent,
+ unsigned int token,
+ char str_ref[SNDRV_CTL_ELEM_ID_NAME_MAXLEN])
+{
+ struct tplg_elem *elem;
+ struct tplg_token *t;
+ struct tplg_vendor_tokens *tokens;
+ unsigned int i;
+ size_t size;
+
+ elem = tplg_elem_lookup(&tplg->token_list, parent->id,
+ SND_TPLG_TYPE_TOKEN, parent->index);
+ if (elem == NULL) {
+ elem = tplg_elem_new_common(tplg, NULL, parent->id,
+ SND_TPLG_TYPE_TOKEN);
+ if (!elem)
+ return -ENOMEM;
+ }
+
+ tokens = elem->tokens;
+ if (tokens) {
+ for (i = 0; i < tokens->num_tokens; i++) {
+ t = &tokens->token[i];
+ if (t->value == token)
+ goto found;
+ }
+ size = sizeof(*tokens) +
+ (tokens->num_tokens + 1) * sizeof(struct tplg_token);
+ tokens = realloc(tokens, size);
+ } else {
+ size = sizeof(*tokens) + 1 * sizeof(struct tplg_token);
+ tokens = calloc(1, size);
+ }
+
+ if (!tokens)
+ return -ENOMEM;
+
+ memset(&tokens->token[tokens->num_tokens], 0, sizeof(struct tplg_token));
+ elem->tokens = tokens;
+ t = &tokens->token[tokens->num_tokens];
+ tokens->num_tokens++;
+ snprintf(t->id, sizeof(t->id), "token%u", token);
+ t->value = token;
+found:
+ snd_strlcpy(str_ref, t->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ return 0;
+}
+
+static int tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos,
+ const void *bin, size_t size)
+{
+ const struct snd_soc_tplg_vendor_array *va;
+ unsigned int j;
+
+ va = bin;
+ if (size < sizeof(*va) || size < va->size) {
+ tplg_dv(tplg, pos, "tuple set verify: wrong size %d", size);
+ return -EINVAL;
+ }
+
+ switch (va->type) {
+ case SND_SOC_TPLG_TUPLE_TYPE_UUID:
+ case SND_SOC_TPLG_TUPLE_TYPE_STRING:
+ case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
+ case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
+ case SND_SOC_TPLG_TUPLE_TYPE_WORD:
+ case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
+ break;
+ default:
+ tplg_dv(tplg, pos, "tuple set verify: unknown array type %d", va->type);
+ return -EINVAL;
+ }
+
+ j = tplg_get_tuple_size(va->type) * va->num_elems;
+ if (j + sizeof(*va) != va->size) {
+ tplg_dv(tplg, pos, "tuple set verify: wrong vendor array size %d "
+ "(expected %d for %d count %d)",
+ va->size, j + sizeof(*va), va->type, va->num_elems);
+ return -EINVAL;
+ }
+
+ if (va->num_elems > 4096) {
+ tplg_dv(tplg, pos, "tuple set verify: tuples overflow %d", va->num_elems);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tplg_decode_tuple_set(snd_tplg_t *tplg,
+ size_t pos,
+ struct tplg_elem *parent,
+ struct tplg_tuple_set **_set,
+ const void *bin, size_t size)
+{
+ const struct snd_soc_tplg_vendor_array *va;
+ struct tplg_tuple_set *set;
+ struct tplg_tuple *tuple;
+ unsigned int j;
+ int err;
+
+ va = bin;
+ if (size < sizeof(*va) || size < va->size) {
+ SNDERR("tuples: wrong size %d", size);
+ return -EINVAL;
+ }
+
+ switch (va->type) {
+ case SND_SOC_TPLG_TUPLE_TYPE_UUID:
+ case SND_SOC_TPLG_TUPLE_TYPE_STRING:
+ case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
+ case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
+ case SND_SOC_TPLG_TUPLE_TYPE_WORD:
+ case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
+ break;
+ default:
+ SNDERR("tuples: unknown array type %d", va->type);
+ return -EINVAL;
+ }
+
+ j = tplg_get_tuple_size(va->type) * va->num_elems;
+ if (j + sizeof(*va) != va->size) {
+ SNDERR("tuples: wrong vendor array size %d "
+ "(expected %d for %d count %d)",
+ va->size, j + sizeof(*va), va->type, va->num_elems);
+ return -EINVAL;
+ }
+
+ if (va->num_elems > 4096) {
+ SNDERR("tuples: tuples overflow %d", va->num_elems);
+ return -EINVAL;
+ }
+
+ set = calloc(1, sizeof(*set) + va->num_elems * sizeof(struct tplg_tuple));
+ if (!set)
+ return -ENOMEM;
+
+ set->type = va->type;
+ set->num_tuples = va->num_elems;
+
+ tplg_dv(tplg, pos, "tuple set: type %d (%s) tuples %d size %d", set->type,
+ get_tuple_type_name(set->type), set->num_tuples, va->size);
+ for (j = 0; j < set->num_tuples; j++) {
+ tuple = &set->tuple[j];
+ switch (va->type) {
+ case SND_SOC_TPLG_TUPLE_TYPE_UUID:
+ err = tplg_add_token(tplg, parent, va->uuid[j].token,
+ tuple->token);
+ if (err < 0)
+ goto retval;
+ memcpy(tuple->uuid, va->uuid[j].uuid,
+ sizeof(va->uuid[j].uuid));
+ break;
+ case SND_SOC_TPLG_TUPLE_TYPE_STRING:
+ err = tplg_add_token(tplg, parent, va->string[j].token,
+ tuple->token);
+ if (err < 0)
+ goto retval;
+ snd_strlcpy(tuple->string, va->string[j].string,
+ sizeof(tuple->string));
+ break;
+ case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
+ case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
+ case SND_SOC_TPLG_TUPLE_TYPE_WORD:
+ case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
+ err = tplg_add_token(tplg, parent, va->value[j].token,
+ tuple->token);
+ if (err < 0)
+ goto retval;
+ tuple->value = va->value[j].value;
+ break;
+ }
+ }
+
+ *_set = set;
+ return 0;
+
+retval:
+ free(set);
+ return err;
+}
+
+/* verify tuples from the binary input */
+static int tplg_verify_tuples(snd_tplg_t *tplg, size_t pos,
+ const void *bin, size_t size)
+{
+ const struct snd_soc_tplg_vendor_array *va;
+ int err;
+
+ if (size < sizeof(*va)) {
+ tplg_dv(tplg, pos, "tuples: small size %d", size);
+ return -EINVAL;
+ }
+
+next:
+ va = bin;
+ if (size < sizeof(*va)) {
+ tplg_dv(tplg, pos, "tuples: unexpected vendor arry size %d", size);
+ return -EINVAL;
+ }
+
+ err = tplg_verify_tuple_set(tplg, pos, va, va->size);
+ if (err < 0)
+ return err;
+
+ bin += va->size;
+ size -= va->size;
+ pos += va->size;
+ if (size > 0)
+ goto next;
+
+ return 0;
+}
+
+/* add tuples from the binary input */
+static int tplg_decode_tuples(snd_tplg_t *tplg,
+ size_t pos,
+ struct tplg_elem *parent,
+ struct tplg_vendor_tuples *tuples,
+ const void *bin, size_t size)
+{
+ const struct snd_soc_tplg_vendor_array *va;
+ struct tplg_tuple_set *set;
+ int err;
+
+ if (size < sizeof(*va)) {
+ SNDERR("tuples: small size %d", size);
+ return -EINVAL;
+ }
+
+next:
+ va = bin;
+ if (size < sizeof(*va)) {
+ SNDERR("tuples: unexpected vendor arry size %d", size);
+ return -EINVAL;
+ }
+
+ if (tuples->num_sets >= tuples->alloc_sets) {
+ SNDERR("tuples: index overflow (%d)", tuples->num_sets);
+ return -EINVAL;
+ }
+
+ err = tplg_decode_tuple_set(tplg, pos, parent, &set, va, va->size);
+ if (err < 0)
+ return err;
+ tuples->set[tuples->num_sets++] = set;
+
+ bin += va->size;
+ size -= va->size;
+ pos += va->size;
+ if (size > 0)
+ goto next;
+
+ return 0;
+}
+
+/* decode private data */
+int tplg_add_data(snd_tplg_t *tplg,
+ struct tplg_elem *parent,
+ const void *bin, size_t size)
+{
+ const struct snd_soc_tplg_private *tp;
+ const struct snd_soc_tplg_vendor_array *va;
+ struct tplg_elem *elem = NULL, *elem2 = NULL;
+ struct tplg_vendor_tuples *tuples = NULL;
+ char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ char suffix[16];
+ size_t pos = 0, off;
+ int err, num_tuples = 0, block = 0;
+
+ if (size == 0)
+ return 0;
+
+ off = offsetof(struct snd_soc_tplg_private, array);
+
+next:
+ tp = bin;
+ if (off + size < tp->size) {
+ SNDERR("data: unexpected element size %d", size);
+ return -EINVAL;
+ }
+
+ if (tplg_verify_tuples(tplg, pos, tp->array, tp->size) < 0) {
+ if (tuples) {
+ err = tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, parent->id);
+ if (err < 0)
+ return err;
+ err = tplg_ref_add(elem2, SND_TPLG_TYPE_TUPLE, id);
+ if (err < 0)
+ return err;
+ err = tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id);
+ if (err < 0)
+ return err;
+ tuples = NULL;
+ }
+ tplg_dv(tplg, pos, "add bytes: size %d", tp->size);
+ snprintf(suffix, sizeof(suffix), "data%u", block++);
+ err = tplg_add_data_bytes(tplg, parent, suffix, tp->array, tp->size);
+ } else {
+ if (!tuples) {
+ snprintf(id, sizeof(id), "%.30s:tuple%d", parent->id, (block++) & 0xffff);
+ elem = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_TUPLE);
+ if (!elem)
+ return -ENOMEM;
+
+ elem2 = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_DATA);
+ if (!elem2)
+ return -ENOMEM;
+
+ tuples = calloc(1, sizeof(*tuples));
+ if (!tuples)
+ return -ENOMEM;
+ elem->tuples = tuples;
+
+ tuples->alloc_sets = (size / sizeof(*va)) + 1;
+ tuples->set = calloc(1, tuples->alloc_sets * sizeof(void *));
+ if (!tuples->set) {
+ tuples->alloc_sets = 0;
+ return -ENOMEM;
+ }
+ }
+ tplg_dv(tplg, pos, "decode tuples: size %d", tp->size);
+ err = tplg_decode_tuples(tplg, pos, parent, tuples, tp->array, tp->size);
+ num_tuples++;
+ }
+ if (err < 0)
+ return err;
+
+ bin += off + tp->size;
+ size -= off + tp->size;
+ pos += off + tp->size;
+ if (size > 0)
+ goto next;
+
+ if (tuples && elem && elem2) {
+ err = tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, parent->id);
+ if (err < 0)
+ return err;
+ err = tplg_ref_add(elem2, SND_TPLG_TYPE_TUPLE, id);
+ if (err < 0)
+ return err;
+ err = tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+/* add private data - bytes */
+int tplg_add_data_bytes(snd_tplg_t *tplg, struct tplg_elem *parent,
+ const char *suffix, const void *bin, size_t size)
+{
+ struct snd_soc_tplg_private *priv;
+ struct tplg_elem *elem;
+ char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+
+ if (suffix)
+ snprintf(id, sizeof(id), "%.30s:%.12s", parent->id, suffix);
+ else
+ snd_strlcpy(id, parent->id, sizeof(id));
+ elem = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_DATA);
+ if (!elem)
+ return -ENOMEM;
+
+ priv = malloc(sizeof(*priv) + size);
+ if (!priv)
+ return -ENOMEM;
+ memcpy(priv->data, bin, size);
+ priv->size = size;
+ elem->data = priv;
+
+ return tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id);
+}
+
+/* decode data from the binary input */
+int tplg_decode_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
+ size_t pos ATTRIBUTE_UNUSED,
+ struct snd_soc_tplg_hdr *hdr ATTRIBUTE_UNUSED,
+ void *bin ATTRIBUTE_UNUSED,
+ size_t size ATTRIBUTE_UNUSED)
+{
+ SNDERR("data type not expected");
+ return -EINVAL;
+}
diff --git a/src/topology/decoder.c b/src/topology/decoder.c
new file mode 100644
index 00000000..2d6a8969
--- /dev/null
+++ b/src/topology/decoder.c
@@ -0,0 +1,136 @@
+/*
+ Copyright (c) 2019 Red Hat Inc.
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ Authors: Jaroslav Kysela <perex@perex.cz>
+*/
+
+#include "list.h"
+#include "tplg_local.h"
+
+/* verbose output detailing each object size and file position */
+void tplg_dv(snd_tplg_t *tplg, size_t pos, const char *fmt, ...)
+{
+ va_list va;
+
+ if (!tplg->verbose)
+ return;
+
+ va_start(va, fmt);
+ fprintf(stdout, "D0x%6.6zx/%6.6zd - ", pos, pos);
+ vfprintf(stdout, fmt, va);
+ va_end(va);
+ putc('\n', stdout);
+}
+
+int tplg_decode_template(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ snd_tplg_obj_template_t *t)
+{
+ int type;
+
+ type = tplg_get_type(hdr->type);
+ tplg_dv(tplg, pos, "template: asoc type %d library type %d", hdr->type, type);
+ if (type < 0)
+ return type;
+
+ memset(t, 0, sizeof(*t));
+ t->type = type;
+ t->index = hdr->index;
+ t->version = hdr->version;
+ t->vendor_type = hdr->vendor_type;
+ tplg_dv(tplg, pos, "template: index %d version %d vendor_type %d",
+ hdr->index, hdr->version, hdr->vendor_type);
+ return 0;
+}
+
+int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags)
+{
+ struct snd_soc_tplg_hdr *hdr;
+ struct tplg_table *tptr;
+ size_t pos;
+ void *b = bin;
+ unsigned int index;
+ int err;
+
+ if (dflags != 0)
+ return -EINVAL;
+ if (tplg == NULL || bin == NULL)
+ return -EINVAL;
+ while (1) {
+ pos = b - bin;
+ if (size == pos) {
+ tplg_dv(tplg, pos, "block: success (total %zd)", size);
+ return 0;
+ }
+ if (size - pos < sizeof(*hdr)) {
+ tplg_dv(tplg, pos, "block: small size");
+ SNDERR("incomplete header data to decode");
+ return -EINVAL;
+ }
+ hdr = b;
+ if (hdr->magic != SND_SOC_TPLG_MAGIC) {
+ SNDERR("bad block magic %08x", hdr->magic);
+ return -EINVAL;
+ }
+
+ tplg_dv(tplg, pos, "block: abi %d size %d payload size %d",
+ hdr->abi, hdr->size, hdr->payload_size);
+ if (hdr->abi != SND_SOC_TPLG_ABI_VERSION) {
+ SNDERR("unsupported ABI version %d", hdr->abi);
+ return -EINVAL;
+ }
+ if (hdr->size != sizeof(*hdr)) {
+ SNDERR("header size mismatch");
+ return -EINVAL;
+ }
+
+ if (size - pos < hdr->size + hdr->payload_size) {
+ SNDERR("incomplete payload data to decode");
+ return -EINVAL;
+ }
+
+ if (hdr->payload_size < 8) {
+ SNDERR("wrong payload size %d", hdr->payload_size);
+ return -EINVAL;
+ }
+
+ /* first block must be manifest */
+ if (b == bin) {
+ if (hdr->type != SND_SOC_TPLG_TYPE_MANIFEST) {
+ SNDERR("first block must be manifest (value %d)", hdr->type);
+ return -EINVAL;
+ }
+ err = snd_tplg_set_version(tplg, hdr->version);
+ if (err < 0)
+ return err;
+ }
+
+ pos += hdr->size;
+ for (index = 0; index < tplg_table_items; index++) {
+ tptr = &tplg_table[index];
+ if (tptr->tsoc == (int)hdr->type)
+ break;
+ }
+ if (index >= tplg_table_items || tptr->decod == NULL) {
+ SNDERR("unknown block type %d", hdr->type);
+ return -EINVAL;
+ }
+ tplg_dv(tplg, pos, "block: type %d - %s", hdr->type, tptr->name);
+ err = tptr->decod(tplg, pos, hdr, b + hdr->size, hdr->payload_size);
+ if (err < 0)
+ return err;
+ b += hdr->size + hdr->payload_size;
+ }
+}
diff --git a/src/topology/elem.c b/src/topology/elem.c
index 89aed1fc..ed5b5f13 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -31,6 +31,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_manifest_data,
.save = tplg_save_manifest_data,
+ .decod = tplg_decode_manifest_data,
},
{
.name = "control mixer",
@@ -43,6 +44,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_control_mixer,
.save = tplg_save_control_mixer,
+ .decod = tplg_decode_control_mixer,
},
{
.name = "control enum",
@@ -55,6 +57,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_control_enum,
.save = tplg_save_control_enum,
+ .decod = tplg_decode_control_enum,
},
{
.name = "control extended (bytes)",
@@ -67,6 +70,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_control_bytes,
.save = tplg_save_control_bytes,
+ .decod = tplg_decode_control_bytes,
},
{
.name = "dapm widget",
@@ -79,6 +83,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_dapm_widget,
.save = tplg_save_dapm_widget,
+ .decod = tplg_decode_dapm_widget,
},
{
.name = "pcm",
@@ -91,6 +96,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_pcm,
.save = tplg_save_pcm,
+ .decod = tplg_decode_pcm,
},
{
.name = "physical dai",
@@ -103,6 +109,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_dai,
.save = tplg_save_dai,
+ .decod = tplg_decode_dai,
},
{
.name = "be",
@@ -116,6 +123,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_link,
.save = tplg_save_link,
+ .decod = tplg_decode_link,
},
{
.name = "cc",
@@ -128,6 +136,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_cc,
.save = tplg_save_cc,
+ .decod = tplg_decode_cc,
},
{
.name = "route (dapm graph)",
@@ -138,6 +147,7 @@ struct tplg_table tplg_table[] = {
.build = 1,
.parse = tplg_parse_dapm_graph,
.gsave = tplg_save_dapm_graph,
+ .decod = tplg_decode_dapm_graph,
},
{
.name = "private data",
@@ -149,6 +159,7 @@ struct tplg_table tplg_table[] = {
.enew = 1,
.parse = tplg_parse_data,
.save = tplg_save_data,
+ .decod = tplg_decode_data,
},
{
.name = "text",
@@ -220,6 +231,17 @@ struct tplg_table tplg_table[] = {
unsigned int tplg_table_items = ARRAY_SIZE(tplg_table);
+int tplg_get_type(int asoc_type)
+{
+ unsigned int index;
+
+ for (index = 0; index < tplg_table_items; index++)
+ if (tplg_table[index].tsoc == asoc_type)
+ return tplg_table[index].type;
+ SNDERR("uknown asoc type %d", asoc_type);
+ return -EINVAL;
+}
+
int tplg_ref_add(struct tplg_elem *elem, int type, const char* id)
{
struct tplg_ref *ref;
@@ -331,6 +353,36 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base, const char* id,
return NULL;
}
+/* find an element by type */
+struct tplg_elem *tplg_elem_type_lookup(snd_tplg_t *tplg,
+ enum snd_tplg_type type)
+{
+ struct tplg_table *tptr;
+ struct list_head *pos, *list;
+ struct tplg_elem *elem;
+ unsigned int index;
+
+ for (index = 0; index < tplg_table_items; index++) {
+ tptr = &tplg_table[index];
+ if (!tptr->enew)
+ continue;
+ if ((int)type != tptr->type)
+ continue;
+ break;
+ }
+ if (index >= tplg_table_items)
+ return NULL;
+
+ list = (struct list_head *)((void *)tplg + tptr->loff);
+
+ /* return only first element */
+ list_for_each(pos, list) {
+ elem = list_entry(pos, struct tplg_elem, list);
+ return elem;
+ }
+ return NULL;
+}
+
/* insert a new element into list in the ascending order of index value */
void tplg_elem_insert(struct tplg_elem *elem_p, struct list_head *list)
{
@@ -428,3 +480,31 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
elem->type = type;
return elem;
}
+
+struct tplg_alloc {
+ struct list_head list;
+ void *data[0];
+};
+
+void *tplg_calloc(struct list_head *heap, size_t size)
+{
+ struct tplg_alloc *a;
+
+ a = calloc(1, sizeof(*a) + size);
+ if (a == NULL)
+ return NULL;
+ list_add_tail(&a->list, heap);
+ return a->data;
+}
+
+void tplg_free(struct list_head *heap)
+{
+ struct list_head *pos, *npos;
+ struct tplg_alloc *a;
+
+ list_for_each_safe(pos, npos, heap) {
+ a = list_entry(pos, struct tplg_alloc, list);
+ list_del(&a->list);
+ free(a);
+ }
+}
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 5a5dd14f..d7783a93 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -396,17 +396,21 @@ int snd_tplg_build_bin(snd_tplg_t *tplg,
int snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len)
{
+ struct tplg_elem *elem;
+
+ elem = tplg_elem_type_lookup(tplg, SND_TPLG_TYPE_MANIFEST);
+ if (elem == NULL) {
+ elem = tplg_elem_new_common(tplg, NULL, "manifest",
+ SND_TPLG_TYPE_MANIFEST);
+ if (!elem)
+ return -ENOMEM;
+ tplg->manifest.size = elem->size;
+ }
+
if (len <= 0)
return 0;
- tplg->manifest.priv.size = len;
-
- tplg->manifest_pdata = malloc(len);
- if (!tplg->manifest_pdata)
- return -ENOMEM;
-
- memcpy(tplg->manifest_pdata, data, len);
- return 0;
+ return tplg_add_data_bytes(tplg, elem, NULL, data, len);
}
int snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version)
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index bd728959..4e04a6bc 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -1679,11 +1679,20 @@ static void tplg_add_stream_object(struct snd_soc_tplg_stream *strm,
strm->channels = strm_tpl->channels;
}
-static void tplg_add_stream_caps(struct snd_soc_tplg_stream_caps *caps,
- struct snd_tplg_stream_caps_template *caps_tpl)
+static int tplg_add_stream_caps(snd_tplg_t *tplg,
+ struct snd_tplg_stream_caps_template *caps_tpl)
{
- snd_strlcpy(caps->name, caps_tpl->name,
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ struct snd_soc_tplg_stream_caps *caps;
+ struct tplg_elem *elem;
+
+ elem = tplg_elem_new_common(tplg, NULL, caps_tpl->name,
+ SND_TPLG_TYPE_STREAM_CAPS);
+ if (!elem)
+ return -ENOMEM;
+
+ caps = elem->stream_caps;
+
+ snd_strlcpy(caps->name, caps_tpl->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
caps->formats = caps_tpl->formats;
caps->rates = caps_tpl->rates;
@@ -1698,15 +1707,17 @@ static void tplg_add_stream_caps(struct snd_soc_tplg_stream_caps *caps,
caps->buffer_size_min = caps_tpl->buffer_size_min;
caps->buffer_size_max = caps_tpl->buffer_size_max;
caps->sig_bits = caps_tpl->sig_bits;
+ return 0;
}
/* Add a PCM element (FE DAI & DAI link) from C API */
int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
{
struct snd_tplg_pcm_template *pcm_tpl = t->pcm;
- struct snd_soc_tplg_pcm *pcm, *_pcm;
+ struct snd_soc_tplg_private *priv;
+ struct snd_soc_tplg_pcm *pcm;
struct tplg_elem *elem;
- int i;
+ int ret, i;
tplg_dbg("PCM: %s, DAI %s\n", pcm_tpl->pcm_name, pcm_tpl->dai_name);
@@ -1732,8 +1743,13 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
pcm->compress = pcm_tpl->compress;
for (i = 0; i < 2; i++) {
- if (pcm_tpl->caps[i])
- tplg_add_stream_caps(&pcm->caps[i], pcm_tpl->caps[i]);
+ if (!pcm_tpl->caps[i] || !pcm_tpl->caps[i]->name)
+ continue;
+ ret = tplg_add_stream_caps(tplg, pcm_tpl->caps[i]);
+ if (ret < 0)
+ return ret;
+ snd_strlcpy(pcm->caps[i].name, pcm_tpl->caps[i]->name,
+ sizeof(pcm->caps[i].name));
}
pcm->flag_mask = pcm_tpl->flag_mask;
@@ -1744,22 +1760,12 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
tplg_add_stream_object(&pcm->stream[i], &pcm_tpl->stream[i]);
/* private data */
- if (pcm_tpl->priv != NULL && pcm_tpl->priv->size) {
- tplg_dbg("\t priv data size %d\n", pcm_tpl->priv->size);
- _pcm = realloc(pcm,
- elem->size + pcm_tpl->priv->size);
- if (!_pcm) {
- tplg_elem_free(elem);
- return -ENOMEM;
- }
-
- pcm = _pcm;
- elem->pcm = pcm;
- elem->size += pcm_tpl->priv->size;
-
- memcpy(pcm->priv.data, pcm_tpl->priv->data,
- pcm_tpl->priv->size);
- pcm->priv.size = pcm_tpl->priv->size;
+ priv = pcm_tpl->priv;
+ if (priv && priv->size > 0) {
+ ret = tplg_add_data(tplg, elem, priv,
+ sizeof(*priv) + priv->size);
+ if (ret < 0)
+ return ret;
}
return 0;
@@ -1810,9 +1816,11 @@ static int set_link_hw_config(struct snd_soc_tplg_hw_config *cfg,
int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
{
struct snd_tplg_link_template *link_tpl = t->link;
- struct snd_soc_tplg_link_config *link, *_link;
+ struct snd_soc_tplg_link_config *link;
+ struct snd_soc_tplg_private *priv;
struct tplg_elem *elem;
unsigned int i;
+ int ret;
if (t->type != SND_TPLG_TYPE_LINK && t->type != SND_TPLG_TYPE_BE
&& t->type != SND_TPLG_TYPE_CC)
@@ -1854,21 +1862,12 @@ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
link->flags = link_tpl->flags;
/* private data */
- if (link_tpl->priv != NULL && link_tpl->priv->size) {
- _link = realloc(link,
- elem->size + link_tpl->priv->size);
- if (!_link) {
- tplg_elem_free(elem);
- return -ENOMEM;
- }
-
- link = _link;
- elem->link = link;
- elem->size += link_tpl->priv->size;
-
- memcpy(link->priv.data, link_tpl->priv->data,
- link_tpl->priv->size);
- link->priv.size = link_tpl->priv->size;
+ priv = link_tpl->priv;
+ if (priv && priv->size > 0) {
+ ret = tplg_add_data(tplg, elem, priv,
+ sizeof(*priv) + priv->size);
+ if (ret < 0)
+ return ret;
}
return 0;
@@ -1877,14 +1876,15 @@ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
{
struct snd_tplg_dai_template *dai_tpl = t->dai;
- struct snd_soc_tplg_dai *dai, *_dai;
+ struct snd_soc_tplg_dai *dai;
+ struct snd_soc_tplg_private *priv;
struct tplg_elem *elem;
- int i;
+ int ret, i;
tplg_dbg("DAI %s\n", dai_tpl->dai_name);
elem = tplg_elem_new_common(tplg, NULL, dai_tpl->dai_name,
- SND_TPLG_TYPE_DAI);
+ SND_TPLG_TYPE_DAI);
if (!elem)
return -ENOMEM;
@@ -1900,8 +1900,13 @@ int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
dai->capture = dai_tpl->capture;
for (i = 0; i < 2; i++) {
- if (dai_tpl->caps[i])
- tplg_add_stream_caps(&dai->caps[i], dai_tpl->caps[i]);
+ if (!dai_tpl->caps[i] || !dai_tpl->caps[i]->name)
+ continue;
+ ret = tplg_add_stream_caps(tplg, dai_tpl->caps[i]);
+ if (ret < 0)
+ return ret;
+ snd_strlcpy(dai->caps[i].name, dai_tpl->caps[i]->name,
+ sizeof(dai->caps[i].name));
}
/* flags */
@@ -1909,22 +1914,299 @@ int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
dai->flags = dai_tpl->flags;
/* private data */
- if (dai_tpl->priv != NULL) {
- _dai = realloc(dai,
- elem->size + dai_tpl->priv->size);
- if (!_dai) {
- tplg_elem_free(elem);
- return -ENOMEM;
+ priv = dai_tpl->priv;
+ if (priv && priv->size > 0) {
+ ret = tplg_add_data(tplg, elem, priv,
+ sizeof(*priv) + priv->size);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* decode pcm from the binary input */
+int tplg_decode_pcm(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ struct snd_soc_tplg_pcm *pcm;
+ snd_tplg_obj_template_t t;
+ struct snd_tplg_pcm_template *pt;
+ struct snd_tplg_stream_caps_template caps[2], *cap;
+ struct snd_tplg_stream_template *stream;
+ unsigned int i;
+ size_t asize;
+ int err;
+
+ err = tplg_decode_template(tplg, pos, hdr, &t);
+ if (err < 0)
+ return err;
+
+ asize = sizeof(*pt) + SND_SOC_TPLG_STREAM_CONFIG_MAX * sizeof(*stream);
+ pt = alloca(asize);
+
+next:
+ memset(pt, 0, asize);
+ pcm = bin;
+
+ if (size < sizeof(*pcm)) {
+ SNDERR("pcm: small size %d", size);
+ return -EINVAL;
+ }
+ if (sizeof(*pcm) != pcm->size) {
+ SNDERR("pcm: unknown element size %d (expected %zd)",
+ pcm->size, sizeof(*pcm));
+ return -EINVAL;
+ }
+ if (pcm->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX) {
+ SNDERR("pcm: wrong number of streams %d", pcm->num_streams);
+ return -EINVAL;
+ }
+ if (sizeof(*pcm) + pcm->priv.size > size) {
+ SNDERR("pcm: wrong private data size %d", pcm->priv.size);
+ return -EINVAL;
+ }
+
+ tplg_dv(tplg, pos, "pcm: size %d private size %d streams %d",
+ pcm->size, pcm->priv.size, pcm->num_streams);
+
+ pt->pcm_name = pcm->pcm_name;
+ tplg_dv(tplg, pos, "pcm: pcm_name '%s'", pt->pcm_name);
+ pt->dai_name = pcm->dai_name;
+ tplg_dv(tplg, pos, "pcm: dai_name '%s'", pt->dai_name);
+ pt->pcm_id = pcm->pcm_id;
+ pt->dai_id = pcm->dai_id;
+ tplg_dv(tplg, pos, "pcm: pcm_id %d dai_id %d", pt->pcm_id, pt->dai_id);
+ pt->playback = pcm->playback;
+ pt->capture = pcm->capture;
+ pt->compress = pcm->compress;
+ tplg_dv(tplg, pos, "pcm: playback %d capture %d compress",
+ pt->playback, pt->capture, pt->compress);
+ pt->num_streams = pcm->num_streams;
+ pt->flag_mask = pcm->flag_mask;
+ pt->flags = pcm->flags;
+ for (i = 0; i < pcm->num_streams; i++) {
+ stream = &pt->stream[i];
+ if (pcm->stream[i].size != sizeof(pcm->stream[0])) {
+ SNDERR("pcm: unknown stream structure size %d",
+ pcm->stream[i].size);
+ return -EINVAL;
+ }
+ stream->name = pcm->stream[i].name;
+ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, stream[i]),
+ "stream %d: '%s'", i, stream->name);
+ stream->format = pcm->stream[i].format;
+ stream->rate = pcm->stream[i].rate;
+ stream->period_bytes = pcm->stream[i].period_bytes;
+ stream->buffer_bytes = pcm->stream[i].buffer_bytes;
+ stream->channels = pcm->stream[i].channels;
+ }
+ for (i = 0; i < 2; i++) {
+ if (i == 0 && !pcm->playback)
+ continue;
+ if (i == 1 && !pcm->capture)
+ continue;
+ cap = &caps[i];
+ pt->caps[i] = cap;
+ if (pcm->caps[i].size != sizeof(pcm->caps[0])) {
+ SNDERR("pcm: unknown caps structure size %d",
+ pcm->caps[i].size);
+ return -EINVAL;
}
+ cap->name = pcm->caps[i].name;
+ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, caps[i]),
+ "caps %d: '%s'", i, cap->name);
+ cap->formats = pcm->caps[i].formats;
+ cap->rates = pcm->caps[i].rates;
+ cap->rate_min = pcm->caps[i].rate_min;
+ cap->rate_max = pcm->caps[i].rate_max;
+ cap->channels_min = pcm->caps[i].channels_min;
+ cap->channels_max = pcm->caps[i].channels_max;
+ cap->periods_min = pcm->caps[i].periods_min;
+ cap->periods_max = pcm->caps[i].periods_max;
+ cap->period_size_min = pcm->caps[i].period_size_min;
+ cap->period_size_max = pcm->caps[i].period_size_max;
+ cap->buffer_size_min = pcm->caps[i].buffer_size_min;
+ cap->buffer_size_max = pcm->caps[i].buffer_size_max;
+ cap->sig_bits = pcm->caps[i].sig_bits;
+ }
+
+ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, priv),
+ "pcm: private start");
+ pt->priv = &pcm->priv;
+
+ bin += sizeof(*pcm) + pcm->priv.size;
+ size -= sizeof(*pcm) + pcm->priv.size;
+ pos += sizeof(*pcm) + pcm->priv.size;
+
+ t.pcm = pt;
+ err = snd_tplg_add_object(tplg, &t);
+ if (err < 0)
+ return err;
+
+ if (size > 0)
+ goto next;
+
+ return 0;
+}
+
+/* decode dai from the binary input */
+int tplg_decode_dai(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ SNDERR("not implemented");
+ return -ENXIO;
+}
+
+/* decode cc from the binary input */
+int tplg_decode_cc(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ SNDERR("not implemented");
+ return -ENXIO;
+}
+
+/* decode link from the binary input */
+int tplg_decode_link(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size)
+{
+ struct snd_soc_tplg_link_config *link;
+ snd_tplg_obj_template_t t;
+ struct snd_tplg_link_template lt;
+ struct snd_tplg_stream_template streams[SND_SOC_TPLG_STREAM_CONFIG_MAX];
+ struct snd_tplg_stream_template *stream;
+ struct snd_tplg_hw_config_template hws[SND_SOC_TPLG_HW_CONFIG_MAX];
+ struct snd_tplg_hw_config_template *hw;
+ unsigned int i, j;
+ int err;
+
+ err = tplg_decode_template(tplg, pos, hdr, &t);
+ if (err < 0)
+ return err;
+
+next:
+ memset(&lt, 0, sizeof(lt));
+ memset(streams, 0, sizeof(streams));
+ memset(hws, 0, sizeof(hws));
+ link = bin;
- dai = _dai;
- dai->priv.size = dai_tpl->priv->size;
+ if (size < sizeof(*link)) {
+ SNDERR("link: small size %d", size);
+ return -EINVAL;
+ }
+ if (sizeof(*link) != link->size) {
+ SNDERR("link: unknown element size %d (expected %zd)",
+ link->size, sizeof(*link));
+ return -EINVAL;
+ }
+ if (link->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX) {
+ SNDERR("link: wrong number of streams %d", link->num_streams);
+ return -EINVAL;
+ }
+ if (link->num_hw_configs > SND_SOC_TPLG_HW_CONFIG_MAX) {
+ SNDERR("link: wrong number of streams %d", link->num_streams);
+ return -EINVAL;
+ }
+ if (sizeof(*link) + link->priv.size > size) {
+ SNDERR("link: wrong private data size %d", link->priv.size);
+ return -EINVAL;
+ }
- elem->dai = dai;
- elem->size += dai->priv.size;
- memcpy(dai->priv.data, dai_tpl->priv->data,
- dai->priv.size);
+ tplg_dv(tplg, pos, "link: size %d private size %d streams %d "
+ "hw_configs %d",
+ link->size, link->priv.size, link->num_streams,
+ link->num_hw_configs);
+
+ lt.id = link->id;
+ lt.name = link->name;
+ tplg_dv(tplg, pos, "link: name '%s'", lt.name);
+ lt.stream_name = link->stream_name;
+ tplg_dv(tplg, pos, "link: stream_name '%s'", lt.stream_name);
+ lt.num_streams = link->num_streams;
+ lt.num_hw_configs = link->num_hw_configs;
+ lt.default_hw_config_id = link->default_hw_config_id;
+ lt.flag_mask = link->flag_mask;
+ lt.flags = link->flags;
+ for (i = 0; i < link->num_streams; i++) {
+ stream = &streams[i];
+ if (link->stream[i].size != sizeof(link->stream[0])) {
+ SNDERR("link: unknown stream structure size %d",
+ link->stream[i].size);
+ return -EINVAL;
+ }
+ stream->name = link->stream[i].name;
+ tplg_dv(tplg,
+ pos + offsetof(struct snd_soc_tplg_link_config, stream[i]),
+ "stream %d: '%s'", i, stream->name);
+ stream->format = link->stream[i].format;
+ stream->rate = link->stream[i].rate;
+ stream->period_bytes = link->stream[i].period_bytes;
+ stream->buffer_bytes = link->stream[i].buffer_bytes;
+ stream->channels = link->stream[i].channels;
}
+ lt.stream = streams;
+ for (i = 0; i < link->num_hw_configs; i++) {
+ hw = &hws[i];
+ if (link->hw_config[i].size != sizeof(link->hw_config[0])) {
+ SNDERR("link: unknown hw_config structure size %d",
+ link->hw_config[i].size);
+ return -EINVAL;
+ }
+ hw->id = link->hw_config[i].id;
+ hw->fmt = link->hw_config[i].fmt;
+ hw->clock_gated = link->hw_config[i].clock_gated;
+ hw->invert_bclk = link->hw_config[i].invert_bclk;
+ hw->invert_fsync = link->hw_config[i].invert_fsync;
+ hw->bclk_master = link->hw_config[i].bclk_master;
+ hw->fsync_master = link->hw_config[i].fsync_master;
+ hw->mclk_direction = link->hw_config[i].mclk_direction;
+ hw->mclk_rate = link->hw_config[i].mclk_rate;
+ hw->bclk_rate = link->hw_config[i].bclk_rate;
+ hw->fsync_rate = link->hw_config[i].fsync_rate;
+ hw->tdm_slots = link->hw_config[i].tdm_slots;
+ hw->tdm_slot_width = link->hw_config[i].tdm_slot_width;
+ hw->tx_slots = link->hw_config[i].tx_slots;
+ hw->rx_slots = link->hw_config[i].rx_slots;
+ hw->tx_channels = link->hw_config[i].tx_channels;
+ if (hw->tx_channels > SND_SOC_TPLG_MAX_CHAN) {
+ SNDERR("link: wrong tx channels %d", hw->tx_channels);
+ return -EINVAL;
+ }
+ for (j = 0; j < hw->tx_channels; j++)
+ hw->tx_chanmap[j] = link->hw_config[i].tx_chanmap[j];
+ hw->rx_channels = link->hw_config[i].rx_channels;
+ if (hw->rx_channels > SND_SOC_TPLG_MAX_CHAN) {
+ SNDERR("link: wrong rx channels %d", hw->tx_channels);
+ return -EINVAL;
+ }
+ for (j = 0; j < hw->rx_channels; j++)
+ hw->rx_chanmap[j] = link->hw_config[i].rx_chanmap[j];
+ }
+ lt.hw_config = hws;
+
+ tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, priv),
+ "link: private start");
+ lt.priv = &link->priv;
+
+ bin += sizeof(*link) + link->priv.size;
+ size -= sizeof(*link) + link->priv.size;
+ pos += sizeof(*link) + link->priv.size;
+
+ t.link = &lt;
+ err = snd_tplg_add_object(tplg, &t);
+ if (err < 0)
+ return err;
+
+ if (size > 0)
+ goto next;
return 0;
}
diff --git a/src/topology/save.c b/src/topology/save.c
index 0498911f..c6eabc49 100644
--- a/src/topology/save.c
+++ b/src/topology/save.c
@@ -577,6 +577,9 @@ int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags)
if (err < 0)
goto _err;
+ if (*dst == NULL)
+ return -EINVAL;
+
if (flags & SND_TPLG_SAVE_NOCHECK)
return 0;
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 74b3a55c..22fc5fba 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -142,7 +142,8 @@ struct tplg_tuple_set {
};
struct tplg_vendor_tuples {
- unsigned int num_sets;
+ unsigned int num_sets;
+ unsigned int alloc_sets;
struct tplg_tuple_set **set;
};
@@ -217,11 +218,19 @@ struct tplg_table {
char **dst, const char *prefix);
int (*gsave)(snd_tplg_t *tplg, int index,
char **dst, const char *prefix);
+ int (*decod)(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
};
extern struct tplg_table tplg_table[];
extern unsigned int tplg_table_items;
+void *tplg_calloc(struct list_head *heap, size_t size);
+void tplg_free(struct list_head *heap);
+
+int tplg_get_type(int asoc_type);
+
int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
int (*fcn)(snd_tplg_t *, snd_config_t *, void *),
void *private);
@@ -246,6 +255,7 @@ int tplg_parse_link(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
int tplg_parse_cc(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg, void *priv);
+unsigned int tplg_get_tuple_size(int type);
void tplg_free_tuples(void *obj);
int tplg_build_data(snd_tplg_t *tplg);
@@ -272,6 +282,8 @@ struct tplg_elem *tplg_elem_lookup(struct list_head *base,
const char* id,
unsigned int type,
int index);
+struct tplg_elem *tplg_elem_type_lookup(snd_tplg_t *tplg,
+ enum snd_tplg_type type);
struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
snd_config_t *cfg, const char *name, enum snd_tplg_type type);
@@ -291,6 +303,10 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *lookup_pcm_dai_stream(struct list_head *base,
const char* id);
+int tplg_add_data(snd_tplg_t *tplg, struct tplg_elem *parent,
+ const void *bin, size_t size);
+int tplg_add_data_bytes(snd_tplg_t *tplg, struct tplg_elem *parent,
+ const char *suffix, const void *bin, size_t size);
int tplg_add_mixer_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_enum_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
@@ -356,3 +372,56 @@ int tplg_save_stream_caps(snd_tplg_t *tplg, struct tplg_elem *elem,
char **dst, const char *pfx);
int tplg_save_dai(snd_tplg_t *tplg, struct tplg_elem *elem,
char **dst, const char *pfx);
+
+void tplg_dv(snd_tplg_t *tplg, size_t pos, const char *fmt, ...);
+int tplg_decode_template(snd_tplg_t *tplg,
+ size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ snd_tplg_obj_template_t *t);
+int tplg_decode_manifest_data(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_control_mixer1(snd_tplg_t *tplg,
+ struct list_head *heap,
+ struct snd_tplg_mixer_template *mt,
+ size_t pos,
+ void *bin, size_t size);
+int tplg_decode_control_mixer(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_control_enum1(snd_tplg_t *tplg,
+ struct list_head *heap,
+ struct snd_tplg_enum_template *et,
+ size_t pos,
+ void *bin, size_t size);
+int tplg_decode_control_enum(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_control_bytes1(snd_tplg_t *tplg,
+ struct snd_tplg_bytes_template *bt,
+ size_t pos,
+ void *bin, size_t size);
+int tplg_decode_control_bytes(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_data(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_dapm_graph(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_dapm_widget(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_link(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_cc(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_pcm(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
+int tplg_decode_dai(snd_tplg_t *tplg, size_t pos,
+ struct snd_soc_tplg_hdr *hdr,
+ void *bin, size_t size);
--
2.24.1
From cb88813ff71226af5d16f8853d186ff7c572dbe0 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 3 Jan 2020 22:07:11 +0100
Subject: [PATCH 54/69] topology: move the elem->list delete to
tplg_elem_free()
The tplg_elem_free() is called in the error path from many places
and it is expected that the element object will be unregistered
from the tplg structure, too.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/elem.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/topology/elem.c b/src/topology/elem.c
index ed5b5f13..cbd7f4b6 100644
--- a/src/topology/elem.c
+++ b/src/topology/elem.c
@@ -301,6 +301,8 @@ struct tplg_elem *tplg_elem_new(void)
void tplg_elem_free(struct tplg_elem *elem)
{
+ list_del(&elem->list);
+
tplg_ref_free_list(&elem->ref_list);
/* free struct snd_tplg_ object,
@@ -323,7 +325,6 @@ void tplg_elem_free_list(struct list_head *base)
list_for_each_safe(pos, npos, base) {
elem = list_entry(pos, struct tplg_elem, list);
- list_del(&elem->list);
tplg_elem_free(elem);
}
}
--
2.24.1
From ae6522e10621839a15f5a439091af7542d84d3e5 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 3 Jan 2020 22:31:27 +0100
Subject: [PATCH 55/69] topology: unify the log mechanism
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/Makefile.am | 3 ++-
src/topology/builder.c | 54 +++++++++++++++++----------------------
src/topology/ctl.c | 30 +++++++++++-----------
src/topology/dapm.c | 19 +++++++-------
src/topology/data.c | 26 +++++++++----------
src/topology/decoder.c | 32 +++++++----------------
src/topology/log.c | 34 ++++++++++++++++++++++++
src/topology/pcm.c | 48 +++++++++++++++++-----------------
src/topology/tplg_local.h | 8 +++++-
9 files changed, 138 insertions(+), 116 deletions(-)
create mode 100644 src/topology/log.c
diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am
index 12d1d445..9f48891f 100644
--- a/src/topology/Makefile.am
+++ b/src/topology/Makefile.am
@@ -29,7 +29,8 @@ libatopology_la_SOURCES =\
ops.c \
elem.c \
save.c \
- decoder.c
+ decoder.c \
+ log.c
noinst_HEADERS = tplg_local.h
diff --git a/src/topology/builder.c b/src/topology/builder.c
index 74c44405..7af5de08 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -20,20 +20,6 @@
#include "list.h"
#include "tplg_local.h"
-/* verbose output detailing each object size and file position */
-static void verbose(snd_tplg_t *tplg, const char *fmt, ...)
-{
- va_list va;
-
- if (!tplg->verbose)
- return;
-
- va_start(va, fmt);
- fprintf(stdout, "0x%6.6zx/%6.6zd - ", tplg->bin_pos, tplg->bin_pos);
- vfprintf(stdout, fmt, va);
- va_end(va);
-}
-
/* write a block, track the position */
static ssize_t twrite(snd_tplg_t *tplg, void *data, size_t data_size)
{
@@ -73,10 +59,11 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type,
return -EINVAL;
}
- verbose(tplg, "header index %d type %d count %d size 0x%lx/%ld vendor %d "
- "version %d\n", index, type, count,
- (long unsigned int)payload_size, (long int)payload_size,
- vendor_type, version);
+ tplg_log(tplg, 'B', tplg->bin_pos,
+ "header index %d type %d count %d size 0x%lx/%ld vendor %d "
+ "version %d", index, type, count,
+ (long unsigned int)payload_size, (long int)payload_size,
+ vendor_type, version);
tplg->next_hdr_pos += hdr.payload_size + sizeof(hdr);
@@ -121,13 +108,15 @@ static int write_elem_block(snd_tplg_t *tplg,
continue;
if (elem->type != SND_TPLG_TYPE_DAPM_GRAPH)
- verbose(tplg, "%s '%s': write %d bytes\n",
- obj_name, elem->id, elem->size);
+ tplg_log(tplg, 'B', tplg->bin_pos,
+ "%s '%s': write %d bytes",
+ obj_name, elem->id, elem->size);
else
- verbose(tplg, "%s '%s -> %s -> %s': write %d bytes\n",
- obj_name, elem->route->source,
- elem->route->control,
- elem->route->sink, elem->size);
+ tplg_log(tplg, 'B', tplg->bin_pos,
+ "%s '%s -> %s -> %s': write %d bytes",
+ obj_name, elem->route->source,
+ elem->route->control,
+ elem->route->sink, elem->size);
wsize = twrite(tplg, elem->obj, elem->size);
if (wsize < 0)
@@ -225,10 +214,13 @@ static ssize_t write_manifest_data(snd_tplg_t *tplg)
return ret;
}
- verbose(tplg, "manifest: write %d bytes\n", sizeof(tplg->manifest));
+ tplg_log(tplg, 'B', tplg->bin_pos, "manifest: write %d bytes",
+ sizeof(tplg->manifest));
ret = twrite(tplg, &tplg->manifest, sizeof(tplg->manifest));
if (ret >= 0) {
- verbose(tplg, "manifest: write %d priv bytes\n", tplg->manifest.priv.size);
+ tplg_log(tplg, 'B', tplg->bin_pos,
+ "manifest: write %d priv bytes",
+ tplg->manifest.priv.size);
ret = twrite(tplg, tplg->manifest_pdata, tplg->manifest.priv.size);
}
return ret;
@@ -280,9 +272,10 @@ int tplg_write_data(snd_tplg_t *tplg)
size = calc_block_size(list);
if (size == 0)
continue;
- verbose(tplg, "block size for type %s (%d:%d) is 0x%zx/%zd\n",
- tptr->name, tptr->type,
- tptr->tsoc, size, size);
+ tplg_log(tplg, 'B', tplg->bin_pos,
+ "block size for type %s (%d:%d) is 0x%zx/%zd",
+ tptr->name, tptr->type,
+ tptr->tsoc, size, size);
ret = write_elem_block(tplg, list, size,
tptr->tsoc, tptr->name);
if (ret < 0) {
@@ -292,7 +285,8 @@ int tplg_write_data(snd_tplg_t *tplg)
}
}
- verbose(tplg, "total size is 0x%zx/%zd\n", tplg->bin_pos, tplg->bin_pos);
+ tplg_log(tplg, 'B', tplg->bin_pos, "total size is 0x%zx/%zd",
+ tplg->bin_pos, tplg->bin_pos);
if (total_size != tplg->bin_pos) {
SNDERR("total size mismatch (%zd != %zd)",
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 24d437aa..a5a81148 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -1216,8 +1216,8 @@ int tplg_decode_control_mixer1(snd_tplg_t *tplg,
return -EINVAL;
}
- tplg_dv(tplg, pos, "mixer: size %d TLV size %d private size %d",
- mc->size, mc->hdr.tlv.size, mc->priv.size);
+ tplg_log(tplg, 'D', pos, "mixer: size %d TLV size %d private size %d",
+ mc->size, mc->hdr.tlv.size, mc->priv.size);
if (size != mc->size + mc->priv.size) {
SNDERR("mixer: unexpected element size %d", size);
return -EINVAL;
@@ -1233,7 +1233,7 @@ int tplg_decode_control_mixer1(snd_tplg_t *tplg,
mt->min = mc->min;
mt->max = mc->max;
mt->platform_max = mc->platform_max;
- tplg_dv(tplg, pos, "mixer: name '%s' access 0x%x",
+ tplg_log(tplg, 'D', pos, "mixer: name '%s' access 0x%x",
mt->hdr.name, mt->hdr.access);
if (mc->num_channels > 0) {
map = tplg_calloc(heap, sizeof(*map));
@@ -1261,16 +1261,16 @@ int tplg_decode_control_mixer1(snd_tplg_t *tplg,
db->min = mc->hdr.tlv.scale.min;
db->step = mc->hdr.tlv.scale.step;
db->mute = mc->hdr.tlv.scale.mute;
- tplg_dv(tplg, pos, "mixer: dB scale TLV: min %d step %d mute %d",
- db->min, db->step, db->mute);
+ tplg_log(tplg, 'D', pos, "mixer: dB scale TLV: min %d step %d mute %d",
+ db->min, db->step, db->mute);
} else {
SNDERR("mixer: wrong TLV size %d", mc->hdr.tlv.size);
return -EINVAL;
}
mt->priv = &mc->priv;
- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_mixer_control, priv),
- "mixer: private start");
+ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_mixer_control, priv),
+ "mixer: private start");
return 0;
}
@@ -1338,8 +1338,8 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg,
return -EINVAL;
}
- tplg_dv(tplg, pos, "enum: size %d private size %d",
- ec->size, ec->priv.size);
+ tplg_log(tplg, 'D', pos, "enum: size %d private size %d",
+ ec->size, ec->priv.size);
if (size != ec->size + ec->priv.size) {
SNDERR("enum: unexpected element size %d", size);
return -EINVAL;
@@ -1380,8 +1380,8 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg,
cmt.num_channels = ec->num_channels;
for (i = 0; i < cmt.num_channels; i++) {
struct snd_tplg_channel_elem *channel = &cmt.channel[i];
- tplg_dv(tplg, pos + ((void *)&ec->channel[i] - (void *)ec),
- "enum: channel size %d", ec->channel[i].size);
+ tplg_log(tplg, 'D', pos + ((void *)&ec->channel[i] - (void *)ec),
+ "enum: channel size %d", ec->channel[i].size);
channel->reg = ec->channel[i].reg;
channel->shift = ec->channel[i].shift;
channel->id = ec->channel[i].id;
@@ -1452,8 +1452,8 @@ int tplg_decode_control_bytes1(snd_tplg_t *tplg,
return -EINVAL;
}
- tplg_dv(tplg, pos, "control bytes: size %d private size %d",
- bc->size, bc->priv.size);
+ tplg_log(tplg, 'D', pos, "control bytes: size %d private size %d",
+ bc->size, bc->priv.size);
if (size != bc->size + bc->priv.size) {
SNDERR("bytes: unexpected element size %d", size);
return -EINVAL;
@@ -1473,8 +1473,8 @@ int tplg_decode_control_bytes1(snd_tplg_t *tplg,
bt->ext_ops.get = bc->ext_ops.get;
bt->ext_ops.put = bc->ext_ops.put;
bt->ext_ops.info = bc->ext_ops.info;
- tplg_dv(tplg, pos, "control bytes: name '%s' access 0x%x",
- bt->hdr.name, bt->hdr.access);
+ tplg_log(tplg, 'D', pos, "control bytes: name '%s' access 0x%x",
+ bt->hdr.name, bt->hdr.access);
bt->priv = &bc->priv;
return 0;
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index 9fab2d92..0bf64833 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -895,8 +895,8 @@ next:
return -EINVAL;
}
- tplg_dv(tplg, pos, "dapm widget: size %d private size %d kcontrols %d",
- w->size, w->priv.size, w->num_kcontrols);
+ tplg_log(tplg, 'D', pos, "dapm widget: size %d private size %d kcontrols %d",
+ w->size, w->priv.size, w->num_kcontrols);
wt = tplg_calloc(&heap, sizeof(*wt) + sizeof(void *) * w->num_kcontrols);
if (wt == NULL)
@@ -913,7 +913,8 @@ next:
wt->event_flags = w->event_flags;
wt->event_type = w->event_type;
- tplg_dv(tplg, pos, "dapm widget: name '%s' sname '%s'", wt->name, wt->sname);
+ tplg_log(tplg, 'D', pos, "dapm widget: name '%s' sname '%s'",
+ wt->name, wt->sname);
if (sizeof(*w) + w->priv.size > size) {
SNDERR("dapm widget: wrong private data size %d",
@@ -921,8 +922,8 @@ next:
return -EINVAL;
}
- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_dapm_widget, priv),
- "dapm widget: private start");
+ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_dapm_widget, priv),
+ "dapm widget: private start");
wt->priv = &w->priv;
bin += sizeof(*w) + w->priv.size;
@@ -942,7 +943,7 @@ next:
wt->num_ctls++;
mc = bin;
size2 = mc->size + mc->priv.size;
- tplg_dv(tplg, pos, "kcontrol mixer size %zd", size2);
+ tplg_log(tplg, 'D', pos, "kcontrol mixer size %zd", size2);
if (size2 > size) {
SNDERR("dapm widget: small mixer size %d",
size2);
@@ -962,7 +963,7 @@ next:
wt->num_ctls++;
ec = bin;
size2 = ec->size + ec->priv.size;
- tplg_dv(tplg, pos, "kcontrol enum size %zd", size2);
+ tplg_log(tplg, 'D', pos, "kcontrol enum size %zd", size2);
if (size2 > size) {
SNDERR("dapm widget: small enum size %d",
size2);
@@ -982,7 +983,7 @@ next:
wt->num_ctls++;
bc = bin;
size2 = bc->size + bc->priv.size;
- tplg_dv(tplg, pos, "kcontrol bytes size %zd", size2);
+ tplg_log(tplg, 'D', pos, "kcontrol bytes size %zd", size2);
if (size2 > size) {
SNDERR("dapm widget: small bytes size %d",
size2);
@@ -1049,7 +1050,7 @@ int tplg_decode_dapm_graph(snd_tplg_t *tplg,
ge->ctl = g->control;
ge->sink = g->sink;
gt->count++;
- tplg_dv(tplg, pos, "dapm graph: src='%s' ctl='%s' sink='%s'",
+ tplg_log(tplg, 'D', pos, "dapm graph: src='%s' ctl='%s' sink='%s'",
ge->src, ge->ctl, ge->sink);
bin += sizeof(*g);
size -= sizeof(*g);
diff --git a/src/topology/data.c b/src/topology/data.c
index 64563920..0b513428 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -1604,7 +1604,7 @@ int tplg_decode_manifest_data(snd_tplg_t *tplg,
if (!elem)
return -ENOMEM;
- tplg_dv(tplg, pos, "manifest: private size %d", size);
+ tplg_log(tplg, 'D', pos, "manifest: private size %d", size);
return tplg_add_data(tplg, elem, bin, size);
}
@@ -1664,7 +1664,7 @@ static int tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos,
va = bin;
if (size < sizeof(*va) || size < va->size) {
- tplg_dv(tplg, pos, "tuple set verify: wrong size %d", size);
+ tplg_log(tplg, 'A', pos, "tuple set verify: wrong size %d", size);
return -EINVAL;
}
@@ -1677,20 +1677,20 @@ static int tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos,
case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
break;
default:
- tplg_dv(tplg, pos, "tuple set verify: unknown array type %d", va->type);
+ tplg_log(tplg, 'A', pos, "tuple set verify: unknown array type %d", va->type);
return -EINVAL;
}
j = tplg_get_tuple_size(va->type) * va->num_elems;
if (j + sizeof(*va) != va->size) {
- tplg_dv(tplg, pos, "tuple set verify: wrong vendor array size %d "
- "(expected %d for %d count %d)",
- va->size, j + sizeof(*va), va->type, va->num_elems);
+ tplg_log(tplg, 'A', pos, "tuple set verify: wrong vendor array size %d "
+ "(expected %d for %d count %d)",
+ va->size, j + sizeof(*va), va->type, va->num_elems);
return -EINVAL;
}
if (va->num_elems > 4096) {
- tplg_dv(tplg, pos, "tuple set verify: tuples overflow %d", va->num_elems);
+ tplg_log(tplg, 'A', pos, "tuple set verify: tuples overflow %d", va->num_elems);
return -EINVAL;
}
@@ -1748,8 +1748,8 @@ static int tplg_decode_tuple_set(snd_tplg_t *tplg,
set->type = va->type;
set->num_tuples = va->num_elems;
- tplg_dv(tplg, pos, "tuple set: type %d (%s) tuples %d size %d", set->type,
- get_tuple_type_name(set->type), set->num_tuples, va->size);
+ tplg_log(tplg, 'A', pos, "tuple set: type %d (%s) tuples %d size %d", set->type,
+ get_tuple_type_name(set->type), set->num_tuples, va->size);
for (j = 0; j < set->num_tuples; j++) {
tuple = &set->tuple[j];
switch (va->type) {
@@ -1798,14 +1798,14 @@ static int tplg_verify_tuples(snd_tplg_t *tplg, size_t pos,
int err;
if (size < sizeof(*va)) {
- tplg_dv(tplg, pos, "tuples: small size %d", size);
+ tplg_log(tplg, 'A', pos, "tuples: small size %d", size);
return -EINVAL;
}
next:
va = bin;
if (size < sizeof(*va)) {
- tplg_dv(tplg, pos, "tuples: unexpected vendor arry size %d", size);
+ tplg_log(tplg, 'A', pos, "tuples: unexpected vendor arry size %d", size);
return -EINVAL;
}
@@ -1903,7 +1903,7 @@ next:
return err;
tuples = NULL;
}
- tplg_dv(tplg, pos, "add bytes: size %d", tp->size);
+ tplg_log(tplg, 'A', pos, "add bytes: size %d", tp->size);
snprintf(suffix, sizeof(suffix), "data%u", block++);
err = tplg_add_data_bytes(tplg, parent, suffix, tp->array, tp->size);
} else {
@@ -1929,7 +1929,7 @@ next:
return -ENOMEM;
}
}
- tplg_dv(tplg, pos, "decode tuples: size %d", tp->size);
+ tplg_log(tplg, 'A', pos, "decode tuples: size %d", tp->size);
err = tplg_decode_tuples(tplg, pos, parent, tuples, tp->array, tp->size);
num_tuples++;
}
diff --git a/src/topology/decoder.c b/src/topology/decoder.c
index 2d6a8969..66ebe5d8 100644
--- a/src/topology/decoder.c
+++ b/src/topology/decoder.c
@@ -18,21 +18,6 @@
#include "list.h"
#include "tplg_local.h"
-/* verbose output detailing each object size and file position */
-void tplg_dv(snd_tplg_t *tplg, size_t pos, const char *fmt, ...)
-{
- va_list va;
-
- if (!tplg->verbose)
- return;
-
- va_start(va, fmt);
- fprintf(stdout, "D0x%6.6zx/%6.6zd - ", pos, pos);
- vfprintf(stdout, fmt, va);
- va_end(va);
- putc('\n', stdout);
-}
-
int tplg_decode_template(snd_tplg_t *tplg,
size_t pos,
struct snd_soc_tplg_hdr *hdr,
@@ -41,7 +26,8 @@ int tplg_decode_template(snd_tplg_t *tplg,
int type;
type = tplg_get_type(hdr->type);
- tplg_dv(tplg, pos, "template: asoc type %d library type %d", hdr->type, type);
+ tplg_log(tplg, 'D', pos, "template: asoc type %d library type %d",
+ hdr->type, type);
if (type < 0)
return type;
@@ -50,8 +36,8 @@ int tplg_decode_template(snd_tplg_t *tplg,
t->index = hdr->index;
t->version = hdr->version;
t->vendor_type = hdr->vendor_type;
- tplg_dv(tplg, pos, "template: index %d version %d vendor_type %d",
- hdr->index, hdr->version, hdr->vendor_type);
+ tplg_log(tplg, 'D', pos, "template: index %d version %d vendor_type %d",
+ hdr->index, hdr->version, hdr->vendor_type);
return 0;
}
@@ -71,11 +57,11 @@ int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags)
while (1) {
pos = b - bin;
if (size == pos) {
- tplg_dv(tplg, pos, "block: success (total %zd)", size);
+ tplg_log(tplg, 'D', pos, "block: success (total %zd)", size);
return 0;
}
if (size - pos < sizeof(*hdr)) {
- tplg_dv(tplg, pos, "block: small size");
+ tplg_log(tplg, 'D', pos, "block: small size");
SNDERR("incomplete header data to decode");
return -EINVAL;
}
@@ -85,8 +71,8 @@ int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags)
return -EINVAL;
}
- tplg_dv(tplg, pos, "block: abi %d size %d payload size %d",
- hdr->abi, hdr->size, hdr->payload_size);
+ tplg_log(tplg, 'D', pos, "block: abi %d size %d payload size %d",
+ hdr->abi, hdr->size, hdr->payload_size);
if (hdr->abi != SND_SOC_TPLG_ABI_VERSION) {
SNDERR("unsupported ABI version %d", hdr->abi);
return -EINVAL;
@@ -127,7 +113,7 @@ int snd_tplg_decode(snd_tplg_t *tplg, void *bin, size_t size, int dflags)
SNDERR("unknown block type %d", hdr->type);
return -EINVAL;
}
- tplg_dv(tplg, pos, "block: type %d - %s", hdr->type, tptr->name);
+ tplg_log(tplg, 'D', pos, "block: type %d - %s", hdr->type, tptr->name);
err = tptr->decod(tplg, pos, hdr, b + hdr->size, hdr->payload_size);
if (err < 0)
return err;
diff --git a/src/topology/log.c b/src/topology/log.c
new file mode 100644
index 00000000..1ca36528
--- /dev/null
+++ b/src/topology/log.c
@@ -0,0 +1,34 @@
+/*
+ Copyright (c) 2019 Red Hat Inc.
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ Authors: Jaroslav Kysela <perex@perex.cz>
+*/
+
+#include "list.h"
+#include "tplg_local.h"
+
+/* verbose output detailing each object size and file position */
+void tplg_log_(snd_tplg_t *tplg, char type, size_t pos, const char *fmt, ...)
+{
+ va_list va;
+
+ if (!tplg->verbose)
+ return;
+
+ va_start(va, fmt);
+ fprintf(stdout, "%c0x%6.6zx/%6.6zd - ", type, pos, pos);
+ vfprintf(stdout, fmt, va);
+ va_end(va);
+ putc('\n', stdout);
+}
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 4e04a6bc..918e3e9a 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -1969,21 +1969,21 @@ next:
return -EINVAL;
}
- tplg_dv(tplg, pos, "pcm: size %d private size %d streams %d",
- pcm->size, pcm->priv.size, pcm->num_streams);
+ tplg_log(tplg, 'D', pos, "pcm: size %d private size %d streams %d",
+ pcm->size, pcm->priv.size, pcm->num_streams);
pt->pcm_name = pcm->pcm_name;
- tplg_dv(tplg, pos, "pcm: pcm_name '%s'", pt->pcm_name);
+ tplg_log(tplg, 'D', pos, "pcm: pcm_name '%s'", pt->pcm_name);
pt->dai_name = pcm->dai_name;
- tplg_dv(tplg, pos, "pcm: dai_name '%s'", pt->dai_name);
+ tplg_log(tplg, 'D', pos, "pcm: dai_name '%s'", pt->dai_name);
pt->pcm_id = pcm->pcm_id;
pt->dai_id = pcm->dai_id;
- tplg_dv(tplg, pos, "pcm: pcm_id %d dai_id %d", pt->pcm_id, pt->dai_id);
+ tplg_log(tplg, 'D', pos, "pcm: pcm_id %d dai_id %d", pt->pcm_id, pt->dai_id);
pt->playback = pcm->playback;
pt->capture = pcm->capture;
pt->compress = pcm->compress;
- tplg_dv(tplg, pos, "pcm: playback %d capture %d compress",
- pt->playback, pt->capture, pt->compress);
+ tplg_log(tplg, 'D', pos, "pcm: playback %d capture %d compress",
+ pt->playback, pt->capture, pt->compress);
pt->num_streams = pcm->num_streams;
pt->flag_mask = pcm->flag_mask;
pt->flags = pcm->flags;
@@ -1995,8 +1995,8 @@ next:
return -EINVAL;
}
stream->name = pcm->stream[i].name;
- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, stream[i]),
- "stream %d: '%s'", i, stream->name);
+ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_pcm, stream[i]),
+ "stream %d: '%s'", i, stream->name);
stream->format = pcm->stream[i].format;
stream->rate = pcm->stream[i].rate;
stream->period_bytes = pcm->stream[i].period_bytes;
@@ -2016,8 +2016,8 @@ next:
return -EINVAL;
}
cap->name = pcm->caps[i].name;
- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, caps[i]),
- "caps %d: '%s'", i, cap->name);
+ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_pcm, caps[i]),
+ "caps %d: '%s'", i, cap->name);
cap->formats = pcm->caps[i].formats;
cap->rates = pcm->caps[i].rates;
cap->rate_min = pcm->caps[i].rate_min;
@@ -2033,8 +2033,8 @@ next:
cap->sig_bits = pcm->caps[i].sig_bits;
}
- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, priv),
- "pcm: private start");
+ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_pcm, priv),
+ "pcm: private start");
pt->priv = &pcm->priv;
bin += sizeof(*pcm) + pcm->priv.size;
@@ -2120,16 +2120,16 @@ next:
return -EINVAL;
}
- tplg_dv(tplg, pos, "link: size %d private size %d streams %d "
- "hw_configs %d",
- link->size, link->priv.size, link->num_streams,
- link->num_hw_configs);
+ tplg_log(tplg, 'D', pos, "link: size %d private size %d streams %d "
+ "hw_configs %d",
+ link->size, link->priv.size, link->num_streams,
+ link->num_hw_configs);
lt.id = link->id;
lt.name = link->name;
- tplg_dv(tplg, pos, "link: name '%s'", lt.name);
+ tplg_log(tplg, 'D', pos, "link: name '%s'", lt.name);
lt.stream_name = link->stream_name;
- tplg_dv(tplg, pos, "link: stream_name '%s'", lt.stream_name);
+ tplg_log(tplg, 'D', pos, "link: stream_name '%s'", lt.stream_name);
lt.num_streams = link->num_streams;
lt.num_hw_configs = link->num_hw_configs;
lt.default_hw_config_id = link->default_hw_config_id;
@@ -2143,9 +2143,9 @@ next:
return -EINVAL;
}
stream->name = link->stream[i].name;
- tplg_dv(tplg,
- pos + offsetof(struct snd_soc_tplg_link_config, stream[i]),
- "stream %d: '%s'", i, stream->name);
+ tplg_log(tplg, 'D',
+ pos + offsetof(struct snd_soc_tplg_link_config, stream[i]),
+ "stream %d: '%s'", i, stream->name);
stream->format = link->stream[i].format;
stream->rate = link->stream[i].rate;
stream->period_bytes = link->stream[i].period_bytes;
@@ -2192,8 +2192,8 @@ next:
}
lt.hw_config = hws;
- tplg_dv(tplg, pos + offsetof(struct snd_soc_tplg_pcm, priv),
- "link: private start");
+ tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_pcm, priv),
+ "link: private start");
lt.priv = &link->priv;
bin += sizeof(*link) + link->priv.size;
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 22fc5fba..e061db75 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -226,6 +226,13 @@ struct tplg_table {
extern struct tplg_table tplg_table[];
extern unsigned int tplg_table_items;
+#define tplg_log(tplg, type, pos, fmt, args...) do { \
+ if ((tplg)->verbose) \
+ tplg_log_((tplg), (type), (pos), (fmt), ##args); \
+} while (0)
+
+void tplg_log_(snd_tplg_t *tplg, char type, size_t pos, const char *fmt, ...);
+
void *tplg_calloc(struct list_head *heap, size_t size);
void tplg_free(struct list_head *heap);
@@ -373,7 +380,6 @@ int tplg_save_stream_caps(snd_tplg_t *tplg, struct tplg_elem *elem,
int tplg_save_dai(snd_tplg_t *tplg, struct tplg_elem *elem,
char **dst, const char *pfx);
-void tplg_dv(snd_tplg_t *tplg, size_t pos, const char *fmt, ...);
int tplg_decode_template(snd_tplg_t *tplg,
size_t pos,
struct snd_soc_tplg_hdr *hdr,
--
2.24.1
From d768da27e7f9f56328c61ed5d37c17ce075cbc6e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 3 Jan 2020 22:44:15 +0100
Subject: [PATCH 56/69] topology: tplg_dbg() cleanups
- remove newline at the end
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/channel.c | 6 +++---
src/topology/ctl.c | 40 +++++++++++++++++------------------
src/topology/dapm.c | 32 ++++++++++++++--------------
src/topology/data.c | 48 ++++++++++++++++++++++++------------------
src/topology/ops.c | 8 +++----
src/topology/pcm.c | 36 +++++++++++++++----------------
src/topology/text.c | 6 +++---
7 files changed, 91 insertions(+), 85 deletions(-)
diff --git a/src/topology/channel.c b/src/topology/channel.c
index 390c3f16..47d5ea4c 100644
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -100,7 +100,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
channel += tplg->channel_idx;
snd_config_get_id(cfg, &id);
- tplg_dbg("\tChannel %s at index %d\n", id, tplg->channel_idx);
+ tplg_dbg("\tChannel %s at index %d", id, tplg->channel_idx);
channel_id = lookup_channel(id);
if (channel_id < 0) {
@@ -110,7 +110,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
channel->id = channel_id;
channel->size = sizeof(*channel);
- tplg_dbg("\tChan %s = %d\n", id, channel->id);
+ tplg_dbg("\tChan %s = %d", id, channel->id);
snd_config_for_each(i, next, cfg) {
@@ -129,7 +129,7 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
else if (strcmp(id, "shift") == 0)
channel->shift = value;
- tplg_dbg("\t\t%s = %d\n", id, value);
+ tplg_dbg("\t\t%s = %d", id, value);
}
tplg->channel_idx++;
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index a5a81148..41dc2ddb 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -54,7 +54,7 @@ static int parse_access_values(snd_config_t *cfg,
const char *value = NULL;
unsigned int j;
- tplg_dbg(" Access:\n");
+ tplg_dbg(" Access:");
snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i);
@@ -67,7 +67,7 @@ static int parse_access_values(snd_config_t *cfg,
for (j = 0; j < ARRAY_SIZE(ctl_access); j++) {
if (strcmp(value, ctl_access[j].name) == 0) {
hdr->access |= ctl_access[j].value;
- tplg_dbg("\t%s\n", value);
+ tplg_dbg("\t%s", value);
break;
}
}
@@ -150,7 +150,7 @@ static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
struct snd_soc_tplg_mixer_control *mixer_ctrl = elem->mixer_ctrl;
struct snd_soc_tplg_ctl_tlv *tlv = ref->tlv;
- tplg_dbg("TLV '%s' used by '%s\n", ref->id, elem->id);
+ tplg_dbg("TLV '%s' used by '%s", ref->id, elem->id);
/* TLV has a fixed size */
mixer_ctrl->hdr.tlv = *tlv;
@@ -330,7 +330,7 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
const char *id = NULL;
int val;
- tplg_dbg(" scale: %s\n", elem->id);
+ tplg_dbg(" scale: %s", elem->id);
tplg_tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
tplg_tlv->type = SNDRV_CTL_TLVT_DB_SCALE;
@@ -348,7 +348,7 @@ static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
if (tplg_get_integer(n, &val, 0))
continue;
- tplg_dbg("\t%s = %i\n", id, val);
+ tplg_dbg("\t%s = %i", id, val);
/* get TLV data */
if (strcmp(id, "min") == 0)
@@ -450,7 +450,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
snd_strlcpy(be->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
be->hdr.type = SND_SOC_TPLG_TYPE_BYTES;
- tplg_dbg(" Control Bytes: %s\n", elem->id);
+ tplg_dbg(" Control Bytes: %s", elem->id);
snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i);
@@ -468,7 +468,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
return -EINVAL;
be->base = ival;
- tplg_dbg("\t%s: %d\n", id, be->base);
+ tplg_dbg("\t%s: %d", id, be->base);
continue;
}
@@ -477,7 +477,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
return -EINVAL;
be->num_regs = ival;
- tplg_dbg("\t%s: %d\n", id, be->num_regs);
+ tplg_dbg("\t%s: %d", id, be->num_regs);
continue;
}
@@ -486,7 +486,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
return -EINVAL;
be->max = ival;
- tplg_dbg("\t%s: %d\n", id, be->max);
+ tplg_dbg("\t%s: %d", id, be->max);
continue;
}
@@ -495,7 +495,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
return -EINVAL;
be->mask = ival;
- tplg_dbg("\t%s: %d\n", id, be->mask);
+ tplg_dbg("\t%s: %d", id, be->mask);
continue;
}
@@ -515,7 +515,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
return err;
tlv_set = true;
- tplg_dbg("\t%s: %s\n", id, val);
+ tplg_dbg("\t%s: %s", id, val);
continue;
}
@@ -625,7 +625,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
ec->channel[j].reg = -1;
}
- tplg_dbg(" Control Enum: %s\n", elem->id);
+ tplg_dbg(" Control Enum: %s", elem->id);
snd_config_for_each(i, next, cfg) {
@@ -644,7 +644,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
return -EINVAL;
tplg_ref_add(elem, SND_TPLG_TYPE_TEXT, val);
- tplg_dbg("\t%s: %s\n", id, val);
+ tplg_dbg("\t%s: %s", id, val);
continue;
}
@@ -761,7 +761,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++)
mc->channel[j].reg = -1;
- tplg_dbg(" Control Mixer: %s\n", elem->id);
+ tplg_dbg(" Control Mixer: %s", elem->id);
/* giterate trough each mixer elment */
snd_config_for_each(i, next, cfg) {
@@ -795,7 +795,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
return -EINVAL;
mc->max = ival;
- tplg_dbg("\t%s: %d\n", id, mc->max);
+ tplg_dbg("\t%s: %d", id, mc->max);
continue;
}
@@ -805,7 +805,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
return -EINVAL;
mc->invert = ival;
- tplg_dbg("\t%s: %d\n", id, mc->invert);
+ tplg_dbg("\t%s: %d", id, mc->invert);
continue;
}
@@ -826,7 +826,7 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
return err;
tlv_set = true;
- tplg_dbg("\t%s: %s\n", id, val);
+ tplg_dbg("\t%s: %s", id, val);
continue;
}
@@ -981,7 +981,7 @@ int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
struct tplg_elem *elem;
int ret, i, num_channels;
- tplg_dbg(" Control Mixer: %s\n", mixer->hdr.name);
+ tplg_dbg(" Control Mixer: %s", mixer->hdr.name);
if (mixer->hdr.type != SND_SOC_TPLG_TYPE_MIXER) {
SNDERR("invalid mixer type %d", mixer->hdr.type);
@@ -1045,7 +1045,7 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
struct tplg_elem *elem;
int ret, i, num_items, num_channels;
- tplg_dbg(" Control Enum: %s\n", enum_ctl->hdr.name);
+ tplg_dbg(" Control Enum: %s", enum_ctl->hdr.name);
if (enum_ctl->hdr.type != SND_SOC_TPLG_TYPE_ENUM) {
SNDERR("invalid enum type %d", enum_ctl->hdr.type);
@@ -1128,7 +1128,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
struct tplg_elem *elem;
int ret;
- tplg_dbg(" Control Bytes: %s\n", bytes_ctl->hdr.name);
+ tplg_dbg(" Control Bytes: %s", bytes_ctl->hdr.name);
if (bytes_ctl->hdr.type != SND_SOC_TPLG_TYPE_BYTES) {
SNDERR("invalid bytes type %d", bytes_ctl->hdr.type);
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index 0bf64833..cb85e667 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -76,8 +76,8 @@ static int copy_dapm_control(struct tplg_elem *elem, struct tplg_elem *ref)
{
struct snd_soc_tplg_dapm_widget *widget = elem->widget;
- tplg_dbg("Control '%s' used by '%s'\n", ref->id, elem->id);
- tplg_dbg("\tparent size: %d + %d -> %d, priv size -> %d\n",
+ tplg_dbg("Control '%s' used by '%s'", ref->id, elem->id);
+ tplg_dbg("\tparent size: %d + %d -> %d, priv size -> %d",
elem->size, ref->size, elem->size + ref->size,
widget->priv.size);
@@ -210,8 +210,8 @@ int tplg_build_routes(snd_tplg_t *tplg)
}
route = elem->route;
- tplg_dbg("\nCheck route: sink '%s', control '%s', source '%s'\n",
- route->sink, route->control, route->source);
+ tplg_dbg("Check route: sink '%s', control '%s', source '%s'",
+ route->sink, route->control, route->source);
/* validate sink */
if (strlen(route->sink) <= 0) {
@@ -357,7 +357,7 @@ static int tplg_parse_routes(snd_tplg_t *tplg, snd_config_t *cfg, int index)
if (err < 0)
return err;
- tplg_dbg("route: sink '%s', control '%s', source '%s'\n",
+ tplg_dbg("route: sink '%s', control '%s', source '%s'",
line->sink, line->control, line->source);
}
@@ -520,7 +520,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
if (!elem)
return -ENOMEM;
- tplg_dbg(" Widget: %s\n", elem->id);
+ tplg_dbg(" Widget: %s", elem->id);
widget = elem->widget;
snd_strlcpy(widget->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
@@ -550,7 +550,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
}
widget->id = widget_type;
- tplg_dbg("\t%s: %s\n", id, val);
+ tplg_dbg("\t%s: %s", id, val);
continue;
}
@@ -560,7 +560,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
snd_strlcpy(widget->sname, val,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg("\t%s: %s\n", id, val);
+ tplg_dbg("\t%s: %s", id, val);
continue;
}
@@ -571,7 +571,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
widget->reg = ival ? -1 : 0;
- tplg_dbg("\t%s: %s\n", id, val);
+ tplg_dbg("\t%s: %s", id, val);
continue;
}
@@ -580,7 +580,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
return -EINVAL;
widget->shift = ival;
- tplg_dbg("\t%s: %d\n", id, widget->shift);
+ tplg_dbg("\t%s: %d", id, widget->shift);
continue;
}
@@ -589,7 +589,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
return -EINVAL;
widget->reg = ival;
- tplg_dbg("\t%s: %d\n", id, widget->reg);
+ tplg_dbg("\t%s: %d", id, widget->reg);
continue;
}
@@ -598,7 +598,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
return -EINVAL;
widget->invert = ival;
- tplg_dbg("\t%s: %d\n", id, widget->invert);
+ tplg_dbg("\t%s: %d", id, widget->invert);
continue;
}
@@ -607,7 +607,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
return -EINVAL;
widget->subseq = ival;
- tplg_dbg("\t%s: %d\n", id, widget->subseq);
+ tplg_dbg("\t%s: %d", id, widget->subseq);
continue;
}
@@ -616,7 +616,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
return -EINVAL;
widget->event_type = ival;
- tplg_dbg("\t%s: %d\n", id, widget->event_type);
+ tplg_dbg("\t%s: %d", id, widget->event_type);
continue;
}
@@ -625,7 +625,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
return -EINVAL;
widget->event_flags = ival;
- tplg_dbg("\t%s: %d\n", id, widget->event_flags);
+ tplg_dbg("\t%s: %d", id, widget->event_flags);
continue;
}
@@ -767,7 +767,7 @@ int tplg_add_widget_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
struct tplg_elem *elem;
int i, ret = 0;
- tplg_dbg("Widget: %s\n", wt->name);
+ tplg_dbg("Widget: %s", wt->name);
elem = tplg_elem_new_common(tplg, NULL, wt->name,
SND_TPLG_TYPE_DAPM_WIDGET);
diff --git a/src/topology/data.c b/src/topology/data.c
index 0b513428..37c45919 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -87,7 +87,7 @@ int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem,
if (snd_config_get_string(cfg, &val) < 0)
return -EINVAL;
- tplg_dbg("\tref data: %s\n", val);
+ tplg_dbg("\tref data: %s", val);
err = tplg_ref_add(elem, type, val);
if (err < 0)
return err;
@@ -108,7 +108,7 @@ int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem,
if (snd_config_get_string(n, &val) < 0)
continue;
- tplg_dbg("\tref data: %s\n", val);
+ tplg_dbg("\tref data: %s", val);
err = tplg_ref_add(elem, type, val);
if (err < 0)
return err;
@@ -169,7 +169,7 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)
size_t size, bytes_read;
int ret = 0;
- tplg_dbg("data DataFile: %s\n", elem->id);
+ tplg_dbg("data DataFile: %s", elem->id);
if (snd_config_get_string(cfg, &value) < 0)
return -EINVAL;
@@ -235,19 +235,25 @@ static void dump_priv_data(struct tplg_elem *elem ATTRIBUTE_UNUSED)
#ifdef TPLG_DEBUG
struct snd_soc_tplg_private *priv = elem->data;
unsigned char *p = (unsigned char *)priv->data;
+ char buf[128], buf2[8];
unsigned int i;
- tplg_dbg(" elem size = %d, priv data size = %d\n",
+ tplg_dbg(" elem size = %d, priv data size = %d",
elem->size, priv->size);
+ buf[0] = '\0';
for (i = 0; i < priv->size; i++) {
- if (i > 0 && (i % 16) == 0)
- tplg_dbg("\n");
+ if (i > 0 && (i % 16) == 0) {
+ tplg_dbg("%s", buf);
+ buf[0] = '\0';
+ }
- tplg_dbg(" %02x:", *p++);
+ snprintf(buf2, sizeof(buf2), " %02x", *p++);
+ strcat(buf, buf2);
}
- tplg_dbg("\n\n");
+ if (buf[0])
+ tplg_dbg("%s", buf);
#endif
}
@@ -466,7 +472,7 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
int size, esize, off, num;
int ret;
- tplg_dbg(" data: %s\n", elem->id);
+ tplg_dbg(" data: %s", elem->id);
if (snd_config_get_string(cfg, &value) < 0)
return -EINVAL;
@@ -683,7 +689,7 @@ static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)
if (ref->type != SND_TPLG_TYPE_TUPLE)
continue;
- tplg_dbg("tuples '%s' used by data '%s'\n", ref->id, elem->id);
+ tplg_dbg("tuples '%s' used by data '%s'", ref->id, elem->id);
if (!ref->elem)
ref->elem = tplg_elem_lookup(&tplg->tuple_list,
@@ -799,7 +805,7 @@ static int parse_tuple_set(snd_config_t *cfg,
if (!num_tuples)
return 0;
- tplg_dbg("\t %d %s tuples:\n", num_tuples, id);
+ tplg_dbg("\t %d %s tuples:", num_tuples, id);
set = calloc(1, sizeof(*set) + num_tuples * sizeof(struct tplg_tuple));
if (!set)
return -ENOMEM;
@@ -831,7 +837,7 @@ static int parse_tuple_set(snd_config_t *cfg,
continue;
snd_strlcpy(tuple->string, value,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg("\t\t%s = %s\n", tuple->token, tuple->string);
+ tplg_dbg("\t\t%s = %s", tuple->token, tuple->string);
break;
case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
@@ -839,7 +845,7 @@ static int parse_tuple_set(snd_config_t *cfg,
if (ival < 0)
continue;
tuple->value = ival;
- tplg_dbg("\t\t%s = %d\n", tuple->token, tuple->value);
+ tplg_dbg("\t\t%s = %d", tuple->token, tuple->value);
break;
case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
@@ -862,7 +868,7 @@ static int parse_tuple_set(snd_config_t *cfg,
}
tuple->value = tuple_val;
- tplg_dbg("\t\t%s = 0x%x\n", tuple->token, tuple->value);
+ tplg_dbg("\t\t%s = 0x%x", tuple->token, tuple->value);
break;
default:
@@ -1047,7 +1053,7 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
if (!num_tokens)
return 0;
- tplg_dbg(" Vendor tokens: %s, %d tokens\n", elem->id, num_tokens);
+ tplg_dbg(" Vendor tokens: %s, %d tokens", elem->id, num_tokens);
tokens = calloc(1, sizeof(*tokens)
+ num_tokens * sizeof(struct tplg_token));
@@ -1067,7 +1073,7 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
snd_strlcpy(tokens->token[tokens->num_tokens].id, id,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
tokens->token[tokens->num_tokens].value = value;
- tplg_dbg("\t\t %s : %d\n", tokens->token[tokens->num_tokens].id,
+ tplg_dbg("\t\t %s : %d", tokens->token[tokens->num_tokens].id,
tokens->token[tokens->num_tokens].value);
tokens->num_tokens++;
}
@@ -1116,7 +1122,7 @@ int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
if (!elem)
return -ENOMEM;
- tplg_dbg(" Vendor Tuples: %s\n", elem->id);
+ tplg_dbg(" Vendor Tuples: %s", elem->id);
tuples = calloc(1, sizeof(*tuples));
if (!tuples)
@@ -1133,7 +1139,7 @@ int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
if (snd_config_get_string(n, &value) < 0)
return -EINVAL;
tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, value);
- tplg_dbg("\t refer to vendor tokens: %s\n", value);
+ tplg_dbg("\t refer to vendor tokens: %s", value);
}
if (strcmp(id, "tuples") == 0) {
@@ -1208,7 +1214,7 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg,
manifest = elem->manifest;
manifest->size = elem->size;
- tplg_dbg(" Manifest: %s\n", elem->id);
+ tplg_dbg(" Manifest: %s", elem->id);
snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i);
@@ -1402,7 +1408,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
return -EINVAL;
elem->vendor_type = ival;
- tplg_dbg("\t%s: %d\n", id, elem->index);
+ tplg_dbg("\t%s: %d", id, elem->index);
continue;
}
}
@@ -1506,7 +1512,7 @@ int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem,
return -EINVAL;
}
- tplg_dbg("Data '%s' used by '%s'\n", ref->id, elem->id);
+ tplg_dbg("Data '%s' used by '%s'", ref->id, elem->id);
/* overlook empty private data */
if (!ref_elem->data || !ref_elem->data->size) {
ref->elem = ref_elem;
diff --git a/src/topology/ops.c b/src/topology/ops.c
index 2885c781..110eef58 100644
--- a/src/topology/ops.c
+++ b/src/topology/ops.c
@@ -69,7 +69,7 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
const char *id, *value;
int ival;
- tplg_dbg("\tOps\n");
+ tplg_dbg("\tOps");
hdr->size = sizeof(*hdr);
snd_config_for_each(i, next, cfg) {
@@ -97,7 +97,7 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
else if (strcmp(id, "get") == 0)
hdr->ops.get = ival;
- tplg_dbg("\t\t%s = %d\n", id, ival);
+ tplg_dbg("\t\t%s = %d", id, ival);
}
return 0;
@@ -155,7 +155,7 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
const char *id, *value;
int ival;
- tplg_dbg("\tExt Ops\n");
+ tplg_dbg("\tExt Ops");
snd_config_for_each(i, next, cfg) {
@@ -182,7 +182,7 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
else if (strcmp(id, "get") == 0)
be->ext_ops.get = ival;
- tplg_dbg("\t\t%s = %s\n", id, value);
+ tplg_dbg("\t\t%s = %s", id, value);
}
return 0;
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 918e3e9a..da88783f 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -68,7 +68,7 @@ static void copy_stream_caps(const char *id ATTRIBUTE_UNUSED,
{
struct snd_soc_tplg_stream_caps *ref_caps = ref_elem->stream_caps;
- tplg_dbg("Copy pcm caps (%ld bytes) from '%s' to '%s' \n",
+ tplg_dbg("Copy pcm caps (%ld bytes) from '%s' to '%s'",
sizeof(*caps), ref_elem->id, id);
*caps = *ref_caps;
@@ -388,7 +388,7 @@ static int parse_unsigned(snd_config_t *n, unsigned int *dst)
{
const char *id;
if (snd_config_get_id(n, &id) >= 0)
- tplg_dbg("\t\t%s: %d\n", id, *dst);
+ tplg_dbg("\t\t%s: %d", id, *dst);
}
#endif
return 0;
@@ -415,7 +415,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
sc->size = elem->size;
snd_strlcpy(sc->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg(" PCM Capabilities: %s\n", elem->id);
+ tplg_dbg(" PCM Capabilities: %s", elem->id);
snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i);
@@ -442,7 +442,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
if (err < 0)
return err;
- tplg_dbg("\t\t%s: %s\n", id, val);
+ tplg_dbg("\t\t%s: %s", id, val);
continue;
}
@@ -460,7 +460,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
if (err < 0)
return err;
- tplg_dbg("\t\t%s: %s\n", id, val);
+ tplg_dbg("\t\t%s: %s", id, val);
continue;
}
@@ -625,7 +625,7 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_get_id(cfg, &id);
- tplg_dbg("\t%s:\n", id);
+ tplg_dbg("\t%s:", id);
switch (elem->type) {
case SND_TPLG_TYPE_PCM:
@@ -672,7 +672,7 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_strlcpy(caps[stream].name, value,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg("\t\t%s\n\t\t\t%s\n", id, value);
+ tplg_dbg("\t\t%s\n\t\t\t%s", id, value);
continue;
}
}
@@ -746,7 +746,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
const char *id;
snd_config_get_id(cfg, &id);
- tplg_dbg("\t\tFE DAI %s:\n", id);
+ tplg_dbg("\t\tFE DAI %s:", id);
snd_strlcpy(pcm->dai_name, id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
snd_config_for_each(i, next, cfg) {
@@ -763,7 +763,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
return -EINVAL;
}
- tplg_dbg("\t\t\tindex: %d\n", pcm->dai_id);
+ tplg_dbg("\t\t\tindex: %d", pcm->dai_id);
}
}
@@ -847,7 +847,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
pcm->size = elem->size;
snd_strlcpy(pcm->pcm_name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg(" PCM: %s\n", elem->id);
+ tplg_dbg(" PCM: %s", elem->id);
snd_config_for_each(i, next, cfg) {
@@ -882,7 +882,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
pcm->compress = ival;
- tplg_dbg("\t%s: %d\n", id, ival);
+ tplg_dbg("\t%s: %d", id, ival);
continue;
}
@@ -988,7 +988,7 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
snd_strlcpy(dai->dai_name, elem->id,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg(" DAI: %s\n", elem->id);
+ tplg_dbg(" DAI: %s", elem->id);
snd_config_for_each(i, next, cfg) {
@@ -1142,7 +1142,7 @@ int tplg_parse_link(snd_tplg_t *tplg,
link->size = elem->size;
snd_strlcpy(link->name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg(" Link: %s\n", elem->id);
+ tplg_dbg(" Link: %s", elem->id);
snd_config_for_each(i, next, cfg) {
@@ -1168,7 +1168,7 @@ int tplg_parse_link(snd_tplg_t *tplg,
snd_strlcpy(link->stream_name, val,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg("\t%s: %s\n", id, val);
+ tplg_dbg("\t%s: %s", id, val);
continue;
}
@@ -1280,7 +1280,7 @@ int tplg_parse_cc(snd_tplg_t *tplg,
link = elem->link;
link->size = elem->size;
- tplg_dbg(" CC: %s\n", elem->id);
+ tplg_dbg(" CC: %s", elem->id);
snd_config_for_each(i, next, cfg) {
@@ -1412,7 +1412,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
hw_cfg = elem->hw_cfg;
hw_cfg->size = elem->size;
- tplg_dbg(" Link HW config: %s\n", elem->id);
+ tplg_dbg(" Link HW config: %s", elem->id);
snd_config_for_each(i, next, cfg) {
@@ -1719,7 +1719,7 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
struct tplg_elem *elem;
int ret, i;
- tplg_dbg("PCM: %s, DAI %s\n", pcm_tpl->pcm_name, pcm_tpl->dai_name);
+ tplg_dbg("PCM: %s, DAI %s", pcm_tpl->pcm_name, pcm_tpl->dai_name);
if (pcm_tpl->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX)
return -EINVAL;
@@ -1881,7 +1881,7 @@ int tplg_add_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
struct tplg_elem *elem;
int ret, i;
- tplg_dbg("DAI %s\n", dai_tpl->dai_name);
+ tplg_dbg("DAI %s", dai_tpl->dai_name);
elem = tplg_elem_new_common(tplg, NULL, dai_tpl->dai_name,
SND_TPLG_TYPE_DAI);
diff --git a/src/topology/text.c b/src/topology/text.c
index 6dbf2230..507c5450 100644
--- a/src/topology/text.c
+++ b/src/topology/text.c
@@ -32,13 +32,13 @@ static int parse_text_values(snd_config_t *cfg, struct tplg_elem *elem)
const char *value = NULL;
int j = 0;
- tplg_dbg(" Text Values: %s\n", elem->id);
+ tplg_dbg(" Text Values: %s", elem->id);
snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i);
if (j == SND_SOC_TPLG_NUM_TEXTS) {
- tplg_dbg("text string number exceeds %d\n", j);
+ tplg_dbg("text string number exceeds %d", j);
return -ENOMEM;
}
@@ -48,7 +48,7 @@ static int parse_text_values(snd_config_t *cfg, struct tplg_elem *elem)
snd_strlcpy(&texts->items[j][0], value,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- tplg_dbg("\t%s\n", &texts->items[j][0]);
+ tplg_dbg("\t%s", &texts->items[j][0]);
j++;
}
--
2.24.1
From b20b400e2f598c86abaf697d66396cecd49b3e14 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 3 Jan 2020 22:56:48 +0100
Subject: [PATCH 57/69] topology: cosmetic changes (functions)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 3 ++-
src/topology/ctl.c | 5 +++--
src/topology/data.c | 17 +++++++++--------
src/topology/parser.c | 4 ++--
src/topology/pcm.c | 16 ++++++++--------
5 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index 7af5de08..15757668 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -71,7 +71,8 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type,
}
static int write_elem_block(snd_tplg_t *tplg,
- struct list_head *base, size_t size, int tplg_type, const char *obj_name)
+ struct list_head *base, size_t size,
+ int tplg_type, const char *obj_name)
{
struct list_head *pos, *sub_pos, *sub_base;
struct tplg_elem *elem, *elem_next;
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 41dc2ddb..b78f1c54 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -600,7 +600,7 @@ int tplg_save_control_bytes(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
/* Parse Control Enums. */
int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED)
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_enum_control *ec;
struct tplg_elem *elem;
@@ -736,7 +736,8 @@ int tplg_save_control_enum(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
* Mixer control. Supports multiple channels.
*/
int tplg_parse_control_mixer(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+ snd_config_t *cfg,
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_mixer_control *mc;
struct tplg_elem *elem;
diff --git a/src/topology/data.c b/src/topology/data.c
index 37c45919..b63e98cd 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -516,7 +516,7 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
/* get the token integer value from its id */
static int get_token_value(const char *token_id,
- struct tplg_vendor_tokens *tokens)
+ struct tplg_vendor_tokens *tokens)
{
unsigned int i;
@@ -589,7 +589,8 @@ unsigned int tplg_get_tuple_size(int type)
/* Add a tuples object to the private buffer of its parent data element */
static int copy_tuples(struct tplg_elem *elem,
- struct tplg_vendor_tuples *tuples, struct tplg_vendor_tokens *tokens)
+ struct tplg_vendor_tuples *tuples,
+ struct tplg_vendor_tokens *tokens)
{
struct snd_soc_tplg_private *priv = elem->data, *priv2;
struct tplg_tuple_set *tuple_set;
@@ -781,7 +782,7 @@ static const char *get_tuple_type_name(unsigned int type)
}
static int parse_tuple_set(snd_config_t *cfg,
- struct tplg_tuple_set **s)
+ struct tplg_tuple_set **s)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -965,7 +966,7 @@ static int tplg_save_tuple_set(struct tplg_vendor_tuples *tuples,
}
static int parse_tuple_sets(snd_config_t *cfg,
- struct tplg_vendor_tuples *tuples)
+ struct tplg_vendor_tuples *tuples)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -1033,7 +1034,7 @@ int tplg_save_tuple_sets(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
/* Parse vendor tokens
*/
int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED)
+ void *private ATTRIBUTE_UNUSED)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -1109,7 +1110,7 @@ int tplg_save_tokens(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
/* Parse vendor tuples.
*/
int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED)
+ void *private ATTRIBUTE_UNUSED)
{
snd_config_iterator_t i, next;
snd_config_t *n;
@@ -1193,7 +1194,7 @@ void tplg_free_tuples(void *obj)
/* Parse manifest's data references
*/
int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED)
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_manifest *manifest;
struct tplg_elem *elem;
@@ -1341,7 +1342,7 @@ int tplg_build_manifest_data(snd_tplg_t *tplg)
* words, tuples.
*/
int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
- void *private ATTRIBUTE_UNUSED)
+ void *private ATTRIBUTE_UNUSED)
{
snd_config_iterator_t i, next;
snd_config_t *n;
diff --git a/src/topology/parser.c b/src/topology/parser.c
index d7783a93..436e4841 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -110,8 +110,8 @@ int tplg_get_unsigned(snd_config_t *n, unsigned *val, int base)
* Parse compound
*/
int tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg,
- int (*fcn)(snd_tplg_t *, snd_config_t *, void *),
- void *private)
+ int (*fcn)(snd_tplg_t *, snd_config_t *, void *),
+ void *private)
{
const char *id;
snd_config_iterator_t i, next;
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index da88783f..61159d33 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -1124,8 +1124,8 @@ static int parse_hw_config_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
}
/* Parse a physical link element in text conf file */
-int tplg_parse_link(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+int tplg_parse_link(snd_tplg_t *tplg, snd_config_t *cfg,
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_link_config *link;
struct tplg_elem *elem;
@@ -1264,8 +1264,8 @@ int tplg_save_link(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
}
/* Parse cc */
-int tplg_parse_cc(snd_tplg_t *tplg,
- snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
+int tplg_parse_cc(snd_tplg_t *tplg, snd_config_t *cfg,
+ void *private ATTRIBUTE_UNUSED)
{
struct snd_soc_tplg_link_config *link;
struct tplg_elem *elem;
@@ -1307,8 +1307,8 @@ int tplg_parse_cc(snd_tplg_t *tplg,
/* save CC */
int tplg_save_cc(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
- struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_elem *elem,
+ char **dst, const char *pfx)
{
struct snd_soc_tplg_link_config *link = elem->link;
char pfx2[16];
@@ -1668,7 +1668,7 @@ int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
/* copy stream object */
static void tplg_add_stream_object(struct snd_soc_tplg_stream *strm,
- struct snd_tplg_stream_template *strm_tpl)
+ struct snd_tplg_stream_template *strm_tpl)
{
snd_strlcpy(strm->name, strm_tpl->name,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
@@ -1773,7 +1773,7 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
/* Set link HW config from C API template */
static int set_link_hw_config(struct snd_soc_tplg_hw_config *cfg,
- struct snd_tplg_hw_config_template *tpl)
+ struct snd_tplg_hw_config_template *tpl)
{
unsigned int i;
--
2.24.1
From 14ad963e192f101246e9b559d3b3fd41268330fb Mon Sep 17 00:00:00 2001
From: David Fries <David@Fries.net>
Date: Tue, 7 Jan 2020 09:18:10 -0600
Subject: [PATCH 58/69] mixer: Fix memory leak for more than 16 file descriptor
case
Signed-off-by: David Fries <David@Fries.net>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/mixer/mixer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c
index 82056474..b1af9945 100644
--- a/src/mixer/mixer.c
+++ b/src/mixer/mixer.c
@@ -767,7 +767,7 @@ int snd_mixer_wait(snd_mixer_t *mixer, int timeout)
if (count < 0)
return count;
if ((unsigned int) count > sizeof(spfds) / sizeof(spfds[0])) {
- pfds = malloc(count * sizeof(*pfds));
+ pfds = alloca(count * sizeof(*pfds));
if (!pfds)
return -ENOMEM;
err = snd_mixer_poll_descriptors(mixer, pfds,
--
2.24.1
From a78dd1bd1e9b47c2aee9b1e066de515b6854695a Mon Sep 17 00:00:00 2001
From: Bertware <bert.marcelis@outlook.com>
Date: Mon, 13 Jan 2020 10:21:33 +0100
Subject: [PATCH 59/69] Quote strings containing [ or ] when saving an alsa
config
Signed-off-by: Bert Marcelis <bert.marcelis@outlook.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/conf.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/conf.c b/src/conf.c
index c4db9f21..50d04034 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -1531,6 +1531,8 @@ static void string_print(char *str, int id, snd_output_t *out)
case '.':
case '{':
case '}':
+ case '[':
+ case ']':
case '\'':
case '"':
goto quoted;
--
2.24.1
From b34715004f4a1aabb85c5b9f03ba9f200638ee97 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 15 Jan 2020 09:41:05 +0100
Subject: [PATCH 60/69] ucm: fix the configuration directory (longname) for
ucm2
The new ucm2 expects that the longname directory is shared with
the driver directory. Fix that for 'Syntax 2'.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index d61124a3..b3970a13 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -1649,7 +1649,9 @@ __longname:
if (err == 0) {
/* got device-specific file that matches the card long name */
- snd_strlcpy(uc_mgr->conf_file_name, longname, sizeof(uc_mgr->conf_file_name));
+ if (uc_mgr->conf_format < 2)
+ snd_strlcpy(uc_mgr->conf_file_name, longname,
+ sizeof(uc_mgr->conf_file_name));
goto __parse;
}
}
--
2.24.1
From fe6425af751a768a2ba6cf7d430a85553d3b84f6 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 15 Jan 2020 10:31:56 +0100
Subject: [PATCH 61/69] ucm: split conf_file_name and conf_dir_name
With ucm2, the file name might differ from the directory
name. Also, allocate those fields.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/main.c | 7 ++++---
src/ucm/parser.c | 37 ++++++++++++++++++++++++++-----------
src/ucm/ucm_local.h | 4 ++--
src/ucm/ucm_subs.c | 2 +-
src/ucm/utils.c | 4 ++++
5 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/src/ucm/main.c b/src/ucm/main.c
index 61922f10..23e15bd8 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -1700,12 +1700,13 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
err = 0;
} else if (strcmp(identifier, "_file") == 0) {
/* get the conf file name of the opened card */
- if ((uc_mgr->card_name == NULL)
- || (uc_mgr->conf_file_name[0] == '\0')) {
+ if ((uc_mgr->card_name == NULL) ||
+ (uc_mgr->conf_file_name == NULL) ||
+ (uc_mgr->conf_file_name[0] == '\0')) {
err = -ENOENT;
goto __end;
}
- *value = strndup(uc_mgr->conf_file_name, MAX_FILE);
+ *value = strdup(uc_mgr->conf_file_name);
if (*value == NULL) {
err = -ENOMEM;
goto __end;
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index b3970a13..1bfde0be 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -124,6 +124,16 @@ static void configuration_filename(snd_use_case_mgr_t *uc_mgr,
configuration_filename2(fn, fn_len, 2, dir, file, suffix);
}
+/*
+ * Replace mallocated string
+ */
+static char *replace_string(char **dst, const char *value)
+{
+ free(*dst);
+ *dst = strdup(value);
+ return *dst;
+}
+
/*
* Parse string
*/
@@ -1186,7 +1196,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
/* open Verb file for reading */
configuration_filename(uc_mgr, filename, sizeof(filename),
- uc_mgr->conf_file_name, file, "");
+ uc_mgr->conf_dir_name, file, "");
err = uc_mgr_config_load(uc_mgr->conf_format, filename, &cfg);
if (err < 0) {
uc_error("error: failed to open verb file %s : %d",
@@ -1404,16 +1414,16 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
if (uc_mgr->conf_format >= 2) {
err = snd_config_search(cfg, "Syntax", &n);
if (err < 0) {
- uc_error("Syntax field not found in %s", uc_mgr->conf_file_name);
+ uc_error("Syntax field not found in %s", uc_mgr->conf_dir_name);
return -EINVAL;
}
err = snd_config_get_integer(n, &l);
if (err < 0) {
- uc_error("Syntax field is invalid in %s", uc_mgr->conf_file_name);
+ uc_error("Syntax field is invalid in %s", uc_mgr->conf_dir_name);
return err;
}
if (l < 2 || l > SYNTAX_VERSION_MAX) {
- uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_file_name);
+ uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_dir_name);
return -EINVAL;
}
/* delete this field to avoid strcmp() call in the loop */
@@ -1561,8 +1571,9 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name, char *long
return err;
_name = snd_ctl_card_info_get_name(info);
+ if (replace_string(&mgr->conf_dir_name, _name) == NULL)
+ return -ENOMEM;
_long_name = snd_ctl_card_info_get_longname(info);
- snd_strlcpy(mgr->conf_file_name, _name, sizeof(mgr->conf_file_name));
snd_strlcpy(longname, _long_name, MAX_CARD_LONG_NAME);
return 0;
@@ -1585,7 +1596,7 @@ static int load_master_config(snd_use_case_mgr_t *uc_mgr,
if (getenv(ALSA_CONFIG_UCM2_VAR) || !getenv(ALSA_CONFIG_UCM_VAR)) {
uc_mgr->conf_format = 2;
configuration_filename(uc_mgr, filename, sizeof(filename),
- uc_mgr->conf_file_name, card_name, ".conf");
+ uc_mgr->conf_dir_name, card_name, ".conf");
if (access(filename, R_OK) == 0)
goto __load;
}
@@ -1608,6 +1619,9 @@ __load:
return err;
}
+ if (replace_string(&uc_mgr->conf_file_name, card_name) == NULL)
+ return -ENOMEM;
+
return 0;
}
@@ -1632,7 +1646,8 @@ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr)
char longname[MAX_CARD_LONG_NAME];
int err;
- snd_strlcpy(uc_mgr->conf_file_name, uc_mgr->card_name, sizeof(uc_mgr->conf_file_name));
+ if (replace_string(&uc_mgr->conf_dir_name, uc_mgr->card_name) == NULL)
+ return -ENOMEM;
if (strncmp(name, "hw:", 3) == 0) {
err = get_by_card(uc_mgr, name, longname);
@@ -1650,14 +1665,14 @@ __longname:
if (err == 0) {
/* got device-specific file that matches the card long name */
if (uc_mgr->conf_format < 2)
- snd_strlcpy(uc_mgr->conf_file_name, longname,
- sizeof(uc_mgr->conf_file_name));
+ snd_strlcpy(uc_mgr->conf_dir_name, longname,
+ sizeof(uc_mgr->conf_dir_name));
goto __parse;
}
}
/* standard path */
- err = load_master_config(uc_mgr, uc_mgr->conf_file_name, &cfg, 0);
+ err = load_master_config(uc_mgr, uc_mgr->conf_dir_name, &cfg, 0);
if (err < 0)
goto __error;
@@ -1673,7 +1688,7 @@ __parse:
__error:
uc_mgr_free_ctl_list(uc_mgr);
- uc_mgr->conf_file_name[0] = '\0';
+ uc_mgr->conf_dir_name[0] = '\0';
return err;
}
diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
index ba961507..63e0f3bf 100644
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -187,7 +187,6 @@ struct use_case_verb {
/* verb transition list */
struct list_head transition_list;
- /* hardware devices that can be used with this use case */
struct list_head device_list;
/* component device list */
@@ -205,7 +204,8 @@ struct use_case_verb {
*/
struct snd_use_case_mgr {
char *card_name;
- char conf_file_name[MAX_CARD_LONG_NAME];
+ char *conf_file_name;
+ char *conf_dir_name;
char *comment;
int conf_format;
diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
index 90e395f0..d931f603 100644
--- a/src/ucm/ucm_subs.c
+++ b/src/ucm/ucm_subs.c
@@ -31,7 +31,7 @@
static char *rval_conf_name(snd_use_case_mgr_t *uc_mgr)
{
- if (uc_mgr->conf_file_name[0])
+ if (uc_mgr->conf_file_name && uc_mgr->conf_file_name[0])
return strdup(uc_mgr->conf_file_name);
return NULL;
}
diff --git a/src/ucm/utils.c b/src/ucm/utils.c
index cde1d672..daa568c1 100644
--- a/src/ucm/utils.c
+++ b/src/ucm/utils.c
@@ -441,7 +441,11 @@ void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr)
uc_mgr_free_sequence(&uc_mgr->default_list);
uc_mgr_free_value(&uc_mgr->value_list);
free(uc_mgr->comment);
+ free(uc_mgr->conf_dir_name);
+ free(uc_mgr->conf_file_name);
uc_mgr->comment = NULL;
+ uc_mgr->conf_dir_name = NULL;
+ uc_mgr->conf_file_name = NULL;
uc_mgr->active_verb = NULL;
INIT_LIST_HEAD(&uc_mgr->active_devices);
INIT_LIST_HEAD(&uc_mgr->active_modifiers);
--
2.24.1
From ebf5213cd61824b10bcaf67c570919e2a9ea0e1f Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 15 Jan 2020 10:40:01 +0100
Subject: [PATCH 62/69] ucm: remove MAX_FILE definition and use correct
PATH_MAX
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 6 +++---
src/ucm/ucm_local.h | 1 -
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index 1bfde0be..6c13fafd 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -1167,7 +1167,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
snd_config_t *n;
struct use_case_verb *verb;
snd_config_t *cfg;
- char filename[MAX_FILE];
+ char filename[PATH_MAX];
int err;
/* allocate verb */
@@ -1582,7 +1582,7 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name, char *long
static int load_master_config(snd_use_case_mgr_t *uc_mgr,
const char *card_name, snd_config_t **cfg, int longname)
{
- char filename[MAX_FILE];
+ char filename[PATH_MAX];
int err;
if (strnlen(card_name, MAX_CARD_LONG_NAME) == MAX_CARD_LONG_NAME) {
@@ -1733,7 +1733,7 @@ static int is_component_directory(const char *dir)
*/
int uc_mgr_scan_master_configs(const char **_list[])
{
- char filename[MAX_FILE], dfl[MAX_FILE];
+ char filename[PATH_MAX], dfl[PATH_MAX];
char *env = getenv(ALSA_CONFIG_UCM2_VAR);
const char **list, *d_name;
snd_config_t *cfg, *c;
diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
index 63e0f3bf..fa9fc166 100644
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -42,7 +42,6 @@
#define SYNTAX_VERSION_MAX 2
-#define MAX_FILE 256
#define MAX_CARD_SHORT_NAME 32
#define MAX_CARD_LONG_NAME 80
--
2.24.1
From fbe1ac4a09933f527aff860aad035586367f21b4 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 15 Jan 2020 10:41:35 +0100
Subject: [PATCH 63/69] topology: remove MAX_FILE definition and use correct
PATH_MAX
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/data.c | 2 +-
src/topology/tplg_local.h | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/topology/data.c b/src/topology/data.c
index b63e98cd..5742b357 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -163,7 +163,7 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)
{
struct snd_soc_tplg_private *priv = NULL;
const char *value = NULL;
- char filename[MAX_FILE];
+ char filename[PATH_MAX];
char *env = getenv(ALSA_CONFIG_TPLG_VAR);
FILE *fp;
size_t size, bytes_read;
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index e061db75..5ace0d19 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -29,7 +29,6 @@
#define tplg_dbg(fmt, arg...) do { } while (0)
#endif
-#define MAX_FILE 256
#define TPLG_MAX_PRIV_SIZE (1024 * 128)
/** The name of the environment variable containing the tplg directory */
--
2.24.1
From 7d3fec6ac68de0244621ae0aca7474d159336639 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 17 Jan 2020 18:21:08 +0100
Subject: [PATCH 64/69] ucm: parser - cosmetic fixes in the comments
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 63 ++++++++++++++++++++++++------------------------
1 file changed, 31 insertions(+), 32 deletions(-)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index 6c13fafd..6c5d2902 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -676,42 +676,41 @@ static int parse_value(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
/*
* Parse Modifier Use cases
*
- * # Each modifier is described in new section. N modifiers are allowed
- * SectionModifier."Capture Voice" {
+ * # Each modifier is described in new section. N modifiers are allowed
+ * SectionModifier."Capture Voice" {
*
- * Comment "Record voice call"
+ * Comment "Record voice call"
*
- * SupportedDevice [
- * "x"
- * "y"
- * ]
- *
- * ConflictingDevice [
- * "x"
- * "y"
- * ]
+ * SupportedDevice [
+ * "x"
+ * "y"
+ * ]
*
- * EnableSequence [
- * ....
- * ]
+ * ConflictingDevice [
+ * "x"
+ * "y"
+ * ]
*
- * DisableSequence [
- * ...
- * ]
+ * EnableSequence [
+ * ....
+ * ]
*
- * TransitionSequence."ToModifierName" [
- * ...
- * ]
+ * DisableSequence [
+ * ...
+ * ]
*
- * # Optional TQ and ALSA PCMs
- * Value {
- * TQ Voice
- * CapturePCM "hw:1"
- * PlaybackVolume "name='Master Playback Volume',index=2"
- * PlaybackSwitch "name='Master Playback Switch',index=2"
- * }
+ * TransitionSequence."ToModifierName" [
+ * ...
+ * ]
*
- * }
+ * # Optional TQ and ALSA PCMs
+ * Value {
+ * TQ Voice
+ * CapturePCM "hw:1"
+ * PlaybackVolume "name='Master Playback Volume',index=2"
+ * PlaybackSwitch "name='Master Playback Switch',index=2"
+ * }
+ * }
*
* SupportedDevice and ConflictingDevice cannot be specified together.
* Both are optional.
@@ -836,11 +835,11 @@ static int parse_modifier(snd_use_case_mgr_t *uc_mgr,
/*
* Parse Device Use Cases
*
- *# Each device is described in new section. N devices are allowed
- *SectionDevice."Headphones" {
+ * # Each device is described in new section. N devices are allowed
+ * SectionDevice."Headphones" {
* Comment "Headphones connected to 3.5mm jack"
*
- * upportedDevice [
+ * SupportedDevice [
* "x"
* "y"
* ]
--
2.24.1
From b2fe99277a73ec80eac0bd221672dd4aa02defa7 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen <tanuk@iki.fi>
Date: Fri, 20 Dec 2019 09:26:12 +0200
Subject: [PATCH 65/69] configure.ac: remove an unnecessary libtool fix
This code was added in commit 75d393a563efb578c79364a277087c6326267f52
without explaining why. I assume it was a mistake, since it looks like
the libtool problem should have gone away a long time ago. The referenced
wiki page https://wiki.debian.org/RpathIssue says:
Since libtool 1.5.2 (released 2004-01-25), on Linux libtool no
longer sets RPATH for any directories in the dynamic linker search
path, so this should no longer be an issue unless upstream used a
really old version of libtool when creating their distribution
tarball.
This code caused problems in OpenEmbedded, where the libtool script is
named "x86_64-oe-linux-libtool" or similar rather than just "libtool",
so the sed command failed with a file not found error. Rather than
adapting the code to OpenEmbedded's peculiarities, it seems best to just
remove the unnecessary code altogether.
Note: The rpath is set (hardcoded) for 'make' but it is corrected
for 'make install' by libtool.
Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
configure.ac | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/configure.ac b/configure.ac
index 886f87bc..fb60c030 100644
--- a/configure.ac
+++ b/configure.ac
@@ -765,14 +765,3 @@ test "$build_seq" = "yes" && echo "#include <alsa/seq.h>" >> include/asoundlib.h
test "$build_seq" = "yes" && echo "#include <alsa/seqmid.h>" >> include/asoundlib.h
test "$build_seq" = "yes" && echo "#include <alsa/seq_midi_event.h>" >> include/asoundlib.h
cat "$srcdir"/include/asoundlib-tail.h >> include/asoundlib.h
-
-dnl Taken from https://wiki.debian.org/RpathIssue
-case $host in
- *-*-linux-gnu)
- AC_MSG_RESULT([Fixing libtool for -rpath problems.])
- sed < libtool > libtool-2 \
- 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_IS_A_FOOL__ "/'
- mv libtool-2 libtool
- chmod 755 libtool
- ;;
-esac
--
2.24.1
From c5a09b0feaf759957dfac2c797b652781a0d41fe Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 3 Feb 2020 14:44:13 +0100
Subject: [PATCH 66/69] ucm: parser - use correct filename in
parser_master_file()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index 6c5d2902..dbbd3817 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -1413,16 +1413,16 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
if (uc_mgr->conf_format >= 2) {
err = snd_config_search(cfg, "Syntax", &n);
if (err < 0) {
- uc_error("Syntax field not found in %s", uc_mgr->conf_dir_name);
+ uc_error("Syntax field not found in %s", uc_mgr->conf_file_name);
return -EINVAL;
}
err = snd_config_get_integer(n, &l);
if (err < 0) {
- uc_error("Syntax field is invalid in %s", uc_mgr->conf_dir_name);
+ uc_error("Syntax field is invalid in %s", uc_mgr->conf_file_name);
return err;
}
if (l < 2 || l > SYNTAX_VERSION_MAX) {
- uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_dir_name);
+ uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_file_name);
return -EINVAL;
}
/* delete this field to avoid strcmp() call in the loop */
--
2.24.1
From 71a1367bcabc50f99302d8c76395f1cb84975775 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 3 Feb 2020 15:24:19 +0100
Subject: [PATCH 67/69] ucm: the ucm2/ subdirectory is driver name based
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index dbbd3817..f576fde4 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -1515,7 +1515,7 @@ static int get_card_long_name(snd_use_case_mgr_t *mgr, char *longname)
int card, err;
snd_ctl_t *ctl;
snd_ctl_card_info_t *info;
- const char *_name, *_long_name;
+ const char *_driver, *_name, *_long_name;
snd_ctl_card_info_alloca(&info);
@@ -1535,9 +1535,11 @@ static int get_card_long_name(snd_use_case_mgr_t *mgr, char *longname)
err = get_card_info(mgr, name, &ctl, info);
if (err == 0) {
+ _driver = snd_ctl_card_info_get_driver(info);
_name = snd_ctl_card_info_get_name(info);
_long_name = snd_ctl_card_info_get_longname(info);
- if (!strcmp(card_name, _name) ||
+ if (!strcmp(card_name, _driver) ||
+ !strcmp(card_name, _name) ||
!strcmp(card_name, _long_name)) {
snd_strlcpy(longname, _long_name, MAX_CARD_LONG_NAME);
return 0;
@@ -1560,7 +1562,7 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name, char *long
{
snd_ctl_t *ctl;
snd_ctl_card_info_t *info;
- const char *_name, *_long_name;
+ const char *_driver, *_long_name;
int err;
snd_ctl_card_info_alloca(&info);
@@ -1569,8 +1571,8 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name, char *long
if (err)
return err;
- _name = snd_ctl_card_info_get_name(info);
- if (replace_string(&mgr->conf_dir_name, _name) == NULL)
+ _driver = snd_ctl_card_info_get_driver(info);
+ if (replace_string(&mgr->conf_dir_name, _driver) == NULL)
return -ENOMEM;
_long_name = snd_ctl_card_info_get_longname(info);
snd_strlcpy(longname, _long_name, MAX_CARD_LONG_NAME);
--
2.24.1
From 251bc204a1e7f1bf1d12b452f2b62e15543bba94 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 7 Feb 2020 10:09:07 +0100
Subject: [PATCH 68/69] ucm: implement RenameDevice and RemoveDevice verb
management
With the conditionals, it may be useful to define the devices
in the included configuration files. To satisfy the specification
requirements (device naming) those device names might require
to be renamed or deleted wrong references from the conflicting
or supported lists.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 129 +++++++++++++++++++++++++++++++++++++++++++-
src/ucm/ucm_local.h | 15 ++++++
src/ucm/utils.c | 123 +++++++++++++++++++++++++++++++++++++-----
3 files changed, 254 insertions(+), 13 deletions(-)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index f576fde4..f9a8f628 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -985,6 +985,71 @@ static int parse_device(snd_use_case_mgr_t *uc_mgr,
return 0;
}
+/*
+ * Parse Device Rename/Delete Command
+ *
+ * # The devices might be renamed to allow the better conditional runtime
+ * # evaluation. Bellow example renames Speaker1 device to Speaker and
+ * # removes Speaker2 device.
+ * RenameDevice."Speaker1" "Speaker"
+ * RemoveDevice."Speaker2" "Speaker2"
+ */
+static int parse_dev_name_list(snd_config_t *cfg,
+ struct list_head *list)
+{
+ snd_config_t *n;
+ snd_config_iterator_t i, next;
+ const char *id, *name1;
+ char *name2;
+ struct ucm_dev_name *dev;
+ snd_config_iterator_t pos;
+ int err;
+
+ if (snd_config_get_id(cfg, &id) < 0)
+ return -EINVAL;
+
+ if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
+ uc_error("compound type expected for %s", id);
+ return -EINVAL;
+ }
+
+ snd_config_for_each(i, next, cfg) {
+ n = snd_config_iterator_entry(i);
+
+ if (snd_config_get_id(n, &name1) < 0)
+ return -EINVAL;
+
+ err = parse_string(n, &name2);
+ if (err < 0) {
+ uc_error("error: failed to get target device name for '%s'", name1);
+ return err;
+ }
+
+ /* skip duplicates */
+ list_for_each(pos, list) {
+ dev = list_entry(pos, struct ucm_dev_name, list);
+ if (strcmp(dev->name1, name1) == 0) {
+ free(name2);
+ return 0;
+ }
+ }
+
+ dev = calloc(1, sizeof(*dev));
+ if (dev == NULL)
+ return -ENOMEM;
+ dev->name1 = strdup(name1);
+ if (dev->name1 == NULL) {
+ free(dev);
+ free(name2);
+ return -ENOMEM;
+ }
+ dev->name2 = name2;
+ list_add_tail(&dev->list, list);
+ }
+
+ return 0;
+}
+
static int parse_compound_check_legacy(snd_use_case_mgr_t *uc_mgr,
snd_config_t *cfg,
int (*fcn)(snd_use_case_mgr_t *, snd_config_t *, void *, void *),
@@ -1044,7 +1109,39 @@ static int parse_modifier_name(snd_use_case_mgr_t *uc_mgr,
void *data1,
void *data2 ATTRIBUTE_UNUSED)
{
- return parse_compound_check_legacy(uc_mgr, cfg, parse_modifier, data1);
+ return parse_compound(uc_mgr, cfg, parse_modifier, data1, data2);
+}
+
+static int verb_device_management(struct use_case_verb *verb)
+{
+ struct list_head *pos;
+ struct ucm_dev_name *dev;
+ int err;
+
+ /* rename devices */
+ list_for_each(pos, &verb->rename_list) {
+ dev = list_entry(pos, struct ucm_dev_name, list);
+ err = uc_mgr_rename_device(verb, dev->name1, dev->name2);
+ if (err < 0) {
+ uc_error("error: cannot rename device '%s' to '%s'", dev->name1, dev->name2);
+ return err;
+ }
+ }
+
+ /* remove devices */
+ list_for_each(pos, &verb->rename_list) {
+ dev = list_entry(pos, struct ucm_dev_name, list);
+ err = uc_mgr_remove_device(verb, dev->name2);
+ if (err < 0) {
+ uc_error("error: cannot remove device '%s'", dev->name2);
+ return err;
+ }
+ }
+
+ /* those lists are no longer used */
+ uc_mgr_free_dev_name_list(&verb->rename_list);
+ uc_mgr_free_dev_name_list(&verb->remove_list);
+ return 0;
}
/*
@@ -1180,6 +1277,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
INIT_LIST_HEAD(&verb->cmpt_device_list);
INIT_LIST_HEAD(&verb->modifier_list);
INIT_LIST_HEAD(&verb->value_list);
+ INIT_LIST_HEAD(&verb->rename_list);
+ INIT_LIST_HEAD(&verb->remove_list);
list_add_tail(&verb->list, &uc_mgr->verb_list);
if (use_case_name == NULL)
return -EINVAL;
@@ -1249,6 +1348,26 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
}
continue;
}
+
+ /* device renames */
+ if (strcmp(id, "RenameDevice") == 0) {
+ err = parse_dev_name_list(n, &verb->rename_list);
+ if (err < 0) {
+ uc_error("error: %s failed to parse device rename",
+ file);
+ goto _err;
+ }
+ }
+
+ /* device remove */
+ if (strcmp(id, "RemoveDevice") == 0) {
+ err = parse_dev_name_list(n, &verb->remove_list);
+ if (err < 0) {
+ uc_error("error: %s failed to parse device remove",
+ file);
+ goto _err;
+ }
+ }
}
snd_config_delete(cfg);
@@ -1258,6 +1377,14 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
uc_error("error: no use case device defined", file);
return -EINVAL;
}
+
+ /* do device rename and delete */
+ err = verb_device_management(verb);
+ if (err < 0) {
+ uc_error("error: device management error in verb '%s'", verb->name);
+ return err;
+ }
+
return 0;
_err:
diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
index fa9fc166..ba8d2acb 100644
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -117,6 +117,12 @@ struct ctl_list {
snd_ctl_card_info_t *ctl_info;
};
+struct ucm_dev_name {
+ struct list_head list;
+ char *name1;
+ char *name2;
+};
+
/*
* Describes a Use Case Modifier and it's enable and disable sequences.
* A use case verb can have N modifiers.
@@ -196,6 +202,10 @@ struct use_case_verb {
/* value list */
struct list_head value_list;
+
+ /* temporary modifications lists */
+ struct list_head rename_list;
+ struct list_head remove_list;
};
/*
@@ -252,6 +262,11 @@ int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg);
int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr);
int uc_mgr_scan_master_configs(const char **_list[]);
+int uc_mgr_remove_device(struct use_case_verb *verb, const char *name);
+int uc_mgr_rename_device(struct use_case_verb *verb, const char *src,
+ const char *dst);
+
+void uc_mgr_free_dev_name_list(struct list_head *base);
void uc_mgr_free_sequence_element(struct sequence_element *seq);
void uc_mgr_free_transition_element(struct transition_sequence *seq);
void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr);
diff --git a/src/ucm/utils.c b/src/ucm/utils.c
index daa568c1..60a59172 100644
--- a/src/ucm/utils.c
+++ b/src/ucm/utils.c
@@ -328,6 +328,44 @@ void uc_mgr_free_dev_list(struct dev_list *dev_list)
}
}
+int uc_mgr_rename_in_dev_list(struct dev_list *dev_list, const char *src,
+ const char *dst)
+{
+ struct list_head *pos;
+ struct dev_list_node *dlist;
+ char *dst1;
+
+ list_for_each(pos, &dev_list->list) {
+ dlist = list_entry(pos, struct dev_list_node, list);
+ if (strcmp(dlist->name, src) == 0) {
+ dst1 = strdup(dst);
+ if (dst1 == NULL)
+ return -ENOMEM;
+ free(dlist->name);
+ dlist->name = dst1;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+int uc_mgr_remove_from_dev_list(struct dev_list *dev_list, const char *name)
+{
+ struct list_head *pos;
+ struct dev_list_node *dlist;
+
+ list_for_each(pos, &dev_list->list) {
+ dlist = list_entry(pos, struct dev_list_node, list);
+ if (strcmp(dlist->name, name) == 0) {
+ free(dlist->name);
+ list_del(&dlist->list);
+ free(dlist);
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+
void uc_mgr_free_sequence_element(struct sequence_element *seq)
{
if (seq == NULL)
@@ -381,6 +419,20 @@ void uc_mgr_free_transition(struct list_head *base)
}
}
+void uc_mgr_free_dev_name_list(struct list_head *base)
+{
+ struct list_head *pos, *npos;
+ struct ucm_dev_name *dev;
+
+ list_for_each_safe(pos, npos, base) {
+ dev = list_entry(pos, struct ucm_dev_name, list);
+ list_del(&dev->list);
+ free(dev->name1);
+ free(dev->name2);
+ free(dev);
+ }
+}
+
void uc_mgr_free_modifier(struct list_head *base)
{
struct list_head *pos, *npos;
@@ -400,23 +452,68 @@ void uc_mgr_free_modifier(struct list_head *base)
}
}
-void uc_mgr_free_device(struct list_head *base)
+void uc_mgr_free_device(struct use_case_device *dev)
+{
+ free(dev->name);
+ free(dev->comment);
+ uc_mgr_free_sequence(&dev->enable_list);
+ uc_mgr_free_sequence(&dev->disable_list);
+ uc_mgr_free_transition(&dev->transition_list);
+ uc_mgr_free_dev_list(&dev->dev_list);
+ uc_mgr_free_value(&dev->value_list);
+ list_del(&dev->list);
+ free(dev);
+}
+
+void uc_mgr_free_device_list(struct list_head *base)
{
struct list_head *pos, *npos;
struct use_case_device *dev;
list_for_each_safe(pos, npos, base) {
dev = list_entry(pos, struct use_case_device, list);
- free(dev->name);
- free(dev->comment);
- uc_mgr_free_sequence(&dev->enable_list);
- uc_mgr_free_sequence(&dev->disable_list);
- uc_mgr_free_transition(&dev->transition_list);
- uc_mgr_free_dev_list(&dev->dev_list);
- uc_mgr_free_value(&dev->value_list);
- list_del(&dev->list);
- free(dev);
+ uc_mgr_free_device(dev);
+ }
+}
+
+int uc_mgr_rename_device(struct use_case_verb *verb, const char *src,
+ const char *dst)
+{
+ struct use_case_device *device;
+ struct list_head *pos, *npos;
+ char *dst1;
+
+ /* no errors when device is not found */
+ list_for_each_safe(pos, npos, &verb->device_list) {
+ device = list_entry(pos, struct use_case_device, list);
+ if (strcmp(device->name, src) == 0) {
+ dst1 = strdup(dst);
+ if (dst1 == NULL)
+ return -ENOMEM;
+ free(device->name);
+ device->name = dst1;
+ continue;
+ }
+ uc_mgr_rename_in_dev_list(&device->dev_list, src, dst);
+ }
+ return 0;
+}
+
+int uc_mgr_remove_device(struct use_case_verb *verb, const char *name)
+{
+ struct use_case_device *device;
+ struct list_head *pos, *npos;
+
+ list_for_each_safe(pos, npos, &verb->device_list) {
+ device = list_entry(pos, struct use_case_device, list);
+ if (strcmp(device->name, name) == 0) {
+ uc_mgr_free_device(device);
+ continue;
+ }
+ uc_mgr_remove_from_dev_list(&device->dev_list, name);
+ return 0;
}
+ return -ENOENT;
}
void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr)
@@ -432,9 +529,11 @@ void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr)
uc_mgr_free_sequence(&verb->disable_list);
uc_mgr_free_transition(&verb->transition_list);
uc_mgr_free_value(&verb->value_list);
- uc_mgr_free_device(&verb->device_list);
- uc_mgr_free_device(&verb->cmpt_device_list);
+ uc_mgr_free_device_list(&verb->device_list);
+ uc_mgr_free_device_list(&verb->cmpt_device_list);
uc_mgr_free_modifier(&verb->modifier_list);
+ uc_mgr_free_dev_name_list(&verb->rename_list);
+ uc_mgr_free_dev_name_list(&verb->remove_list);
list_del(&verb->list);
free(verb);
}
--
2.24.1
From fdf96312fa3c9261db2954afcde8c6a15d2ebe44 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 7 Feb 2020 16:18:11 +0100
Subject: [PATCH 69/69] ucm: fill missing device entries (conflicting /
supported)
It is not necessary to maintain this information in sync in the configuration
files. Fill the missing entries to the complementary devices.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 50 ++++++++++++++++++++++++++++++++++++++++++++-
src/ucm/ucm_local.h | 1 +
src/ucm/utils.c | 25 +++++++++++++++++++++++
3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index f9a8f628..23bf6a63 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -1112,6 +1112,52 @@ static int parse_modifier_name(snd_use_case_mgr_t *uc_mgr,
return parse_compound(uc_mgr, cfg, parse_modifier, data1, data2);
}
+static int verb_dev_list_add(struct use_case_verb *verb,
+ enum dev_list_type dst_type,
+ const char *dst,
+ const char *src)
+{
+ struct use_case_device *device;
+ struct list_head *pos;
+
+ list_for_each(pos, &verb->device_list) {
+ device = list_entry(pos, struct use_case_device, list);
+ if (strcmp(device->name, dst) != 0)
+ continue;
+ if (device->dev_list.type != dst_type) {
+ if (list_empty(&device->dev_list.list)) {
+ device->dev_list.type = dst_type;
+ } else {
+ uc_error("error: incompatible device list type ('%s', '%s')",
+ device->name, src);
+ return -EINVAL;
+ }
+ }
+ return uc_mgr_put_to_dev_list(&device->dev_list, src);
+ }
+ return -ENOENT;
+}
+
+static int verb_dev_list_check(struct use_case_verb *verb)
+{
+ struct list_head *pos, *pos2;
+ struct use_case_device *device;
+ struct dev_list_node *dlist;
+ int err;
+
+ list_for_each(pos, &verb->device_list) {
+ device = list_entry(pos, struct use_case_device, list);
+ list_for_each(pos2, &device->dev_list.list) {
+ dlist = list_entry(pos2, struct dev_list_node, list);
+ err = verb_dev_list_add(verb, device->dev_list.type,
+ dlist->name, device->name);
+ if (err < 0)
+ return err;
+ }
+ }
+ return 0;
+}
+
static int verb_device_management(struct use_case_verb *verb)
{
struct list_head *pos;
@@ -1141,7 +1187,9 @@ static int verb_device_management(struct use_case_verb *verb)
/* those lists are no longer used */
uc_mgr_free_dev_name_list(&verb->rename_list);
uc_mgr_free_dev_name_list(&verb->remove_list);
- return 0;
+
+ /* handle conflicting/supported lists */
+ return verb_dev_list_check(verb);
}
/*
diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
index ba8d2acb..acec4bf6 100644
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -262,6 +262,7 @@ int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg);
int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr);
int uc_mgr_scan_master_configs(const char **_list[]);
+int uc_mgr_put_to_dev_list(struct dev_list *dev_list, const char *name);
int uc_mgr_remove_device(struct use_case_verb *verb, const char *name);
int uc_mgr_rename_device(struct use_case_verb *verb, const char *src,
const char *dst);
diff --git a/src/ucm/utils.c b/src/ucm/utils.c
index 60a59172..50b2a1df 100644
--- a/src/ucm/utils.c
+++ b/src/ucm/utils.c
@@ -328,6 +328,31 @@ void uc_mgr_free_dev_list(struct dev_list *dev_list)
}
}
+int uc_mgr_put_to_dev_list(struct dev_list *dev_list, const char *name)
+{
+ struct list_head *pos;
+ struct dev_list_node *dlist;
+ char *n;
+
+ list_for_each(pos, &dev_list->list) {
+ dlist = list_entry(pos, struct dev_list_node, list);
+ if (strcmp(dlist->name, name) == 0)
+ return 0;
+ }
+
+ dlist = calloc(1, sizeof(*dlist));
+ if (dlist == NULL)
+ return -ENOMEM;
+ n = strdup(name);
+ if (n == NULL) {
+ free(dlist);
+ return -ENOMEM;
+ }
+ dlist->name = n;
+ list_add(&dlist->list, &dev_list->list);
+ return 0;
+}
+
int uc_mgr_rename_in_dev_list(struct dev_list *dev_list, const char *src,
const char *dst)
{
--
2.24.1