alsa/0003-ucm-add-_identifiers-list.patch

354 lines
10 KiB
Diff
Raw Normal View History

Accepting request 758564 from home:tiwai:branches:multimedia:libs - Upstream fixes, including the alsa-tools build breakage: 0001-ucm-Use-strncmp-to-avoid-access-out-of-boundary.patch 0002-ucm-return-always-at-least-NULL-if-no-list-is-availa.patch 0003-ucm-add-_identifiers-list.patch 0004-namehint-correct-the-args-check.patch 0005-namehint-improve-the-previous-patch-check-the-return.patch 0006-ucm-docs-allow-spaces-in-device-names-for-JackHWMute.patch 0007-use-case-docs-add-PlaybackMixerCopy-and-CaptureMixer.patch 0008-ucm-docs-add-JackCTL-rearrange-JackControl-and-JackD.patch 0009-ucm-Do-not-fail-to-parse-configs-on-cards-with-an-em.patch 0010-src-ucm-main.c-fix-build-without-mixer.patch 0011-alsa.m4-another-try-to-fix-the-libatopology-detectio.patch 0012-ucm-docs-add-Mic-DigitalMic-and-multiple-devices-com.patch 0013-ucm-docs-remove-DigitalMic-it-does-not-have-sense.patch 0014-ucm-docs-change-the-Mic-description-to-simple-Microp.patch 0015-ucm-docs-add-note-about-the-sequences-and-device-spl.patch 0016-ucm-docs-remove-MixerCopy-values-add-Priority-for-ve.patch 0017-ucm-setup-conf_format-after-getting-ALSA_CONFIG_UCM_.patch 0018-alsa-lib-fix-the-array-parser-unique-compound-keys.patch 0019-topology-remove-vendor_fd-name-from-snd_tplg-structu.patch 0020-topology-file-position-and-size-cleanups.patch 0021-topology-use-an-array-describing-blocks-for-the-main.patch 0022-topology-use-size_t-for-calc_block_size.patch 0023-topology-merge-write_block-to-tplg_write_data.patch 0024-topology-make-vebose-output-more-nice.patch 0025-topology-use-list_insert-macro-in-tplg_elem_insert.patch 0026-topology-dapm-coding-fixes.patch 0027-topology-dapm-merge-identical-index-blocks-like-for-.patch 0028-topology-more-coding-fixes.patch 0029-Fix-alsa-sound-.h-for-external-programs.patch OBS-URL: https://build.opensuse.org/request/show/758564 OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=263
2019-12-20 16:28:33 +00:00
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/30] 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 8e7e838c9cb9..85c58ac0614a 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 b80db65fa93b..d2078a2381d3 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.16.4