Accepting request 838541 from multimedia:libs

- Enable topology support for aarch64

- Backport upstream fixes:
  0001-ucm-substitution-remove-duplicate-allow_empty-assign.patch
  0002-ucm-fix-parse_get_safe_name-safe-name-must-be-checke.patch
  0003-ucm-substitute-the-merged-tree-completely.patch
  0004-ctl-improve-documentation-for-identifier-of-control-.patch
  0005-pcm-dmix-make-lockless-operation-optional.patch
  0006-pcm-dmix-Fix-semaphore-usage-with-lockless-operation.patch
  0007-pcm-iec958-implement-HDMI-HBR-audio-formatting.patch
  0008-pcm-iec958-set-channel-status-bits-according-to-rate.patch
  0009-conf-pcm-USB-Added-S-PDIF-fix-for-Asus-Xonar-SE.patch
  0010-control-ctlparse-fix-enum-values-in-or.patch
  0011-conf-USB-Audio-Disable-IEC958-on-Lenovo-ThinkStation.patch
  0012-pcm-dmix-fix-access-to-sum-buffer-in-non-interleaved.patch
  0014-control-Add-documentation-for-snd_ctl_elem_list_.patch
  0015-conf-quote-also-strings-with-and-characters-in-strin.patch
  0016-topology-decode-Fix-channel-map-memory-allocation.patch
  0017-topology-decode-Fix-infinite-loop-in-decoding-enum-c.patch
  0018-topology-decode-Remove-decoding-values-for-enum-cont.patch
  0019-topology-decode-Add-enum-control-texts-as-separate-e.patch
  0020-topology-decode-Fix-printing-texts-section.patch
  0021-topology-decode-Change-declaration-of-enum-decoding-.patch
  0022-topology-decode-Fix-decoding-PCM-formats-and-rates.patch
  0023-topology-decode-Print-sig_bits-field-in-PCM-capabili.patch
  0024-topology-decode-Add-DAI-name-printing.patch
  0025-topology-Make-buffer-for-saving-dynamic-size.patch
  0026-topology-return-correct-value-in-tplg_save_printf.patch
  0027-topology-fix-some-gcc10-warnings-labs-signess.patch
  0028-topology-fix-sort_config.patch

OBS-URL: https://build.opensuse.org/request/show/838541
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/alsa?expand=0&rev=204
This commit is contained in:
Dominique Leuenberger 2020-10-03 16:56:27 +00:00 committed by Git OBS Bridge
commit 5e9a347d3f
33 changed files with 3793 additions and 0 deletions

View File

@ -0,0 +1,36 @@
From 485930ea5dc8a14e0d215de44557372ca41b15f4 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 30 Jun 2020 09:22:12 +0200
Subject: [PATCH 01/32] ucm: substitution - remove duplicate allow_empty
assignment
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/ucm_subs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
index a154aa510ee8..d40e5478b084 100644
--- a/src/ucm/ucm_subs.c
+++ b/src/ucm/ucm_subs.c
@@ -303,7 +303,6 @@ __std:
} else if (value[1] != '{') {
goto __std;
}
- allow_empty = false;
fcn2 = NULL;
MATCH_VARIABLE(value, "${OpenName}", rval_open_name, false);
MATCH_VARIABLE(value, "${ConfTopDir}", rval_conf_topdir, false);
@@ -365,7 +364,8 @@ __rval:
}
strncpy(r, value, idsize);
r[idsize] = '\0';
- uc_error("variable '%s' is not defined in this context!", r);
+ uc_error("variable '%s' is %s in this context!", r,
+ rval ? "empty" : "not defined");
err = -EINVAL;
goto __error;
}
--
2.16.4

View File

@ -0,0 +1,35 @@
From 30d12e930cfcba777a29af502a9c1dbfa5e37c04 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Fri, 3 Jul 2020 14:48:18 +0200
Subject: [PATCH 02/32] ucm: fix parse_get_safe_name() - safe name must be
checked after substitution
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/parser.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index 3b7fc931362f..d034b8598a85 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -234,9 +234,14 @@ int parse_get_safe_name(snd_use_case_mgr_t *uc_mgr, snd_config_t *n,
if (err < 0)
return err;
}
- if (!parse_is_name_safe(id))
+ err = get_string3(uc_mgr, id, name);
+ if (err < 0)
+ return err;
+ if (!parse_is_name_safe(*name)) {
+ free(*name);
return -EINVAL;
- return get_string3(uc_mgr, id, name);
+ }
+ return 0;
}
/*
--
2.16.4

View File

@ -0,0 +1,147 @@
From 32addac948a61c4770f9cdf459fa29879602df38 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 6 Jul 2020 16:34:33 +0200
Subject: [PATCH 03/32] ucm: substitute the merged tree completely
We need to define the common shared configuration like for multiple
HDMI devices or so. Substitute the whole merged configuration tree
including identifiers.
Fixes: https://github.com/alsa-project/alsa-lib/issues/67
Fixes: https://github.com/alsa-project/alsa-ucm-conf/commit/dcef48f13d4f5db79b006755074940b94730a883
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/ucm/ucm_cond.c | 2 +-
src/ucm/ucm_include.c | 9 +++++++--
src/ucm/ucm_local.h | 6 +++++-
src/ucm/ucm_subs.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/src/ucm/ucm_cond.c b/src/ucm/ucm_cond.c
index cc4915396d71..3ca3096e0b19 100644
--- a/src/ucm/ucm_cond.c
+++ b/src/ucm/ucm_cond.c
@@ -401,7 +401,7 @@ int uc_mgr_evaluate_condition(snd_use_case_mgr_t *uc_mgr,
err = uc_mgr_evaluate_inplace(uc_mgr, a);
if (err < 0)
return err;
- err = uc_mgr_config_tree_merge(parent, a, before, after);
+ err = uc_mgr_config_tree_merge(uc_mgr, parent, a, before, after);
if (err < 0)
return err;
snd_config_delete(a);
diff --git a/src/ucm/ucm_include.c b/src/ucm/ucm_include.c
index c69490f49c6e..94ae944d2001 100644
--- a/src/ucm/ucm_include.c
+++ b/src/ucm/ucm_include.c
@@ -206,7 +206,8 @@ static int compound_merge(const char *id,
return 0;
}
-int uc_mgr_config_tree_merge(snd_config_t *parent, snd_config_t *new_ctx,
+int uc_mgr_config_tree_merge(snd_use_case_mgr_t *uc_mgr,
+ snd_config_t *parent, snd_config_t *new_ctx,
snd_config_t *before, snd_config_t *after)
{
snd_config_iterator_t i, next;
@@ -214,6 +215,10 @@ int uc_mgr_config_tree_merge(snd_config_t *parent, snd_config_t *new_ctx,
const char *id;
int err;
+ err = uc_mgr_substitute_tree(uc_mgr, new_ctx);
+ if (err < 0)
+ return err;
+
snd_config_for_each(i, next, new_ctx) {
n = snd_config_iterator_entry(i);
err = snd_config_remove(n);
@@ -271,7 +276,7 @@ int uc_mgr_evaluate_include(snd_use_case_mgr_t *uc_mgr,
err = uc_mgr_evaluate_inplace(uc_mgr, a);
if (err < 0)
return err;
- err = uc_mgr_config_tree_merge(parent, a, before, after);
+ err = uc_mgr_config_tree_merge(uc_mgr, parent, a, before, after);
if (err < 0)
return err;
snd_config_delete(a);
diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h
index 709f4cbd5a20..dd72e3f55f95 100644
--- a/src/ucm/ucm_local.h
+++ b/src/ucm/ucm_local.h
@@ -307,7 +307,11 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr,
char **_rvalue,
const char *value);
-int uc_mgr_config_tree_merge(snd_config_t *parent, snd_config_t *new_ctx,
+int uc_mgr_substitute_tree(snd_use_case_mgr_t *uc_mgr,
+ snd_config_t *node);
+
+int uc_mgr_config_tree_merge(snd_use_case_mgr_t *uc_mgr,
+ snd_config_t *parent, snd_config_t *new_ctx,
snd_config_t *before, snd_config_t *after);
int uc_mgr_evaluate_inplace(snd_use_case_mgr_t *uc_mgr,
diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
index d40e5478b084..f608bb0955a6 100644
--- a/src/ucm/ucm_subs.c
+++ b/src/ucm/ucm_subs.c
@@ -395,3 +395,56 @@ __error:
free(r);
return err;
}
+
+static inline int uc_mgr_substitute_check(const char *s)
+{
+ return s && strstr(s, "${") != NULL;
+}
+
+int uc_mgr_substitute_tree(snd_use_case_mgr_t *uc_mgr, snd_config_t *node)
+{
+ snd_config_iterator_t i, next;
+ snd_config_t *n;
+ const char *id, *s2;
+ char *s;
+ int err;
+
+ err = snd_config_get_id(node, &id);
+ if (err < 0)
+ return err;
+ if (uc_mgr_substitute_check(id)) {
+ err = uc_mgr_get_substituted_value(uc_mgr, &s, id);
+ if (err < 0)
+ return err;
+ err = snd_config_set_id(node, s);
+ free(s);
+ if (err < 0) {
+ uc_error("unable to set substituted id '%s' (old id '%s')", s, id);
+ return err;
+ }
+ }
+ if (snd_config_get_type(node) != SND_CONFIG_TYPE_COMPOUND) {
+ if (snd_config_get_type(node) == SND_CONFIG_TYPE_STRING) {
+ err = snd_config_get_string(node, &s2);
+ if (err < 0)
+ return err;
+ if (!uc_mgr_substitute_check(s2))
+ return 0;
+ err = uc_mgr_get_substituted_value(uc_mgr, &s, s2);
+ if (err < 0)
+ return err;
+ err = snd_config_set_string(node, s);
+ free(s);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+ }
+ snd_config_for_each(i, next, node) {
+ n = snd_config_iterator_entry(i);
+ err = uc_mgr_substitute_tree(uc_mgr, n);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
--
2.16.4

View File

@ -0,0 +1,36 @@
From 877bdf95fdfdac840a7a664362ec69b85c59ecb0 Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Fri, 3 Jul 2020 09:37:51 +0900
Subject: [PATCH 04/32] ctl: improve documentation for identifier of control
element
In documentation, there're two ways relevant to the identifier of control
element. However, the case of combination has the lack of parameters.
This commit improves documentation in this point.
Fixes: f3c24de8c0df ("ctl: add an overview for design of ALSA control interface")
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/control/control.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/control/control.c b/src/control/control.c
index 19528ae30a0b..e21e8f1d2621 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -49,8 +49,8 @@ are managed according to below model.
- An element includes some members to have a value. The value of each member
can be changed by both of userspace applications and drivers in kernel.
-Each element can be identified by two ways; a combination of name and index, or
-numerical number (numid).
+Each element can be identified by two ways; the numerical number (numid), or the
+combination of interface, device, subdevice, name, and index.
The type of element set is one of integer, integerr64, boolean, enumerators,
bytes and IEC958 structure. This indicates the type of value for each member in
--
2.16.4

View File

@ -0,0 +1,107 @@
From 4759865c861c708ce4a68fc08060fc820628ccaf Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 19 Jun 2020 18:57:05 +0200
Subject: [PATCH 05/32] pcm: dmix: make lockless operation optional
The recently reported (but a long-standing) bug about the
unconditional semaphore usage in the dmix implies that basically we've
had no problem with the locking in the practical usages over years.
Although the lockless operation has a clear merit, it's a much higher
CPU usage (especially on some uncached pages), and it might lead to a
potential deadlock in theory (which is hard to reproduce at will,
though).
This patch introduces a new configure option "--enable-lockless-dmix"
or "--disable-lockless-dmix" to let user choose the default dmix
operation mode. The usage of the lockless mixing has been already
conditionally enabled via asoundrc and card config
"direct_memory_access", so we just need to set the default value based
on it.
In this patch, the default is set off to the lockless mixing, i.e. the
generic mixing is chosen. It makes more sense from the performance
POV. For any users who still require the lockless operation, it can
be enabled either via configure option or the asoundrc.
The magic number used in the shmem is also changed depending on the
operation mode. It's just for safety, not to conflict both operation
modes with each other.
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
configure.ac | 13 +++++++++++++
src/pcm/pcm_direct.c | 16 +++++++++++++---
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index 93a54c909d1d..01357fb9310f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -629,6 +629,19 @@ if test "$build_pcm_mmap_emul" = "yes"; then
AC_DEFINE([BUILD_PCM_PLUGIN_MMAP_EMUL], "1", [Build PCM mmap-emul plugin])
fi
+if test "$build_pcm_dmix" = "yes"; then
+AC_MSG_CHECKING(for default lockless dmix)
+AC_ARG_ENABLE(lockless-dmix,
+ AS_HELP_STRING([--enable-lockless-dmix],
+ [use lockless dmix as default on x86]),
+ lockless_dmix="$enableval", lockless_dmix="no")
+if test "$lockless_dmix" = "yes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([LOCKLESS_DMIX_DEFAULT], "1", [Lockless dmix as default])
+else
+ AC_MSG_RESULT(no)
+fi
+fi
dnl Create PCM plugin symbol list for static library
rm -f "$srcdir"/src/pcm/pcm_symbols_list.c
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
index 665340954cf3..19c5a811262f 100644
--- a/src/pcm/pcm_direct.c
+++ b/src/pcm/pcm_direct.c
@@ -82,7 +82,13 @@ int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix)
return 0;
}
-#define SND_PCM_DIRECT_MAGIC (0xa15ad300 + sizeof(snd_pcm_direct_share_t))
+static unsigned int snd_pcm_direct_magic(snd_pcm_direct_t *dmix)
+{
+ if (!dmix->direct_memory_access)
+ return 0xa15ad300 + sizeof(snd_pcm_direct_share_t);
+ else
+ return 0xb15ad300 + sizeof(snd_pcm_direct_share_t);
+}
/*
* global shared memory area
@@ -132,10 +138,10 @@ retryget:
buf.shm_perm.gid = dmix->ipc_gid;
shmctl(dmix->shmid, IPC_SET, &buf);
}
- dmix->shmptr->magic = SND_PCM_DIRECT_MAGIC;
+ dmix->shmptr->magic = snd_pcm_direct_magic(dmix);
return 1;
} else {
- if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {
+ if (dmix->shmptr->magic != snd_pcm_direct_magic(dmix)) {
snd_pcm_direct_shm_discard(dmix);
return -EINVAL;
}
@@ -1892,7 +1898,11 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
rec->slowptr = 1;
rec->max_periods = 0;
rec->var_periodsize = 0;
+#ifdef LOCKLESS_DMIX_DEFAULT
rec->direct_memory_access = 1;
+#else
+ rec->direct_memory_access = 0;
+#endif
rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_AUTO;
rec->tstamp_type = -1;
--
2.16.4

View File

@ -0,0 +1,110 @@
From d824b461ae807ea436e2df36da9c2212e485e3e6 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Fri, 19 Jun 2020 18:40:46 +0200
Subject: [PATCH 06/32] pcm: dmix: Fix semaphore usage with lockless operation
As Maarten Baert recently reported, the current dmix code applies the
semaphore unnecessarily around mixing streams even when the lockless
mix operation is used on x86. This was rather introduced mistakenly
at the commit 267d7c728196 ("Add support of little-endian on
i386/x86_64 dmix") where the generic dmix code was included on x86,
too.
For achieving the original performance back, this patch changes the
semaphore handling to be checked at run time instead of statically at
compile time.
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_direct.h | 1 +
src/pcm/pcm_dmix.c | 18 +++++++++++-------
src/pcm/pcm_dmix_generic.c | 2 +-
src/pcm/pcm_dmix_i386.c | 1 +
src/pcm/pcm_dmix_x86_64.c | 1 +
5 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
index 8a236970a3a1..2150bce15449 100644
--- a/src/pcm/pcm_direct.h
+++ b/src/pcm/pcm_direct.h
@@ -186,6 +186,7 @@ struct snd_pcm_direct {
mix_areas_32_t *remix_areas_32;
mix_areas_24_t *remix_areas_24;
mix_areas_u8_t *remix_areas_u8;
+ unsigned int use_sem;
} dmix;
struct {
unsigned long long chn_mask;
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index 843fa3168756..e9343b19a536 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -292,13 +292,17 @@ static void remix_areas(snd_pcm_direct_t *dmix,
* the area via semaphore
*/
#ifndef DOC_HIDDEN
-#ifdef NO_CONCURRENT_ACCESS
-#define dmix_down_sem(dmix) snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT)
-#define dmix_up_sem(dmix) snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT)
-#else
-#define dmix_down_sem(dmix)
-#define dmix_up_sem(dmix)
-#endif
+static void dmix_down_sem(snd_pcm_direct_t *dmix)
+{
+ if (dmix->u.dmix.use_sem)
+ snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
+}
+
+static void dmix_up_sem(snd_pcm_direct_t *dmix)
+{
+ if (dmix->u.dmix.use_sem)
+ snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
+}
#endif
/*
diff --git a/src/pcm/pcm_dmix_generic.c b/src/pcm/pcm_dmix_generic.c
index 40c08747a74a..8a5b6f148556 100644
--- a/src/pcm/pcm_dmix_generic.c
+++ b/src/pcm/pcm_dmix_generic.c
@@ -43,7 +43,6 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
#ifndef ARCH_ADD
#define ARCH_ADD(p,a) (*(p) += (a))
#define ARCH_CMPXCHG(p,a,b) (*(p)) /* fake */
-#define NO_CONCURRENT_ACCESS /* use semaphore to avoid race */
#define IS_CONCURRENT 0 /* no race check */
#endif
@@ -530,6 +529,7 @@ static void generic_mix_select_callbacks(snd_pcm_direct_t *dmix)
dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8;
dmix->u.dmix.remix_areas_24 = generic_remix_areas_24;
dmix->u.dmix.remix_areas_u8 = generic_remix_areas_u8;
+ dmix->u.dmix.use_sem = 1;
}
#endif
diff --git a/src/pcm/pcm_dmix_i386.c b/src/pcm/pcm_dmix_i386.c
index 1ab983a8a373..82a91c5c2897 100644
--- a/src/pcm/pcm_dmix_i386.c
+++ b/src/pcm/pcm_dmix_i386.c
@@ -135,4 +135,5 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix)
dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp: mix_areas_24;
dmix->u.dmix.remix_areas_24 = smp > 1 ? remix_areas_24_smp: remix_areas_24;
}
+ dmix->u.dmix.use_sem = 0;
}
diff --git a/src/pcm/pcm_dmix_x86_64.c b/src/pcm/pcm_dmix_x86_64.c
index 34c40d4e9d1d..4d882bfd01bf 100644
--- a/src/pcm/pcm_dmix_x86_64.c
+++ b/src/pcm/pcm_dmix_x86_64.c
@@ -102,4 +102,5 @@ static void mix_select_callbacks(snd_pcm_direct_t *dmix)
dmix->u.dmix.remix_areas_32 = smp > 1 ? remix_areas_32_smp : remix_areas_32;
dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp : mix_areas_24;
dmix->u.dmix.remix_areas_24 = smp > 1 ? remix_areas_24_smp : remix_areas_24;
+ dmix->u.dmix.use_sem = 0;
}
--
2.16.4

View File

@ -0,0 +1,151 @@
From 8defc5c2a65345a1aee613ebf0999d203c2e0433 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Mon, 13 Jul 2020 23:17:03 +0200
Subject: [PATCH 07/32] pcm: iec958: implement HDMI HBR audio formatting
High bitrate compressed audio data like DTS HD or MAT is usually
packed into 8-channel data. The HDMI specs state this has to be
formatted as a single IEC958 stream, compared to normal multi-
channel PCM data which has to be formatted as parallel IEC958 streams.
As this single-stream formatting mode may break existing setups that
expect non-PCM multichannel data to be formatted as parallel IEC958
streams it needs to be explicitly selected by setting the hdmi_mode
option to true.
The single-stream formatting implementation is prepared to cope with
arbitrary channel counts but only limited testing was done for channel
counts other than 8.
Signed-off-by: Matthias Reichl <hias@horus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_iec958.c | 37 +++++++++++++++++++++++++++++++++----
1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c
index 76d3ca7b8e3c..17ade9571cae 100644
--- a/src/pcm/pcm_iec958.c
+++ b/src/pcm/pcm_iec958.c
@@ -63,6 +63,7 @@ struct snd_pcm_iec958 {
unsigned int byteswap;
unsigned char preamble[3]; /* B/M/W or Z/X/Y */
snd_pcm_fast_ops_t fops;
+ int hdmi_mode;
};
enum { PREAMBLE_Z, PREAMBLE_X, PREAMBLE_Y };
@@ -193,6 +194,10 @@ static void snd_pcm_iec958_encode(snd_pcm_iec958_t *iec,
unsigned int channel;
int32_t sample = 0;
int counter = iec->counter;
+ int single_stream = iec->hdmi_mode &&
+ (iec->status[0] & IEC958_AES0_NONAUDIO) &&
+ (channels == 8);
+ int counter_step = single_stream ? ((channels + 1) >> 1) : 1;
for (channel = 0; channel < channels; ++channel) {
const char *src;
uint32_t *dst;
@@ -205,7 +210,12 @@ static void snd_pcm_iec958_encode(snd_pcm_iec958_t *iec,
src_step = snd_pcm_channel_area_step(src_area);
dst_step = snd_pcm_channel_area_step(dst_area) / sizeof(uint32_t);
frames1 = frames;
- iec->counter = counter;
+
+ if (single_stream)
+ iec->counter = (counter + (channel >> 1)) % 192;
+ else
+ iec->counter = counter;
+
while (frames1-- > 0) {
goto *get;
#define GET32_END after
@@ -217,9 +227,11 @@ static void snd_pcm_iec958_encode(snd_pcm_iec958_t *iec,
*dst = sample;
src += src_step;
dst += dst_step;
- iec->counter++;
+ iec->counter += counter_step;
iec->counter %= 192;
}
+ if (single_stream) /* set counter to ch0 value for next iteration */
+ iec->counter = (counter + frames * counter_step) % 192;
}
}
#endif /* DOC_HIDDEN */
@@ -473,6 +485,7 @@ static const snd_pcm_ops_t snd_pcm_iec958_ops = {
* \param close_slave When set, the slave PCM handle is closed with copy PCM
* \param status_bits The IEC958 status bits
* \param preamble_vals The preamble byte values
+ * \param hdmi_mode When set, enable HDMI compliant formatting
* \retval zero on success otherwise a negative error code
* \warning Using of this function might be dangerous in the sense
* of compatibility reasons. The prototype might be freely
@@ -481,7 +494,8 @@ static const snd_pcm_ops_t snd_pcm_iec958_ops = {
int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat,
snd_pcm_t *slave, int close_slave,
const unsigned char *status_bits,
- const unsigned char *preamble_vals)
+ const unsigned char *preamble_vals,
+ int hdmi_mode)
{
snd_pcm_t *pcm;
snd_pcm_iec958_t *iec;
@@ -519,6 +533,8 @@ int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
memcpy(iec->preamble, preamble_vals, 3);
+ iec->hdmi_mode = hdmi_mode;
+
err = snd_pcm_new(&pcm, SND_PCM_TYPE_IEC958, name, slave->stream, slave->mode);
if (err < 0) {
free(iec);
@@ -566,9 +582,14 @@ pcm.name {
[preamble.z or preamble.b val]
[preamble.x or preamble.m val]
[preamble.y or preamble.w val]
+ [hdmi_mode true]
}
\endcode
+When <code>hdmi_mode</code> is true, 8-channel compressed data is
+formatted as 4 contiguous frames of a single IEC958 stream as required
+by the HDMI HBR specification.
+
\subsection pcm_plugins_iec958_funcref Function reference
<UL>
@@ -605,6 +626,7 @@ int _snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name,
unsigned char preamble_vals[3] = {
0x08, 0x02, 0x04 /* Z, X, Y */
};
+ int hdmi_mode = 0;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
@@ -633,6 +655,13 @@ int _snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name,
preamble = n;
continue;
}
+ if (strcmp(id, "hdmi_mode") == 0) {
+ err = snd_config_get_bool(n);
+ if (err < 0)
+ continue;
+ hdmi_mode = err;
+ continue;
+ }
SNDERR("Unknown field %s", id);
return -EINVAL;
}
@@ -707,7 +736,7 @@ int _snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name,
return err;
err = snd_pcm_iec958_open(pcmp, name, sformat, spcm, 1,
status ? status_bits : NULL,
- preamble_vals);
+ preamble_vals, hdmi_mode);
if (err < 0)
snd_pcm_close(spcm);
return err;
--
2.16.4

View File

@ -0,0 +1,123 @@
From 36e4b296d2f4ad0034f7028256c64b8af003068d Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Mon, 13 Jul 2020 23:17:04 +0200
Subject: [PATCH 08/32] pcm: iec958: set channel status bits according to rate
and format
This mimics snd_pcm_create_iec958_consumer in the kernel.
The rate and wordlength bits will only be modified if they are
set to "not indicated", which is now the default if no status
option is used.
This allows applications to override parameters determined from
the stream or implement channel status bits extensions without
needing to change pcm_iec958 code.
Signed-off-by: Matthias Reichl <hias@horus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_iec958.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 76 insertions(+), 4 deletions(-)
diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c
index 17ade9571cae..a11a043924f6 100644
--- a/src/pcm/pcm_iec958.c
+++ b/src/pcm/pcm_iec958.c
@@ -365,9 +365,80 @@ static int snd_pcm_iec958_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params
iec->byteswap = format != SND_PCM_FORMAT_IEC958_SUBFRAME;
}
}
- /* FIXME: needs to adjust status_bits according to the format
- * and sample rate
- */
+
+ if ((iec->status[0] & IEC958_AES0_PROFESSIONAL) == 0) {
+ if ((iec->status[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) {
+ unsigned int rate = 0;
+ unsigned char fs;
+
+ err = INTERNAL(snd_pcm_hw_params_get_rate)(params, &rate, 0);
+ if (err < 0)
+ rate = 0;
+
+ switch (rate) {
+ case 22050:
+ fs = IEC958_AES3_CON_FS_22050;
+ break;
+ case 24000:
+ fs = IEC958_AES3_CON_FS_24000;
+ break;
+ case 32000:
+ fs = IEC958_AES3_CON_FS_32000;
+ break;
+ case 44100:
+ fs = IEC958_AES3_CON_FS_44100;
+ break;
+ case 48000:
+ fs = IEC958_AES3_CON_FS_48000;
+ break;
+ case 88200:
+ fs = IEC958_AES3_CON_FS_88200;
+ break;
+ case 96000:
+ fs = IEC958_AES3_CON_FS_96000;
+ break;
+ case 176400:
+ fs = IEC958_AES3_CON_FS_176400;
+ break;
+ case 192000:
+ fs = IEC958_AES3_CON_FS_192000;
+ break;
+ case 768000:
+ fs = IEC958_AES3_CON_FS_768000;
+ break;
+ default:
+ fs = IEC958_AES3_CON_FS_NOTID;
+ break;
+ }
+
+ iec->status[3] &= ~IEC958_AES3_CON_FS;
+ iec->status[3] |= fs;
+ }
+
+ if ((iec->status[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) {
+ unsigned char ws;
+ switch (snd_pcm_format_width(format)) {
+ case 16:
+ ws = IEC958_AES4_CON_WORDLEN_20_16;
+ break;
+ case 18:
+ ws = IEC958_AES4_CON_WORDLEN_22_18;
+ break;
+ case 20:
+ ws = IEC958_AES4_CON_WORDLEN_20_16 | IEC958_AES4_CON_MAX_WORDLEN_24;
+ break;
+ case 24:
+ case 32: /* Assume 24-bit width for 32-bit samples. */
+ ws = IEC958_AES4_CON_WORDLEN_24_20 | IEC958_AES4_CON_MAX_WORDLEN_24;
+ break;
+ default:
+ ws = IEC958_AES4_CON_WORDLEN_NOTID;
+ break;
+ }
+ iec->status[4] &= ~(IEC958_AES4_CON_MAX_WORDLEN_24 | IEC958_AES4_CON_WORDLEN);
+ iec->status[4] |= ws;
+ }
+ }
return 0;
}
@@ -504,7 +575,8 @@ int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
IEC958_AES0_CON_EMPHASIS_NONE,
IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
0,
- IEC958_AES3_CON_FS_48000
+ IEC958_AES3_CON_FS_NOTID, /* will be set in hwparams */
+ IEC958_AES4_CON_WORDLEN_NOTID /* will be set in hwparams */
};
assert(pcmp && slave);
--
2.16.4

View File

@ -0,0 +1,27 @@
From a80606d1abfd3c2bccfa179c31af8b6e7c0a9031 Mon Sep 17 00:00:00 2001
From: omar <odzinic@gmail.com>
Date: Mon, 20 Jul 2020 11:46:46 -0400
Subject: [PATCH 09/32] conf: pcm - USB - Added S/PDIF fix for Asus Xonar SE
Resolves #70
From: omar <odzinic@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/conf/cards/USB-Audio.conf | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf
index 01664abfc263..297629f34d77 100644
--- a/src/conf/cards/USB-Audio.conf
+++ b/src/conf/cards/USB-Audio.conf
@@ -42,6 +42,7 @@ USB-Audio.pcm.iec958_device {
"ASUS XONAR U5" 1
"XONAR U5" 1
"XONAR SOUND CARD" 1
+ "Xonar SoundCard" 2
# The below don't have digital in/out, so prevent them from being opened.
"Andrea PureAudio USB-SA Headset" 999
--
2.16.4

View File

@ -0,0 +1,60 @@
From a3ca4803cb8db73d01231c69620e2d18573ffba9 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 27 Jul 2020 13:18:20 +0200
Subject: [PATCH 10/32] control: ctlparse - fix enum values in '' or ""
This comit fixes the enum value string parser
(fixes aaf3a081bff1cc85635f7a3c3d4287c4addbbd84).
BugLink: https://github.com/alsa-project/alsa-ucm-conf/pull/40
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/control/ctlparse.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/src/control/ctlparse.c b/src/control/ctlparse.c
index ee1e0602cbf7..74f76cca9ca4 100644
--- a/src/control/ctlparse.c
+++ b/src/control/ctlparse.c
@@ -282,23 +282,27 @@ static int get_ctl_enum_item_index(snd_ctl_t *handle,
if (items <= 0)
return -1;
+ end = *ptr;
+ if (end == '\'' || end == '"')
+ ptr++;
+ else
+ end = '\0';
+
for (i = 0; i < items; i++) {
snd_ctl_elem_info_set_item(info, i);
if (snd_ctl_elem_info(handle, info) < 0)
return -1;
name = snd_ctl_elem_info_get_item_name(info);
- end = *ptr;
- if (end == '\'' || end == '"')
- ptr++;
- else
- end = '\0';
len = strlen(name);
- if (strncmp(name, ptr, len) == 0) {
- if (ptr[len] == end || ptr[len] == ',' || ptr[len] == '\n') {
- ptr += len;
- *ptrp = ptr;
- return i;
- }
+ if (strncmp(name, ptr, len))
+ continue;
+ if (end == '\0' && (ptr[len] == '\0' || ptr[len] == ',' || ptr[len] == '\n')) {
+ *ptrp = ptr + len;
+ return i;
+ }
+ if (end != '\0' && ptr[len] == end) {
+ *ptrp = ptr + len + 1;
+ return i;
}
}
return -1;
--
2.16.4

View File

@ -0,0 +1,31 @@
From 464c2f8b61855cb22d61c4b232f74d6767fac5fb Mon Sep 17 00:00:00 2001
From: Kai-Heng Feng <kai.heng.feng@canonical.com>
Date: Mon, 3 Aug 2020 23:57:45 +0800
Subject: [PATCH 11/32] conf: USB-Audio: Disable IEC958 on Lenovo ThinkStation
P620
Both USB audio cards on Lenovo ThinkStation P620 don't support IEC958,
so disable IEC958 accordingly.
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/conf/cards/USB-Audio.conf | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/conf/cards/USB-Audio.conf b/src/conf/cards/USB-Audio.conf
index 297629f34d77..9b64af3c0da9 100644
--- a/src/conf/cards/USB-Audio.conf
+++ b/src/conf/cards/USB-Audio.conf
@@ -63,6 +63,8 @@ USB-Audio.pcm.iec958_device {
"Scarlett 2i4 USB" 999
"Sennheiser USB headset" 999
"SWTOR Gaming Headset by Razer" 999
+ "ThinkStation P620 Main" 999
+ "ThinkStation P620 Rear" 999
"Thunderbolt Dock Audio Headset" 999
"Thunderbolt Dock Audio Module" 999
"USB Device 0x46d_0x821" 999
--
2.16.4

View File

@ -0,0 +1,92 @@
From 82cb27c165d4337fe3183668bd0fa21ff6287e8e Mon Sep 17 00:00:00 2001
From: Vijay Palaniswamy <vijay.palaniswamy@in.bosch.com>
Date: Thu, 23 Jul 2020 11:49:10 +0530
Subject: [PATCH 12/32] pcm: dmix: fix access to sum-buffer in non-interleaved
mixing mode
When dmix uses non-interleaved mixing mode the offset and step width
to sum_buffer was calculated by using the dmix channels instead of
the slave channels. This leads to audio distortions due to frame
corruption.
example:
- With below configuratio, Do aplay on both device in parallel for
audio distortion
pcm.dmix_2_channels {
type dmix
ipc_key 5678293
ipc_perm 0660
ipc_gid audio
bindings [0 1]
slave {
pcm "hardware"
channels 2
periods 4
period_time 40000
}
}
pcm.dmix_1_channels {
type dmix
ipc_key 5678293
ipc_perm 0660
ipc_gid audio
bindings [0]
slave {
pcm "hardware"
channels 1
periods 4
period_time 40000
}
}
pcm.hardware {
type hw
card 0
channels 2
rate 48000
format S16_LE
}
Signed-off-by: Vijay Palaniswamy <vijay.palaniswamy@in.bosch.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_dmix.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
index e9343b19a536..8bce7aca85f7 100644
--- a/src/pcm/pcm_dmix.c
+++ b/src/pcm/pcm_dmix.c
@@ -212,10 +212,10 @@ static void mix_areas(snd_pcm_direct_t *dmix,
do_mix_areas(size,
((unsigned char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + dst_ofs * dst_step,
((unsigned char *)src_areas[chn].addr + src_areas[chn].first / 8) + src_ofs * src_step,
- dmix->u.dmix.sum_buffer + channels * dst_ofs + chn,
+ dmix->u.dmix.sum_buffer + dmix->shmptr->s.channels * dst_ofs + dchn,
dst_step,
src_step,
- channels * sizeof(signed int));
+ dmix->shmptr->s.channels * sizeof(signed int));
}
}
@@ -280,10 +280,10 @@ static void remix_areas(snd_pcm_direct_t *dmix,
do_remix_areas(size,
((unsigned char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + dst_ofs * dst_step,
((unsigned char *)src_areas[chn].addr + src_areas[chn].first / 8) + src_ofs * src_step,
- dmix->u.dmix.sum_buffer + channels * dst_ofs + chn,
+ dmix->u.dmix.sum_buffer + dmix->shmptr->s.channels * dst_ofs + dchn,
dst_step,
src_step,
- channels * sizeof(signed int));
+ dmix->shmptr->s.channels * sizeof(signed int));
}
}
--
2.16.4

View File

@ -0,0 +1,278 @@
From e097dd491a8f25418a90d38aea549bb4668de955 Mon Sep 17 00:00:00 2001
From: "Tanjeff-N. Moos" <tanjeff@cccmz.de>
Date: Fri, 14 Aug 2020 08:40:28 +0200
Subject: [PATCH 14/32] control: Add documentation for snd_ctl_elem_list_*.
Signed-off-by: Tanjeff-N. Moos <tanjeff@cccmz.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/control.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/control/control.c | 80 +++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 148 insertions(+), 13 deletions(-)
diff --git a/include/control.h b/include/control.h
index 02db72d413ae..9deec6f3dee4 100644
--- a/include/control.h
+++ b/include/control.h
@@ -56,7 +56,75 @@ typedef struct _snd_ctl_card_info snd_ctl_card_info_t;
/** CTL element identifier container */
typedef struct _snd_ctl_elem_id snd_ctl_elem_id_t;
-/** CTL element identifier list container */
+/** CTL element list container
+ *
+ * This is a list of CTL elements. The list contains management
+ * information (e.g. how many elements the sound card has) as well as
+ * the element identifiers. All functions which operate on the list
+ * are named snd_ctl_elem_list_*().
+ *
+ * \par Memory management
+ *
+ * There are two memory areas to deal with: The list container itself
+ * and the memory for the element identifiers.
+ *
+ * To manage the area for the list container, the following functions
+ * are used:
+ *
+ * - snd_ctl_elem_list_malloc() / snd_ctl_elem_list_free() to allocate
+ * and free memory on the heap, or
+ * - snd_ctl_elem_list_alloca() to allocate the memory on the
+ * stack. This memory is auto-released when the stack is unwound.
+ *
+ * To manage the space for the element identifiers, the
+ * snd_ctl_elem_list_alloc_space() and snd_ctl_elem_list_free_space()
+ * are used. Allocating the right amount of space can be achieved by
+ * first obtaining the number of elements and then calling
+ * snd_ctl_elem_list_alloc_space():
+ *
+ * \code
+ * snd_ctl_elem_list_t* list;
+ * int count;
+ *
+ * // Initialise list
+ * snd_ctl_elem_list_malloc(&list);
+ *
+ * // Get number of elements
+ * snd_ctl_elem_list(ctl, list);
+ * count = snd_ctl_elem_list_get_count(list);
+ *
+ * // Allocate space for identifiers
+ * snd_ctl_elem_list_alloc_space(list, count);
+ *
+ * // Get identifiers
+ * snd_ctl_elem_list(ctl, list); // yes, this is same as above :)
+ *
+ * // Do something useful with the list...
+ *
+ * // Cleanup
+ * snd_ctl_elem_list_free_space(list);
+ * snd_ctl_elem_list_free(list);
+ * \endcode
+ *
+ *
+ * \par The Elements
+ *
+ * The elements in the list are accessed using an index. This index is
+ * the location in the list; Don't confuse it with the 'index' of the
+ * element identifier. For example:
+ *
+ * \code
+ * snd_ctl_elem_list_t list;
+ * unsigned int element_index;
+ *
+ * // Allocate space, fill list ...
+ *
+ * element_index = snd_ctl_elem_list_get_index(&list, 2);
+ * \endcode
+ *
+ * This will access the 3rd element in the list (index=2) and get the
+ * elements index from the driver (which might be 13, for example).
+ */
typedef struct _snd_ctl_elem_list snd_ctl_elem_list_t;
/** CTL element info container */
@@ -354,11 +422,18 @@ void snd_ctl_event_copy(snd_ctl_event_t *dst, const snd_ctl_event_t *src);
snd_ctl_event_type_t snd_ctl_event_get_type(const snd_ctl_event_t *obj);
size_t snd_ctl_elem_list_sizeof(void);
+
/** \hideinitializer
- * \brief allocate an invalid #snd_ctl_elem_list_t using standard alloca
- * \param ptr returned pointer
+ *
+ * \brief Allocate a #snd_ctl_elem_list_t using standard alloca.
+ *
+ * The memory is allocated on the stack and will automatically be
+ * released when the stack unwinds (i.e. no free() is needed).
+ *
+ * \param ptr Pointer to allocated memory.
*/
#define snd_ctl_elem_list_alloca(ptr) __snd_alloca(ptr, snd_ctl_elem_list)
+
int snd_ctl_elem_list_malloc(snd_ctl_elem_list_t **ptr);
void snd_ctl_elem_list_free(snd_ctl_elem_list_t *obj);
void snd_ctl_elem_list_clear(snd_ctl_elem_list_t *obj);
diff --git a/src/control/control.c b/src/control/control.c
index e21e8f1d2621..1bcf1ab2e431 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -280,6 +280,21 @@ int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info)
/**
* \brief Get a list of element identifiers
+ *
+ * Before calling this function, memoru must be allocated using
+ * snd_ctl_elem_list_malloc().
+ *
+ * This function obtains data from the sound card driver and puts it
+ * into the list.
+ *
+ * If there was space allocated for the element identifiers (using
+ * snd_ctl_elem_list_alloc_space()), information will be filled in. If
+ * too little space was allocated, only a part of the elements will be
+ * queried. If there was too much space allocated, some of it remains
+ * unused. Use snd_ctl_elem_list_get_count() and
+ * snd_ctl_elem_list_get_used() to obtain information about space
+ * usage. See #snd_ctl_elem_list_t to learn more.
+ *
* \param ctl CTL handle
* \param list CTL element identifiers list pointer
* \return 0 on success otherwise a negative error code
@@ -1508,9 +1523,14 @@ const char *snd_ctl_event_type_name(snd_ctl_event_type_t type)
/**
* \brief allocate space for CTL element identifiers list
- * \param obj CTL element identifiers list
- * \param entries Entries to allocate
- * \return 0 on success otherwise a negative error code
+ *
+ * The space can be released with snd_ctl_elem_list_free_space().
+ *
+ * \param obj CTL element identifiers list.
+ * \param entries How many entries to allocate. See
+ * #snd_ctl_elem_list_t to learn how to obtain
+ * this number in advance.
+ * \return 0 on success otherwise a negative error code.
*/
int snd_ctl_elem_list_alloc_space(snd_ctl_elem_list_t *obj, unsigned int entries)
{
@@ -1526,6 +1546,10 @@ int snd_ctl_elem_list_alloc_space(snd_ctl_elem_list_t *obj, unsigned int entries
/**
* \brief free previously allocated space for CTL element identifiers list
+ *
+ * Releases space previously allocated using
+ * snd_ctl_elem_list_alloc_space().
+ *
* \param obj CTL element identifiers list
*/
void snd_ctl_elem_list_free_space(snd_ctl_elem_list_t *obj)
@@ -2016,7 +2040,7 @@ snd_ctl_event_type_t snd_ctl_event_get_type(const snd_ctl_event_t *obj)
}
/**
- * \brief get size of #snd_ctl_elem_list_t
+ * \brief get size of #snd_ctl_elem_list_t.
* \return size in bytes
*/
size_t snd_ctl_elem_list_sizeof()
@@ -2025,7 +2049,10 @@ size_t snd_ctl_elem_list_sizeof()
}
/**
- * \brief allocate an invalid #snd_ctl_elem_list_t using standard malloc
+ * \brief allocate a #snd_ctl_elem_list_t using standard malloc.
+ *
+ * The memory can be released using snd_ctl_elem_list_free().
+ *
* \param ptr returned pointer
* \return 0 on success otherwise negative error code
*/
@@ -2039,7 +2066,15 @@ int snd_ctl_elem_list_malloc(snd_ctl_elem_list_t **ptr)
}
/**
- * \brief frees a previously allocated #snd_ctl_elem_list_t
+ * \brief frees a previously allocated #snd_ctl_elem_list_t.
+ *
+ * Release memory previously allocated using
+ * snd_ctl_elem_list_malloc().
+ *
+ * If you used snd_ctl_elem_list_alloc_space() on the list, you must
+ * use snd_ctl_elem_list_free_space() \em before calling this
+ * function.
+ *
* \param obj pointer to object to free
*/
void snd_ctl_elem_list_free(snd_ctl_elem_list_t *obj)
@@ -2048,7 +2083,15 @@ void snd_ctl_elem_list_free(snd_ctl_elem_list_t *obj)
}
/**
- * \brief clear given #snd_ctl_elem_list_t object
+ * \brief Clear given #snd_ctl_elem_list_t object.
+ *
+ * This will make the stored identifiers inaccessible without freeing
+ * their space.
+ *
+ * \warning The element identifier space cannot be freed after calling
+ * this function. Therefore, snd_ctl_elem_list_free_space()
+ * must be called in advance.
+ *
* \param obj pointer to object to clear
*/
void snd_ctl_elem_list_clear(snd_ctl_elem_list_t *obj)
@@ -2057,7 +2100,11 @@ void snd_ctl_elem_list_clear(snd_ctl_elem_list_t *obj)
}
/**
- * \brief copy one #snd_ctl_elem_list_t to another
+ * \brief copy one #snd_ctl_elem_list_t to another.
+ *
+ * This performs a shallow copy. That means the both lists will share
+ * the same space for the elements. The elements will not be copied.
+ *
* \param dst pointer to destination
* \param src pointer to source
*/
@@ -2080,6 +2127,12 @@ void snd_ctl_elem_list_set_offset(snd_ctl_elem_list_t *obj, unsigned int val)
/**
* \brief Get number of used entries in CTL element identifiers list
+ *
+ * This function returns how many entries are actually filled with
+ * useful information.
+ *
+ * See also snd_ctl_elem_list_get_count().
+ *
* \param obj CTL element identifier list
* \return number of used entries
*/
@@ -2090,7 +2143,14 @@ unsigned int snd_ctl_elem_list_get_used(const snd_ctl_elem_list_t *obj)
}
/**
- * \brief Get total count of elements present in CTL device (information present in every filled CTL element identifiers list)
+ * \brief Get total count of elements present in CTL device
+ *
+ * This function returns how many entries were allocated using
+ * snd_ctl_elem_list_alloc_space(). This information is present after
+ * snd_ctl_elem_list() was called.
+ *
+ * See also snd_ctl_elem_list_get_used().
+ *
* \param obj CTL element identifier list
* \return total number of elements
*/
@@ -2140,7 +2200,7 @@ snd_ctl_elem_iface_t snd_ctl_elem_list_get_interface(const snd_ctl_elem_list_t *
}
/**
- * \brief Get device part of CTL element identifier for an entry of a CTL element identifiers list
+ * \brief Get the device part of CTL element identifier for an entry of a CTL element identifiers list
* \param obj CTL element identifier list
* \param idx Index of entry
* \return CTL element related device
--
2.16.4

View File

@ -0,0 +1,27 @@
From ed752498522b0a99a9fbec99247d9c73b10abb3e Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 18 Aug 2020 16:53:23 +0200
Subject: [PATCH 15/32] conf: quote also strings with '*' and '#' characters in
string_print()
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 8518f90c5d60..7df2b4e77759 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -1536,6 +1536,8 @@ static void string_print(char *str, int id, snd_output_t *out)
case ']':
case '\'':
case '"':
+ case '*':
+ case '#':
goto quoted;
default:
if (*p <= 31 || *p >= 127)
--
2.16.4

View File

@ -0,0 +1,54 @@
From 1ac965184eaefe503939e454273223a1d8d32f41 Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:08:54 +0200
Subject: [PATCH 16/32] topology: decode: Fix channel map memory allocation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Memory allocated on the stack was referenced outside of the function scope
caused undefined behaviour.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/ctl.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 90241b6318c5..6e6c1d163aa3 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -1330,7 +1330,6 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg,
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)) {
@@ -1375,11 +1374,13 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg,
}
}
- 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];
+ et->map = tplg_calloc(heap, sizeof(struct snd_tplg_channel_map_template));
+ if (!et->map)
+ return -ENOMEM;
+ et->map->num_channels = ec->num_channels;
+ for (i = 0; i < et->map->num_channels; i++) {
+ struct snd_tplg_channel_elem *channel = &et->map->channel[i];
+
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;
--
2.16.4

View File

@ -0,0 +1,36 @@
From 346a5efa87c38a0d5ff9bd5b5d08be27b6c9bfaf Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:08:55 +0200
Subject: [PATCH 17/32] topology: decode: Fix infinite loop in decoding enum
control
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Accessing memory outside of allocated boundaries caused segmentation fault.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/ctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 6e6c1d163aa3..0aa49ab82c1e 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -1367,7 +1367,7 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg,
et->texts = tplg_calloc(heap, sizeof(char *) * ec->items);
if (!et->texts)
return -ENOMEM;
- for (i = 0; ec->items; i++) {
+ for (i = 0; i < 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];
--
2.16.4

View File

@ -0,0 +1,42 @@
From 11d4a5aa721dce2c3f7430996caf244a73dd5099 Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:08:56 +0200
Subject: [PATCH 18/32] topology: decode: Remove decoding values for enum
control
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Values have no representation in standard ALSA configuration files,
therefore there is no need to populate them. Also memory for values
wasn't allocated which was causing undefined behaviour.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/ctl.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 0aa49ab82c1e..02e482e7d05d 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -1367,11 +1367,8 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg,
et->texts = tplg_calloc(heap, sizeof(char *) * ec->items);
if (!et->texts)
return -ENOMEM;
- for (i = 0; i < ec->items; i++) {
- unsigned int j = i * sizeof(int) * ENUM_VAL_SIZE;
+ for (i = 0; i < ec->items; i++)
et->texts[i] = ec->texts[i];
- et->values[i] = (int *)&ec->values[j];
- }
}
et->map = tplg_calloc(heap, sizeof(struct snd_tplg_channel_map_template));
--
2.16.4

View File

@ -0,0 +1,50 @@
From f1435207a2fbe35bf616c6d58eecd8801dbe5642 Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:08:57 +0200
Subject: [PATCH 19/32] topology: decode: Add enum control texts as separate
element
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Texts are separate sections that should referenced by enum control.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/ctl.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 02e482e7d05d..1f3984616a65 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -1088,11 +1088,19 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
}
if (enum_ctl->texts != NULL) {
+ struct tplg_elem *texts = tplg_elem_new_common(tplg, NULL,
+ enum_ctl->hdr.name, SND_TPLG_TYPE_TEXT);
+
+ texts->texts->num_items = num_items;
for (i = 0; i < num_items; i++) {
- if (enum_ctl->texts[i] != NULL)
- snd_strlcpy(ec->texts[i], enum_ctl->texts[i],
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ if (!enum_ctl->texts[i])
+ continue;
+ snd_strlcpy(ec->texts[i], enum_ctl->texts[i],
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ snd_strlcpy(texts->texts->items[i], enum_ctl->texts[i],
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
}
+ tplg_ref_add(elem, SND_TPLG_TYPE_TEXT, enum_ctl->hdr.name);
}
if (enum_ctl->values != NULL) {
--
2.16.4

View File

@ -0,0 +1,33 @@
From 56a096ca2ceaf1dec944258d961c274e6550b27a Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:08:58 +0200
Subject: [PATCH 20/32] topology: decode: Fix printing texts section
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/text.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/topology/text.c b/src/topology/text.c
index 507c5450ab14..b899b2813ab4 100644
--- a/src/topology/text.c
+++ b/src/topology/text.c
@@ -103,7 +103,7 @@ int tplg_save_text(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
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]);
+ err = tplg_save_printf(dst, pfx, "\t'%s'\n", texts->items[i]);
if (err >= 0)
err = tplg_save_printf(dst, pfx, "]\n");
return err;
--
2.16.4

View File

@ -0,0 +1,95 @@
From c32498603aea7cc2f3fa3f850f9e4ea0f6ce03b2 Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:08:59 +0200
Subject: [PATCH 21/32] topology: decode: Change declaration of enum decoding
function
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Size constraints are always checked before invoking
tplg_decode_control_enum1. There is no need to validate it twice.
Alos moved debug print about size to invoking function, since now it's it
responsibility to check size.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/ctl.c | 19 +++++--------------
src/topology/dapm.c | 3 +--
src/topology/tplg_local.h | 2 +-
3 files changed, 7 insertions(+), 17 deletions(-)
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 1f3984616a65..47db400fd4d1 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -1335,22 +1335,10 @@ 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)
{
- struct snd_soc_tplg_enum_control *ec = bin;
int i;
- if (size < sizeof(*ec)) {
- SNDERR("enum: small size %d", size);
- return -EINVAL;
- }
-
- 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;
- }
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);
@@ -1427,7 +1415,10 @@ next:
return -EINVAL;
}
- err = tplg_decode_control_enum1(tplg, &heap, &et, pos, bin, size);
+ tplg_log(tplg, 'D', pos, "enum: size %d private size %d",
+ ec->size, ec->priv.size);
+
+ err = tplg_decode_control_enum1(tplg, &heap, &et, pos, ec);
if (err >= 0) {
t.enum_ctl = &et;
err = snd_tplg_add_object(tplg, &t);
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index cd1a87704681..73a9390340c2 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -972,8 +972,7 @@ next:
err = -EINVAL;
goto retval;
}
- err = tplg_decode_control_enum1(tplg, &heap, et, pos,
- bin, size2);
+ err = tplg_decode_control_enum1(tplg, &heap, et, pos, ec);
break;
case SND_SOC_TPLG_TYPE_BYTES:
bt = tplg_calloc(&heap, sizeof(*bt));
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 5ace0d1919e1..acb01a831f30 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -398,7 +398,7 @@ 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);
int tplg_decode_control_enum(snd_tplg_t *tplg, size_t pos,
struct snd_soc_tplg_hdr *hdr,
void *bin, size_t size);
--
2.16.4

View File

@ -0,0 +1,46 @@
From acbb0e3b1741107d01f03ee06f7819fd7f90bec4 Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:09:00 +0200
Subject: [PATCH 22/32] topology: decode: Fix decoding PCM formats and rates
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Not checking _LAST format and rate, which are valid indexes in arrays,
makes data loss while converting binary to standard ALSA configuration
file.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/pcm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index b15b95045ab5..db401145f3ec 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -549,7 +549,7 @@ int tplg_save_stream_caps(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
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++) {
+ 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",
@@ -563,7 +563,7 @@ int tplg_save_stream_caps(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
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++) {
+ 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",
--
2.16.4

View File

@ -0,0 +1,38 @@
From d93b3462996a20951bc0ca753d0304bbbb9850fc Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:09:01 +0200
Subject: [PATCH 23/32] topology: decode: Print sig_bits field in PCM
capabilities section
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Not printing this field makes data loss while converting from binary
to standard ALSA configuration file.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/pcm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index db401145f3ec..49c5eaba8b82 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -604,6 +604,9 @@ int tplg_save_stream_caps(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
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 && sc->sig_bits)
+ err = tplg_save_printf(dst, pfx, "\tsig_bits %u\n",
+ sc->sig_bits);
if (err >= 0)
err = tplg_save_printf(dst, pfx, "}\n");
return err;
--
2.16.4

View File

@ -0,0 +1,38 @@
From 6b0fb2bc7e0cfac8e1aedfcad183ab247c85173d Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:09:02 +0200
Subject: [PATCH 24/32] topology: decode: Add DAI name printing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
DAI name is a part of topology binary. Not printing makes data loss while
converting from binary to standard ALSA configuration file.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/pcm.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 49c5eaba8b82..5a54e1534c95 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -781,7 +781,9 @@ int tplg_save_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct snd_soc_tplg_pcm *pcm = elem->pcm;
int err = 0;
- if (pcm->dai_id > 0)
+ if (strlen(pcm->dai_name))
+ err = tplg_save_printf(dst, pfx, "dai.'%s'.id %u\n", pcm->dai_name, pcm->dai_id);
+ else if (pcm->dai_id > 0)
err = tplg_save_printf(dst, pfx, "dai.0.id %u\n", pcm->dai_id);
return err;
}
--
2.16.4

View File

@ -0,0 +1,94 @@
From d04e72c9a593015952e4858b92ab3f9d821560d9 Mon Sep 17 00:00:00 2001
From: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Date: Mon, 31 Aug 2020 11:09:03 +0200
Subject: [PATCH 25/32] topology: Make buffer for saving dynamic size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some fields can exceed size limit, e.g. private data has no size
restriction. Therefore it needs to be dynamically increased.
Signed-off-by: Piotr Maziarz <piotrx.maziarz@linux.intel.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/save.c | 34 +++++++++++++++++++++++++++++-----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/src/topology/save.c b/src/topology/save.c
index 4ecf86c3ade4..9c74735aea36 100644
--- a/src/topology/save.c
+++ b/src/topology/save.c
@@ -19,22 +19,43 @@
#include "tplg_local.h"
#define SAVE_ALLOC_SHIFT (13) /* 8192 bytes */
+#define PRINT_BUF_SIZE (1024)
+#define PRINT_BUF_SIZE_MAX (1024 * 1024)
int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...)
{
va_list va;
- char buf[1024], *s;
+ char *buf, *s;
size_t n, l, t, pl;
+ int ret = 0;
+
+ buf = malloc(PRINT_BUF_SIZE);
+ if (!buf)
+ return -ENOMEM;
if (pfx == NULL)
pfx = "";
va_start(va, fmt);
- n = vsnprintf(buf, sizeof(buf), fmt, va);
+ n = vsnprintf(buf, PRINT_BUF_SIZE, fmt, va);
va_end(va);
- if (n >= sizeof(buf))
- return -EOVERFLOW;
+ if (n >= PRINT_BUF_SIZE_MAX) {
+ ret = -EOVERFLOW;
+ goto end;
+ }
+
+ if (n >= PRINT_BUF_SIZE) {
+ char *tmp = realloc(buf, n + 1);
+ if (!tmp) {
+ ret = -ENOMEM;
+ goto end;
+ }
+ buf = tmp;
+ va_start(va, fmt);
+ n = vsnprintf(buf, n + 1, fmt, va);
+ va_end(va);
+ }
pl = strlen(pfx);
l = *dst ? strlen(*dst) : 0;
@@ -47,7 +68,8 @@ int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...)
if (s == NULL) {
free(*dst);
*dst = NULL;
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto end;
}
} else {
s = *dst;
@@ -57,6 +79,8 @@ int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...)
strcpy(s + l, pfx);
strcpy(s + l + pl, buf);
*dst = s;
+end:
+ free(buf);
return 0;
}
--
2.16.4

View File

@ -0,0 +1,26 @@
From dc778bade60812a71b98ac827c2c6e3c02f14cf1 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 31 Aug 2020 13:21:26 +0200
Subject: [PATCH 26/32] topology: return correct value in tplg_save_printf()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/save.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/topology/save.c b/src/topology/save.c
index 9c74735aea36..16fd694638ef 100644
--- a/src/topology/save.c
+++ b/src/topology/save.c
@@ -81,7 +81,7 @@ int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...)
*dst = s;
end:
free(buf);
- return 0;
+ return ret;
}
int tplg_nice_value_format(char *dst, size_t dst_size, unsigned int value)
--
2.16.4

View File

@ -0,0 +1,40 @@
From 6ca1ddfbcdf97ad46c3767ba314d1144119361fd Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 31 Aug 2020 13:25:01 +0200
Subject: [PATCH 27/32] topology: fix some gcc10 warnings (labs, signess)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/builder.c | 2 +-
src/topology/ctl.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/topology/builder.c b/src/topology/builder.c
index 15757668d7d4..f8aba830320e 100644
--- a/src/topology/builder.c
+++ b/src/topology/builder.c
@@ -55,7 +55,7 @@ static ssize_t write_block_header(snd_tplg_t *tplg, unsigned int type,
" 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));
+ tplg->bin_pos - tplg->next_hdr_pos);
return -EINVAL;
}
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 47db400fd4d1..1d31b4944abf 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -1363,7 +1363,7 @@ int tplg_decode_control_enum1(snd_tplg_t *tplg,
et->texts = tplg_calloc(heap, sizeof(char *) * ec->items);
if (!et->texts)
return -ENOMEM;
- for (i = 0; i < ec->items; i++)
+ for (i = 0; (unsigned int)i < ec->items; i++)
et->texts[i] = ec->texts[i];
}
--
2.16.4

View File

@ -0,0 +1,48 @@
From 84c6aeef5ca89c0686ae2a9ed90504010f8fe9e6 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 31 Aug 2020 14:25:56 +0200
Subject: [PATCH 28/32] topology: fix sort_config()
The temporary config array must be initialized for all compound types.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/save.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/src/topology/save.c b/src/topology/save.c
index 16fd694638ef..631d84b273bf 100644
--- a/src/topology/save.c
+++ b/src/topology/save.c
@@ -143,7 +143,6 @@ static snd_config_t *sort_config(const char *id, snd_config_t *src)
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;
@@ -155,14 +154,13 @@ static snd_config_t *sort_config(const char *id, snd_config_t *src)
if (a == NULL)
return NULL;
array = snd_config_is_array(src);
- if (array <= 0) {
- index = 0;
- snd_config_for_each(i, next, src) {
- snd_config_t *s = snd_config_iterator_entry(i);
- a[index++] = s;
- }
- qsort(a, count, sizeof(a[0]), _compar);
+ index = 0;
+ snd_config_for_each(i, next, src) {
+ snd_config_t *s = snd_config_iterator_entry(i);
+ a[index++] = s;
}
+ if (array <= 0)
+ qsort(a, count, sizeof(a[0]), _compar);
if (snd_config_make_compound(&dst, id, count == 1)) {
free(a);
return NULL;
--
2.16.4

View File

@ -0,0 +1,159 @@
From ab73253924ad8d46f94ab1212e0f05ebc2e3dcc5 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 31 Aug 2020 14:27:26 +0200
Subject: [PATCH 29/32] topology: fix the unaligned access
Introduce unaligned_get32/put32 helpers to deal with the
packed structures.
Use the gcc __BYTE_ORDER__ defines for the endian checks.
It may be improved to support other compilation environment.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/parser.c | 6 ++----
src/topology/pcm.c | 26 ++++++++++++++------------
src/topology/tplg_local.h | 13 +++++++++++++
3 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/src/topology/parser.c b/src/topology/parser.c
index 436e48416a43..f34de01bdc53 100644
--- a/src/topology/parser.c
+++ b/src/topology/parser.c
@@ -427,10 +427,8 @@ void snd_tplg_verbose(snd_tplg_t *tplg, int verbose)
static bool is_little_endian(void)
{
-#ifdef __BYTE_ORDER
- #if __BYTE_ORDER == __LITTLE_ENDIAN
- return true;
- #endif
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_INT__ == 4
+ return true;
#endif
return false;
}
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index 5a54e1534c95..a60ba00d979a 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -376,19 +376,19 @@ 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)
+static int parse_unsigned(snd_config_t *n, void *dst)
{
int ival;
if (tplg_get_integer(n, &ival, 0) < 0)
return -EINVAL;
- *dst = ival;
+ unaligned_put32(dst, ival);
#if TPLG_DEBUG
{
const char *id;
if (snd_config_get_id(n, &id) >= 0)
- tplg_dbg("\t\t%s: %d", id, *dst);
+ tplg_dbg("\t\t%s: %d", id, ival);
}
#endif
return 0;
@@ -621,7 +621,7 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem = private;
struct snd_soc_tplg_pcm *pcm;
struct snd_soc_tplg_dai *dai;
- unsigned int *playback, *capture;
+ void *playback, *capture;
struct snd_soc_tplg_stream_caps *caps;
const char *id, *value;
int stream;
@@ -651,10 +651,10 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
if (strcmp(id, "playback") == 0) {
stream = SND_SOC_TPLG_STREAM_PLAYBACK;
- *playback = 1;
+ unaligned_put32(playback, 1);
} else if (strcmp(id, "capture") == 0) {
stream = SND_SOC_TPLG_STREAM_CAPTURE;
- *capture = 1;
+ unaligned_put32(capture, 1);
} else
return -EINVAL;
@@ -747,6 +747,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id;
+ unsigned int dai_id;
snd_config_get_id(cfg, &id);
tplg_dbg("\t\tFE DAI %s:", id);
@@ -761,12 +762,13 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
continue;
if (strcmp(id, "id") == 0) {
- if (tplg_get_unsigned(n, &pcm->dai_id, 0)) {
+ if (tplg_get_unsigned(n, &dai_id, 0)) {
SNDERR("invalid fe dai ID");
return -EINVAL;
}
- tplg_dbg("\t\t\tindex: %d", pcm->dai_id);
+ unaligned_put32(&pcm->dai_id, dai_id);
+ tplg_dbg("\t\t\tindex: %d", dai_id);
}
}
@@ -790,7 +792,7 @@ int tplg_save_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
/* 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)
+ void *mask, void *flags)
{
int ret;
@@ -798,11 +800,11 @@ static int parse_flag(snd_config_t *n, unsigned int mask_in,
if (ret < 0)
return ret;
- *mask |= mask_in;
+ unaligned_put32(mask, unaligned_get32(mask) | mask_in);
if (ret)
- *flags |= mask_in;
+ unaligned_put32(flags, unaligned_get32(flags) | mask_in);
else
- *flags &= ~mask_in;
+ unaligned_put32(flags, unaligned_get32(flags) & (~mask_in));
return 0;
}
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index acb01a831f30..0c7be2001a63 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -225,6 +225,19 @@ struct tplg_table {
extern struct tplg_table tplg_table[];
extern unsigned int tplg_table_items;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_INT__ == 4
+static inline unsigned int unaligned_get32(void *src)
+{
+ unsigned int ret;
+ memcpy(&ret, src, sizeof(ret));
+ return ret;
+}
+static inline void unaligned_put32(void *dst, unsigned int val)
+{
+ memcpy(dst, &val, sizeof(val));
+}
+#endif
+
#define tplg_log(tplg, type, pos, fmt, args...) do { \
if ((tplg)->verbose) \
tplg_log_((tplg), (type), (pos), (fmt), ##args); \
--
2.16.4

View File

@ -0,0 +1,666 @@
From 472ab5db67a0ed04de634214773e7b17d10b5415 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Mon, 31 Aug 2020 19:44:46 +0200
Subject: [PATCH 30/32] topology: improve the printf buffer management
The commit d04e72c9a593015952e4858b92ab3f9d821560d9 introduced
the dynamic printf buffer allocation for each tplg_save_printf()
call.
Introduce 'struct tplg_buf' which carries extra information about
the temporary printf buffer and the destination buffer to save allocation
requests.
The printf buffer is also allocated using 1024 bytes chunks.
A comparison between 'alloc everyting' and 'cache+chunk alloc' for the
random picked topology file:
1: 18,620 allocs, 18,620 frees, 7,239,688 bytes allocated
2: 12,490 allocs, 12,490 frees, 962,568 bytes allocated
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/topology/channel.c | 3 +-
src/topology/ctl.c | 14 +++---
src/topology/dapm.c | 5 ++-
src/topology/data.c | 15 ++++---
src/topology/ops.c | 6 +--
src/topology/pcm.c | 18 ++++----
src/topology/save.c | 108 ++++++++++++++++++++++++++++------------------
src/topology/text.c | 2 +-
src/topology/tplg_local.h | 56 +++++++++++++-----------
9 files changed, 130 insertions(+), 97 deletions(-)
diff --git a/src/topology/channel.c b/src/topology/channel.c
index 47d5ea4c419a..ebdff46968f6 100644
--- a/src/topology/channel.c
+++ b/src/topology/channel.c
@@ -138,7 +138,8 @@ int tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg,
int tplg_save_channels(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct snd_soc_tplg_channel *channel,
- unsigned int count, char **dst, const char *pfx)
+ unsigned int count, struct tplg_buf *dst,
+ const char *pfx)
{
struct snd_soc_tplg_channel *c;
const char *s;
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
index 1d31b4944abf..a38399631c54 100644
--- a/src/topology/ctl.c
+++ b/src/topology/ctl.c
@@ -105,8 +105,8 @@ int parse_access(snd_config_t *cfg,
/* 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)
+ struct snd_soc_tplg_ctl_hdr *hdr,
+ struct tplg_buf *dst, const char *pfx)
{
const char *last;
unsigned int j, count, access, cval;
@@ -399,7 +399,7 @@ int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
/* save TLV data */
int tplg_save_tlv(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_ctl_tlv *tlv = elem->tlv;
struct snd_soc_tplg_tlv_dbscale *scale;
@@ -557,7 +557,7 @@ int tplg_parse_control_bytes(snd_tplg_t *tplg,
/* save control bytes */
int tplg_save_control_bytes(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_bytes_control *be = elem->bytes_ext;
char pfx2[16];
@@ -697,7 +697,7 @@ int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
/* save control eunm */
int tplg_save_control_enum(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_enum_control *ec = elem->enum_ctrl;
char pfx2[16];
@@ -858,8 +858,8 @@ int tplg_parse_control_mixer(snd_tplg_t *tplg,
}
int tplg_save_control_mixer(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
- struct tplg_elem *elem, char **dst,
- const char *pfx)
+ struct tplg_elem *elem,
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_mixer_control *mc = elem->mixer_ctrl;
char pfx2[16];
diff --git a/src/topology/dapm.c b/src/topology/dapm.c
index 73a9390340c2..46f2f8b3dae5 100644
--- a/src/topology/dapm.c
+++ b/src/topology/dapm.c
@@ -416,7 +416,8 @@ int tplg_parse_dapm_graph(snd_tplg_t *tplg, snd_config_t *cfg,
}
/* save DAPM graph */
-int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, char **dst, const char *pfx)
+int tplg_save_dapm_graph(snd_tplg_t *tplg, int index,
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_dapm_graph_elem *route;
struct list_head *pos;
@@ -669,7 +670,7 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg,
/* save DAPM widget */
int tplg_save_dapm_widget(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_dapm_widget *widget = elem->widget;
const char *s;
diff --git a/src/topology/data.c b/src/topology/data.c
index 5742b35773f6..3585af309499 100644
--- a/src/topology/data.c
+++ b/src/topology/data.c
@@ -121,7 +121,8 @@ int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem,
/* 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)
+ const char *id, struct tplg_buf *dst,
+ const char *pfx)
{
struct tplg_ref *ref, *last;
struct list_head *pos;
@@ -890,7 +891,7 @@ err:
/* 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_buf *dst, const char *pfx)
{
struct tplg_tuple_set *set;
struct tplg_tuple *tuple;
@@ -1014,7 +1015,7 @@ static int parse_tuple_sets(snd_config_t *cfg,
/* save tuple sets */
int tplg_save_tuple_sets(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct tplg_vendor_tuples *tuples = elem->tuples;
unsigned int i;
@@ -1085,7 +1086,7 @@ int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
/* save vendor tokens */
int tplg_save_tokens(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct tplg_vendor_tokens *tokens = elem->tokens;
unsigned int i;
@@ -1156,7 +1157,7 @@ int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
/* save vendor tuples */
int tplg_save_tuples(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
char pfx2[16];
int err;
@@ -1242,7 +1243,7 @@ int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg,
/* save manifest data */
int tplg_save_manifest_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
- struct tplg_elem *elem, char **dst,
+ struct tplg_elem *elem, struct tplg_buf *dst,
const char *pfx)
{
struct list_head *pos;
@@ -1420,7 +1421,7 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
/* save data element */
int tplg_save_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_private *priv = elem->data;
struct list_head *pos;
diff --git a/src/topology/ops.c b/src/topology/ops.c
index 110eef58851d..da175608557a 100644
--- a/src/topology/ops.c
+++ b/src/topology/ops.c
@@ -105,8 +105,8 @@ int tplg_parse_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *cfg,
/* 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)
+ struct snd_soc_tplg_ctl_hdr *hdr,
+ struct tplg_buf *dst, const char *pfx)
{
const char *s;
int err;
@@ -191,7 +191,7 @@ int tplg_parse_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
/* 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)
+ struct tplg_buf *dst, const char *pfx)
{
const char *s;
int err;
diff --git a/src/topology/pcm.c b/src/topology/pcm.c
index a60ba00d979a..191b7a0a92da 100644
--- a/src/topology/pcm.c
+++ b/src/topology/pcm.c
@@ -538,7 +538,7 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
/* save stream caps */
int tplg_save_stream_caps(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_stream_caps *sc = elem->stream_caps;
const char *s;
@@ -686,7 +686,7 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
/* 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)
+ struct tplg_buf *dst, const char *pfx)
{
static const char *stream_ids[2] = {
"playback",
@@ -778,7 +778,7 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
/* 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 tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_pcm *pcm = elem->pcm;
int err = 0;
@@ -810,7 +810,7 @@ static int parse_flag(snd_config_t *n, unsigned int mask_in,
}
static int save_flags(unsigned int flags, unsigned int mask,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
static unsigned int flag_masks[3] = {
SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES,
@@ -944,7 +944,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
/* save PCM */
int tplg_save_pcm(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_pcm *pcm = elem->pcm;
char pfx2[16];
@@ -1081,7 +1081,7 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
/* save DAI */
int tplg_save_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_dai *dai = elem->dai;
char pfx2[16];
@@ -1235,7 +1235,7 @@ int tplg_parse_link(snd_tplg_t *tplg, snd_config_t *cfg,
/* save physical link */
int tplg_save_link(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_link_config *link = elem->link;
char pfx2[16];
@@ -1315,7 +1315,7 @@ int tplg_parse_cc(snd_tplg_t *tplg, snd_config_t *cfg,
/* save CC */
int tplg_save_cc(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_link_config *link = elem->link;
char pfx2[16];
@@ -1611,7 +1611,7 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
/* save hw config */
int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct snd_soc_tplg_hw_config *hc = elem->hw_cfg;
int err;
diff --git a/src/topology/save.c b/src/topology/save.c
index 631d84b273bf..56250af308b2 100644
--- a/src/topology/save.c
+++ b/src/topology/save.c
@@ -19,25 +19,43 @@
#include "tplg_local.h"
#define SAVE_ALLOC_SHIFT (13) /* 8192 bytes */
-#define PRINT_BUF_SIZE (1024)
+#define PRINT_ALLOC_SHIFT (10) /* 1024 bytes */
#define PRINT_BUF_SIZE_MAX (1024 * 1024)
+#define NEXT_CHUNK(val, shift) ((((val) >> (shift)) + 1) << (shift))
-int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...)
+void tplg_buf_init(struct tplg_buf *buf)
+{
+ buf->dst = NULL;
+ buf->dst_len = 0;
+ buf->printf_buf = NULL;
+ buf->printf_buf_size = 0;
+}
+
+void tplg_buf_free(struct tplg_buf *buf)
+{
+ free(buf->dst);
+ free(buf->printf_buf);
+}
+
+char *tplg_buf_detach(struct tplg_buf *buf)
+{
+ char *ret = buf->dst;
+ free(buf->printf_buf);
+ return ret;
+}
+
+int tplg_save_printf(struct tplg_buf *dst, const char *pfx, const char *fmt, ...)
{
va_list va;
- char *buf, *s;
+ char *s;
size_t n, l, t, pl;
int ret = 0;
- buf = malloc(PRINT_BUF_SIZE);
- if (!buf)
- return -ENOMEM;
-
if (pfx == NULL)
pfx = "";
va_start(va, fmt);
- n = vsnprintf(buf, PRINT_BUF_SIZE, fmt, va);
+ n = vsnprintf(dst->printf_buf, dst->printf_buf_size, fmt, va);
va_end(va);
if (n >= PRINT_BUF_SIZE_MAX) {
@@ -45,42 +63,41 @@ int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...)
goto end;
}
- if (n >= PRINT_BUF_SIZE) {
- char *tmp = realloc(buf, n + 1);
- if (!tmp) {
+ if (n >= dst->printf_buf_size) {
+ t = NEXT_CHUNK(n + 1, PRINT_ALLOC_SHIFT);
+ s = realloc(dst->printf_buf, t);
+ if (!s) {
ret = -ENOMEM;
goto end;
}
- buf = tmp;
+ dst->printf_buf = s;
+ dst->printf_buf_size = t;
va_start(va, fmt);
- n = vsnprintf(buf, n + 1, fmt, va);
+ n = vsnprintf(dst->printf_buf, n + 1, fmt, va);
va_end(va);
}
pl = strlen(pfx);
- l = *dst ? strlen(*dst) : 0;
+ l = dst->dst_len;
t = l + pl + n + 1;
/* allocate chunks */
- if (*dst == NULL ||
+ if (dst->dst == NULL ||
(l >> SAVE_ALLOC_SHIFT) != (t >> SAVE_ALLOC_SHIFT)) {
- s = realloc(*dst, ((t >> SAVE_ALLOC_SHIFT) + 1) <<
- SAVE_ALLOC_SHIFT);
+ s = realloc(dst->dst, NEXT_CHUNK(t, SAVE_ALLOC_SHIFT));
if (s == NULL) {
- free(*dst);
- *dst = NULL;
ret = -ENOMEM;
goto end;
}
} else {
- s = *dst;
+ s = dst->dst;
}
if (pl > 0)
strcpy(s + l, pfx);
- strcpy(s + l + pl, buf);
- *dst = s;
+ strcpy(s + l + pl, dst->printf_buf);
+ dst->dst = s;
+ dst->dst_len = t - 1;
end:
- free(buf);
return ret;
}
@@ -209,7 +226,7 @@ static int tplg_check_quoted(const unsigned char *p)
return 0;
}
-static int tplg_save_quoted(char **dst, const char *str)
+static int tplg_save_quoted(struct tplg_buf *dst, const char *str)
{
static const char nibble[16] = "0123456789abcdef";
unsigned char *p, *d, *t;
@@ -263,7 +280,7 @@ static int tplg_save_quoted(char **dst, const char *str)
return tplg_save_printf(dst, NULL, "'%s'", d);
}
-static int tplg_save_string(char **dst, const char *str, int id)
+static int tplg_save_string(struct tplg_buf *dst, const char *str, int id)
{
const unsigned char *p = (const unsigned char *)str;
@@ -279,7 +296,7 @@ static int tplg_save_string(char **dst, const char *str, int id)
return tplg_save_printf(dst, NULL, "%s", str);
}
-static int save_config(char **dst, int level, const char *delim, snd_config_t *src)
+static int save_config(struct tplg_buf *dst, int level, const char *delim, snd_config_t *src)
{
snd_config_iterator_t i, next;
snd_config_t *s;
@@ -400,7 +417,8 @@ retval:
return 0;
}
-static int tplg_save(snd_tplg_t *tplg, char **dst, int gindex, const char *prefix)
+static int tplg_save(snd_tplg_t *tplg, struct tplg_buf *dst,
+ int gindex, const char *prefix)
{
struct tplg_table *tptr;
struct tplg_elem *elem;
@@ -484,8 +502,6 @@ static int tplg_save(snd_tplg_t *tplg, char **dst, int gindex, const char *prefi
return 0;
_err:
- free(*dst);
- *dst = NULL;
return err;
}
@@ -540,9 +556,9 @@ static int tplg_index_groups(snd_tplg_t *tplg, int **indexes)
int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags)
{
+ struct tplg_buf buf, buf2;
snd_input_t *in;
snd_config_t *top, *top2;
- char *dst2;
int *indexes, *a;
int err;
@@ -550,35 +566,41 @@ int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags)
assert(dst);
*dst = NULL;
+ tplg_buf_init(&buf);
+
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,
+ err = tplg_save_printf(&buf, NULL,
"IndexGroup.%d {\n",
*a);
if (err >= 0)
- err = tplg_save(tplg, dst, *a, "\t");
+ err = tplg_save(tplg, &buf, *a, "\t");
if (err >= 0)
- err = tplg_save_printf(dst, NULL, "}\n");
+ err = tplg_save_printf(&buf, NULL, "}\n");
}
free(indexes);
} else {
- err = tplg_save(tplg, dst, -1, NULL);
+ err = tplg_save(tplg, &buf, -1, NULL);
}
if (err < 0)
goto _err;
- if (*dst == NULL)
- return -EINVAL;
+ if (buf.dst == NULL) {
+ err = -EINVAL;
+ goto _err;
+ }
- if (flags & SND_TPLG_SAVE_NOCHECK)
+ if (flags & SND_TPLG_SAVE_NOCHECK) {
+ *dst = tplg_buf_detach(&buf);
return 0;
+ }
/* always load configuration - check */
- err = snd_input_buffer_open(&in, *dst, strlen(*dst));
+ err = snd_input_buffer_open(&in, buf.dst, strlen(buf.dst));
if (err < 0) {
SNDERR("could not create input buffer");
goto _err;
@@ -610,20 +632,20 @@ int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags)
top = top2;
}
- dst2 = NULL;
- err = save_config(&dst2, 0, NULL, top);
+ tplg_buf_init(&buf2);
+ err = save_config(&buf2, 0, NULL, top);
snd_config_delete(top);
if (err < 0) {
SNDERR("could not save configuration");
goto _err;
}
- free(*dst);
- *dst = dst2;
+ tplg_buf_free(&buf);
+ *dst = tplg_buf_detach(&buf2);
return 0;
_err:
- free(*dst);
+ tplg_buf_free(&buf);
*dst = NULL;
return err;
}
diff --git a/src/topology/text.c b/src/topology/text.c
index b899b2813ab4..b07feb999db9 100644
--- a/src/topology/text.c
+++ b/src/topology/text.c
@@ -93,7 +93,7 @@ int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,
/* save text data */
int tplg_save_text(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
struct tplg_elem *elem,
- char **dst, const char *pfx)
+ struct tplg_buf *dst, const char *pfx)
{
struct tplg_texts *texts = elem->texts;
unsigned int i;
diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h
index 0c7be2001a63..d553117e2333 100644
--- a/src/topology/tplg_local.h
+++ b/src/topology/tplg_local.h
@@ -200,6 +200,14 @@ struct map_elem {
int id;
};
+/* output buffer */
+struct tplg_buf {
+ char *dst;
+ size_t dst_len;
+ char *printf_buf;
+ size_t printf_buf_size;
+};
+
/* mapping table */
struct tplg_table {
const char *name;
@@ -214,9 +222,9 @@ struct tplg_table {
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);
+ struct tplg_buf *dst, const char *prefix);
int (*gsave)(snd_tplg_t *tplg, int index,
- char **dst, const char *prefix);
+ struct tplg_buf *dst, const char *prefix);
int (*decod)(snd_tplg_t *tplg, size_t pos,
struct snd_soc_tplg_hdr *hdr,
void *bin, size_t size);
@@ -348,49 +356,49 @@ 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_printf(struct tplg_buf *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);
+ const char *id, struct tplg_buf *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);
+ unsigned int channel_count, struct tplg_buf *dst, const char *pfx);
int tplg_save_ops(snd_tplg_t *tplg, struct snd_soc_tplg_ctl_hdr *hdr,
- char **dst, const char *pfx);
+ struct tplg_buf *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);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_manifest_data(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_control_mixer(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_control_enum(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_control_bytes(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_tlv(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_data(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_text(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_tokens(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_tuples(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_dapm_graph(snd_tplg_t *tplg, int index,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_dapm_widget(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_link(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_cc(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_pcm(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_hw_config(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_stream_caps(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_save_dai(snd_tplg_t *tplg, struct tplg_elem *elem,
- char **dst, const char *pfx);
+ struct tplg_buf *dst, const char *pfx);
int tplg_decode_template(snd_tplg_t *tplg,
size_t pos,
--
2.16.4

View File

@ -0,0 +1,111 @@
From 84185b5c94ec8a214103b8ec02d272f0158c24e6 Mon Sep 17 00:00:00 2001
From: "Tanjeff-N. Moos" <tanjeff@cccmz.de>
Date: Wed, 2 Sep 2020 11:27:26 +0200
Subject: [PATCH 31/32] control: Improve general control interface
documentation.
Signed-off-by: Tanjeff-N. Moos <tanjeff@cccmz.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/control/control.c | 72 ++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 63 insertions(+), 9 deletions(-)
diff --git a/src/control/control.c b/src/control/control.c
index 1bcf1ab2e431..497a5399b7e6 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -31,7 +31,7 @@
/*! \page control Control interface
<P>Control interface is designed to access primitive controls. There is
-also interface notifying about control and structure changes.
+also an interface for notifying about control and structure changes.
\section control_general_overview General overview
@@ -43,20 +43,74 @@ are managed according to below model.
Some element sets can be added to a sound card by drivers in kernel and
userspace applications.
- element
- - An element can be identified by userspace applications. Each element has
- own identical information.
+ - A control element might be a master volume control, for example, or a
+ read-only indicator, such as a sync status. An element has a type (e.g.
+ INTEGER or BOOLEAN) and - depending on the type - min/max values, a step
+ size, a set of possible values (for enums), etc.
- member
- - An element includes some members to have a value. The value of each member
- can be changed by both of userspace applications and drivers in kernel.
-Each element can be identified by two ways; the numerical number (numid), or the
-combination of interface, device, subdevice, name, and index.
+ - An element includes one or more member(s) to have a value. For
+ example, a stereo volume control element has two members (for
+ left/right). The members share the same properties (e.g. both
+ volume controls have the same min/max values). The value of each
+ member can be changed by both of userspace applications and
+ drivers in kernel.
-The type of element set is one of integer, integerr64, boolean, enumerators,
+
+\section identifying_elements Identifying the Elements
+
+Each element has the following identifying properties:
+
+ - The numid (a numeric identifier, assigned when the sound card is
+ detected, constant while the sound card is kept connected)
+
+ - The interface type (e.g. MIXER, CARD or PCM)
+ - The device
+ - The subdevice
+ - Its name
+ - Its index
+
+An element can be identified either by its numid or by the tuple
+(interface type, device, subdevice, name, index). This tuple is always
+the same (driver updates can change it, but in practice this is
+rare). The numid can change on each boot. In case of an USB sound
+card, the numid can also change when it is reconnected.
+
+
+\section element_lists Element Lists
+
+An element list can be used to obtain a list of all elements of the
+sound card. The list contains generic information (e.g. how many
+elements the card has), and the identifying properties of the elements
+(numid, card, name, ...). See #snd_ctl_elem_list_t to learn more about
+element lists.
+
+
+\section working_with_elements Working with Elements
+
+It is possible to obtain information about an element using the
+snd_ctl_elem_info_*() functions. For enums, the allowed values can be
+obtained, for integers, the min/max values can be obtained, and so
+on. In addition, these functions can report the identifying
+properties. E.g. when the element is addressed using its numid, the
+functions complements the name, index, etc.
+
+To access the values of a control, use the snd_ctl_elem_value*()
+functions. These allow to get and set the actual values or
+settings. It is also possible to get and set the ID values (such as
+the numid or the name).
+
+
+\section element_sets Element Sets
+
+The type of element set is one of integer, integer64, boolean, enumerators,
bytes and IEC958 structure. This indicates the type of value for each member in
elements included in the element set.
-When the value of member is changed, corresponding events are transferred to
+
+\section events Events
+
+When the value of a member is changed, corresponding events are transferred to
userspace applications. The applications should subscribe any events in advance.
\section tlv_blob Supplemental data for elements in an element set
--
2.16.4

View File

@ -0,0 +1,828 @@
From c1e72460de5ddcfdc8b93e73952c6fe9d6f60591 Mon Sep 17 00:00:00 2001
From: "Tanjeff-N. Moos" <tanjeff@cccmz.de>
Date: Wed, 2 Sep 2020 11:27:27 +0200
Subject: [PATCH 32/32] control: Add documentation for snd_ctl_elem_value_*.
Signed-off-by: Tanjeff-N. Moos <tanjeff@cccmz.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/control.h | 61 ++++++-
src/control/control.c | 454 +++++++++++++++++++++++++++++++++-----------------
2 files changed, 357 insertions(+), 158 deletions(-)
diff --git a/include/control.h b/include/control.h
index 9deec6f3dee4..8766f44097ea 100644
--- a/include/control.h
+++ b/include/control.h
@@ -130,7 +130,53 @@ typedef struct _snd_ctl_elem_list snd_ctl_elem_list_t;
/** CTL element info container */
typedef struct _snd_ctl_elem_info snd_ctl_elem_info_t;
-/** CTL element value container */
+/** CTL element value container
+ *
+ * Contains the value(s) (i.e. members) of a single element. All
+ * values of a given element are of the same type.
+ *
+ * \par Memory management
+ *
+ * To access a value, a snd_ctl_elem_value_t must be allocated using
+ * snd_ctl_elem_value_alloca() or snd_ctl_elem_value_malloc(). When
+ * using the latter, it must be freed again using
+ * snd_ctl_elem_value_free().
+ *
+ * \par Identifier
+ *
+ * Then, the ID must be filled. It is sufficient to fill only the
+ * numid, if known. Otherwise, interface type, device, subdevice,
+ * name, index must all be given. The following functions can be used
+ * to fill the ID:
+ *
+ * - snd_ctl_elem_value_set_id(): Set the ID. Requires an
+ * snd_ctl_elem_id_t object.
+ * - snd_ctl_elem_value_set_numid(): Set the numid.
+ * - Or use all of the following:
+ *
+ * - snd_ctl_elem_value_set_interface()
+ * - snd_ctl_elem_value_set_device()
+ * - snd_ctl_elem_value_set_subdevice()
+ * - snd_ctl_elem_value_set_name()
+ * - snd_ctl_elem_value_set_index()
+ *
+ * When communicating with the driver (snd_ctl_elem_read(),
+ * snd_ctl_elem_write()), and the numid was given, the interface,
+ * device, ... are filled (even if you set the before). When the numid
+ * is unset (i.e. it is 0), it is filled.
+ *
+ * \par Communicating with the driver
+ *
+ * After the value container was created and filled with the ID of the
+ * desired element, the value(s) can be fetched from the driver (and
+ * thus from the hardware) or written to the driver.
+ *
+ * To fetch a value, use snd_ctl_elem_read(). Thereafter, use the
+ * snd_ctl_elem_value_get_*() functions to obtain the actual value.
+ *
+ * To write a new value, first use a snd_ctl_elem_value_set_*() to set
+ * it, then call snd_ctl_elem_write() to write it to the driver.
+ */
typedef struct _snd_ctl_elem_value snd_ctl_elem_value_t;
/** CTL event container */
@@ -529,11 +575,20 @@ int snd_ctl_elem_add_iec958(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id);
int snd_ctl_elem_remove(snd_ctl_t *ctl, snd_ctl_elem_id_t *id);
size_t snd_ctl_elem_value_sizeof(void);
+
/** \hideinitializer
- * \brief allocate an invalid #snd_ctl_elem_value_t using standard alloca
- * \param ptr returned pointer
+ * \brief Allocate an invalid #snd_ctl_elem_value_t on the stack.
+ *
+ * Allocate space for a value object on the stack. The allocated
+ * memory need not be freed, because is on the stack.
+ *
+ * See snd_ctl_elem_value_t for details.
+ *
+ * \param ptr Pointer to a snd_ctl_elem_value_t pointer. The address
+ * of the allocated space will returned here.
*/
#define snd_ctl_elem_value_alloca(ptr) __snd_alloca(ptr, snd_ctl_elem_value)
+
int snd_ctl_elem_value_malloc(snd_ctl_elem_value_t **ptr);
void snd_ctl_elem_value_free(snd_ctl_elem_value_t *obj);
void snd_ctl_elem_value_clear(snd_ctl_elem_value_t *obj);
diff --git a/src/control/control.c b/src/control/control.c
index 497a5399b7e6..08058c067e28 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -38,32 +38,39 @@ also an interface for notifying about control and structure changes.
In ALSA control feature, each sound card can have control elements. The elements
are managed according to below model.
- - element set
+ - Element set
+
- A set of elements with the same attribute (i.e. name, get/put operations).
Some element sets can be added to a sound card by drivers in kernel and
userspace applications.
- - element
+
+ - Element
+
- A control element might be a master volume control, for example, or a
read-only indicator, such as a sync status. An element has a type (e.g.
- INTEGER or BOOLEAN) and - depending on the type - min/max values, a step
- size, a set of possible values (for enums), etc.
- - member
+ SNDRV_CTL_ELEM_TYPE_INTEGER or SNDRV_CTL_ELEM_TYPE_BOOLEAN) and - depending
+ on the type - min/max values, a step size, a set of possible values (for
+ enums), etc.
+
+ - Member
- - An element includes one or more member(s) to have a value. For
- example, a stereo volume control element has two members (for
- left/right). The members share the same properties (e.g. both
- volume controls have the same min/max values). The value of each
- member can be changed by both of userspace applications and
- drivers in kernel.
+ - An element usually includes one or more member(s) to have a value. For
+ example, a stereo volume control element has two members (for left/right),
+ while a mono volume has only one member. The member count can be obtained
+ using snd_ctl_elem_info_get_count(). Elements of type
+ "SNDRV_CTL_ELEM_TYPE_BYTES" or "SNDRV_CTL_ELEM_TYPE_IEC958" have no members
+ at all (and thus no member count), they have just a single value. The
+ members share the same properties (e.g. both volume control members have
+ the same min/max values). The value of each member can be changed by both
+ of userspace applications and drivers in kernel.
-\section identifying_elements Identifying the Elements
+\section identifying_elements Identifying Elements
Each element has the following identifying properties:
- The numid (a numeric identifier, assigned when the sound card is
detected, constant while the sound card is kept connected)
-
- The interface type (e.g. MIXER, CARD or PCM)
- The device
- The subdevice
@@ -95,10 +102,10 @@ on. In addition, these functions can report the identifying
properties. E.g. when the element is addressed using its numid, the
functions complements the name, index, etc.
-To access the values of a control, use the snd_ctl_elem_value*()
-functions. These allow to get and set the actual values or
-settings. It is also possible to get and set the ID values (such as
-the numid or the name).
+To access the members (i.e. values) of a control, use the
+snd_ctl_elem_value*() functions. These allow to get and set the
+actual values or settings. It is also possible to get and set the ID
+values (such as the numid or the name).
\section element_sets Element Sets
@@ -931,10 +938,19 @@ int snd_ctl_elem_remove(snd_ctl_t *ctl, snd_ctl_elem_id_t *id)
}
/**
- * \brief Get CTL element value
- * \param ctl CTL handle
- * \param data Data of an element.
- * \return 0 on success otherwise a negative error code
+ * \brief Get CTL element value.
+ *
+ * Read information from sound card. You must set the ID of the
+ * element before calling this function.
+ *
+ * See snd_ctl_elem_value_t for details.
+ *
+ * \param ctl CTL handle.
+ * \param data The element value. The ID must be set before calling
+ * the function, and the actual value will be returned
+ * here.
+ *
+ * \return 0 on success otherwise a negative error code.
*/
int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *data)
{
@@ -943,9 +959,16 @@ int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *data)
}
/**
- * \brief Set CTL element value
- * \param ctl CTL handle
- * \param data Data of an element.
+ * \brief Set CTL element value.
+ *
+ * Write new value(s) to the sound card. You must set the ID and the
+ * value of the element before calling this function.
+ *
+ * See snd_ctl_elem_value_t for details.
+ *
+ * \param ctl CTL handle.
+ * \param data The new value.
+ *
* \retval 0 on success
* \retval >0 on success when value was changed
* \retval <0 a negative error code
@@ -2877,9 +2900,16 @@ size_t snd_ctl_elem_value_sizeof()
}
/**
- * \brief Allocate an invalid #snd_ctl_elem_value_t using standard malloc(3).
- * \param ptr Returned pointer for data of an element.
- * \return 0 on success otherwise negative error code.
+ * \brief Allocate an invalid #snd_ctl_elem_value_t on the heap.
+ *
+ * Allocate space for a value object on the head. The allocated memory
+ * must be freed using snd_ctl_elem_value_free().
+ *
+ * See snd_ctl_elem_value_t for details.
+ *
+ * \param ptr Pointer to a snd_ctl_elem_value_t pointer. The address
+ * of the allocated space will be returned here.
+ * \return 0 on success, otherwise a negative error code.
*/
int snd_ctl_elem_value_malloc(snd_ctl_elem_value_t **ptr)
{
@@ -2891,8 +2921,10 @@ int snd_ctl_elem_value_malloc(snd_ctl_elem_value_t **ptr)
}
/**
- * \brief Frees a previously allocated data of an element.
- * \param obj Data of an element.
+ * \brief Free an #snd_ctl_elem_value_t previously allocated using
+ * snd_ctl_elem_value_malloc().
+ *
+ * \param obj Pointer to the snd_ctl_elem_value_t.
*/
void snd_ctl_elem_value_free(snd_ctl_elem_value_t *obj)
{
@@ -2901,6 +2933,9 @@ void snd_ctl_elem_value_free(snd_ctl_elem_value_t *obj)
/**
* \brief Clear given data of an element.
+ *
+ * See snd_ctl_elem_value_t for details.
+ *
* \param obj Data of an element.
*/
void snd_ctl_elem_value_clear(snd_ctl_elem_value_t *obj)
@@ -2909,7 +2944,7 @@ void snd_ctl_elem_value_clear(snd_ctl_elem_value_t *obj)
}
/**
- * \brief Copy two data of elements.
+ * \brief Bitwise copy of a snd_ctl_elem_value_t value.
* \param dst Pointer to destination.
* \param src Pointer to source.
*/
@@ -2921,9 +2956,10 @@ void snd_ctl_elem_value_copy(snd_ctl_elem_value_t *dst,
}
/**
- * \brief Compare one data of an element to the other.
- * \param left Pointer to first data.
- * \param right Pointer to second data.
+ * \brief Compare two snd_ctl_elem_value_t values, bytewise.
+ *
+ * \param left First value.
+ * \param right Second value.
* \return 0 on match, less than or greater than otherwise, see memcmp(3).
*/
int snd_ctl_elem_value_compare(snd_ctl_elem_value_t *left,
@@ -2934,9 +2970,13 @@ int snd_ctl_elem_value_compare(snd_ctl_elem_value_t *left,
}
/**
- * \brief Get element identifier from given data of an element.
- * \param obj Data of an element.
- * \param ptr Pointer for element identifier.
+ * \brief Get the element identifier from the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \param ptr Pointer to an identifier object. The identifier is
+ * stored there.
*/
void snd_ctl_elem_value_get_id(const snd_ctl_elem_value_t *obj, snd_ctl_elem_id_t *ptr)
{
@@ -2945,9 +2985,12 @@ void snd_ctl_elem_value_get_id(const snd_ctl_elem_value_t *obj, snd_ctl_elem_id_
}
/**
- * \brief Get element numeric identifier from given data of an element.
- * \param obj Data of an element.
- * \return Element numeric identifier.
+ * \brief Get the identifiers 'numid' part from the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \return The numid.
*/
unsigned int snd_ctl_elem_value_get_numid(const snd_ctl_elem_value_t *obj)
{
@@ -2956,10 +2999,12 @@ unsigned int snd_ctl_elem_value_get_numid(const snd_ctl_elem_value_t *obj)
}
/**
- * \brief Get interface part of element identifier from given data of an
- * element.
- * \param obj Data of an element.
- * \return Interface part of element identifier.
+ * \brief Get the identifiers 'interface' part from the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \return The interface part of element identifier.
*/
snd_ctl_elem_iface_t snd_ctl_elem_value_get_interface(const snd_ctl_elem_value_t *obj)
{
@@ -2968,9 +3013,12 @@ snd_ctl_elem_iface_t snd_ctl_elem_value_get_interface(const snd_ctl_elem_value_t
}
/**
- * \brief Get device part of element identifier from given data of an element.
- * \param obj Data of an element.
- * \return Device part of element identifier.
+ * \brief Get the identifiers 'device' part from the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \return The device part of element identifier.
*/
unsigned int snd_ctl_elem_value_get_device(const snd_ctl_elem_value_t *obj)
{
@@ -2979,10 +3027,12 @@ unsigned int snd_ctl_elem_value_get_device(const snd_ctl_elem_value_t *obj)
}
/**
- * \brief Get subdevice part of element identifier from given data of an
- * element.
- * \param obj Data of an element.
- * \return Subdevice part of element identifier.
+ * \brief Get the identifiers 'subdevice' part from the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \return The subdevice part of element identifier.
*/
unsigned int snd_ctl_elem_value_get_subdevice(const snd_ctl_elem_value_t *obj)
{
@@ -2991,9 +3041,12 @@ unsigned int snd_ctl_elem_value_get_subdevice(const snd_ctl_elem_value_t *obj)
}
/**
- * \brief Get name part of element identifier from given data of an element.
- * \param obj Data of an element.
- * \return Name part of element identifier.
+ * \brief Get the identifiers 'name' part from the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \return The "name" part of element identifier.
*/
const char *snd_ctl_elem_value_get_name(const snd_ctl_elem_value_t *obj)
{
@@ -3002,9 +3055,12 @@ const char *snd_ctl_elem_value_get_name(const snd_ctl_elem_value_t *obj)
}
/**
- * \brief Get index part of element identifier from given data of an element.
- * \param obj Data of an element.
- * \return Index part of element identifier.
+ * \brief Get the identifiers 'index' part from the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \return The index part of element identifier.
*/
unsigned int snd_ctl_elem_value_get_index(const snd_ctl_elem_value_t *obj)
{
@@ -3012,10 +3068,14 @@ unsigned int snd_ctl_elem_value_get_index(const snd_ctl_elem_value_t *obj)
return obj->id.index;
}
+
/**
- * \brief Set element identifier to given data of an element.
- * \param obj Data of an element.
- * \param ptr Pointer to an element identifier.
+ * \brief Set the element identifier within the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \param ptr The new identifier.
*/
void snd_ctl_elem_value_set_id(snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_t *ptr)
{
@@ -3024,9 +3084,12 @@ void snd_ctl_elem_value_set_id(snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_
}
/**
- * \brief Set numeric identifier to given data of an element.
- * \param obj Data of an element.
- * \param val Value for numeric identifier.
+ * \brief Set the identifiers 'numid' part within the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \param val The new numid.
*/
void snd_ctl_elem_value_set_numid(snd_ctl_elem_value_t *obj, unsigned int val)
{
@@ -3035,9 +3098,12 @@ void snd_ctl_elem_value_set_numid(snd_ctl_elem_value_t *obj, unsigned int val)
}
/**
- * \brief Set interface part of element identifier to given data of an element.
- * \param obj Data of an element.
- * \param val Value for interface part of element identifier.
+ * \brief Set the identifiers 'interface' part within the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \param val The new interface.
*/
void snd_ctl_elem_value_set_interface(snd_ctl_elem_value_t *obj, snd_ctl_elem_iface_t val)
{
@@ -3046,9 +3112,12 @@ void snd_ctl_elem_value_set_interface(snd_ctl_elem_value_t *obj, snd_ctl_elem_if
}
/**
- * \brief Set device part of element identifier to given data of an element.
- * \param obj Data of an element.
- * \param val Value for device part of element identifier.
+ * \brief Set the identifiers 'device' part within the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \param val The new device.
*/
void snd_ctl_elem_value_set_device(snd_ctl_elem_value_t *obj, unsigned int val)
{
@@ -3057,9 +3126,12 @@ void snd_ctl_elem_value_set_device(snd_ctl_elem_value_t *obj, unsigned int val)
}
/**
- * \brief Set subdevice part of element identifier to given data of an element.
- * \param obj Data of an element.
- * \param val Value for subdevice part of element identifier.
+ * \brief Set the identifiers 'subdevice' part within the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \param val The new subdevice.
*/
void snd_ctl_elem_value_set_subdevice(snd_ctl_elem_value_t *obj, unsigned int val)
{
@@ -3068,9 +3140,12 @@ void snd_ctl_elem_value_set_subdevice(snd_ctl_elem_value_t *obj, unsigned int va
}
/**
- * \brief Set name part of element identifier to given data of an element.
- * \param obj Data of an element.
- * \param val Value for name part of element identifier,
+ * \brief Set the identifiers 'name' part within the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \param val The new name.
*/
void snd_ctl_elem_value_set_name(snd_ctl_elem_value_t *obj, const char *val)
{
@@ -3079,9 +3154,12 @@ void snd_ctl_elem_value_set_name(snd_ctl_elem_value_t *obj, const char *val)
}
/**
- * \brief Set index part of element identifier to given data of an element.
- * \param obj Data of an element.
- * \param val Value for index part of element identifier.
+ * \brief Set the identifiers 'index' part within the given element value.
+ *
+ * See snd_ctl_elem_value_t for more details.
+ *
+ * \param obj The element value.
+ * \param val The new index.
*/
void snd_ctl_elem_value_set_index(snd_ctl_elem_value_t *obj, unsigned int val)
{
@@ -3090,12 +3168,16 @@ void snd_ctl_elem_value_set_index(snd_ctl_elem_value_t *obj, unsigned int val)
}
/**
- * \brief Get value of a specified member from given data as an element of
- * boolean type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \return Value for the member.
- */
+ * \brief Get an element members value.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BOOLEAN. It
+ * returns the value of one member. See \ref snd_ctl_elem_value_t and \ref
+ * control for more details.
+ *
+ * \param obj The element value object
+ * \param idx The index of the member.
+ * \return The members value.
+ */
int snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t *obj, unsigned int idx)
{
assert(obj);
@@ -3104,12 +3186,16 @@ int snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t *obj, unsigned int
}
/**
- * \brief Get value of a specified member from given data as an element of
- * integer type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \return Value for the member.
- */
+ * \brief Get an element members value.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_INTEGER. It
+ * returns the value of one member. See \ref snd_ctl_elem_value_t and \ref
+ * control for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the member.
+ * \return The members value.
+ */
long snd_ctl_elem_value_get_integer(const snd_ctl_elem_value_t *obj, unsigned int idx)
{
assert(obj);
@@ -3118,12 +3204,16 @@ long snd_ctl_elem_value_get_integer(const snd_ctl_elem_value_t *obj, unsigned in
}
/**
- * \brief Get value of a specified member from given data as an element of
- * integer64 type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \return Value for the member.
- */
+ * \brief Get an element members value.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_INTEGER64. It
+ * returns the value of one member. See \ref snd_ctl_elem_value_t and \ref
+ * control for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the member.
+ * \return The members value.
+ */
long long snd_ctl_elem_value_get_integer64(const snd_ctl_elem_value_t *obj, unsigned int idx)
{
assert(obj);
@@ -3132,12 +3222,16 @@ long long snd_ctl_elem_value_get_integer64(const snd_ctl_elem_value_t *obj, unsi
}
/**
- * \brief Get value of a specified member from given data as an element of
- * enumerated type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \return Value for the member. This is an index of name set in the element.
- */
+ * \brief Get an element members value.
+ *
+ * Use this function if the element is of type
+ * SNDRV_CTL_ELEM_TYPE_ENUMERATED. It returns the index of the active item. See
+ * \ref snd_ctl_elem_value_t and \ref control for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the requested member.
+ * \return The index of the active item.
+ */
unsigned int snd_ctl_elem_value_get_enumerated(const snd_ctl_elem_value_t *obj, unsigned int idx)
{
assert(obj);
@@ -3146,12 +3240,16 @@ unsigned int snd_ctl_elem_value_get_enumerated(const snd_ctl_elem_value_t *obj,
}
/**
- * \brief Get value of a specified member from given data as an element of
- * bytes type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \return Value for the member.
- */
+ * \brief Get an element members value.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BYTE. It
+ * returns the value of one member. See \ref snd_ctl_elem_value_t and \ref
+ * control for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the member.
+ * \return The members value.
+ */
unsigned char snd_ctl_elem_value_get_byte(const snd_ctl_elem_value_t *obj, unsigned int idx)
{
assert(obj);
@@ -3160,12 +3258,16 @@ unsigned char snd_ctl_elem_value_get_byte(const snd_ctl_elem_value_t *obj, unsig
}
/**
- * \brief Set value of a specified member to given data as an element of
- * boolean type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \param val Value for the member.
- */
+ * \brief Set an element members value.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BOOLEAN. It
+ * sets the value of one member. See \ref snd_ctl_elem_value_t and \ref control
+ * for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the member.
+ * \param val The new value.
+ */
void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
{
assert(obj);
@@ -3174,12 +3276,16 @@ void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx,
}
/**
- * \brief Set value of a specified member to given data as an element of
- * integer type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \param val Value for the member.
- */
+ * \brief Set an element members value.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_INTEGER. It
+ * sets the value of one member. See \ref snd_ctl_elem_value_t and \ref control
+ * for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the member.
+ * \param val The new value.
+ */
void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx, long val)
{
assert(obj);
@@ -3188,12 +3294,16 @@ void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx,
}
/**
- * \brief Set value of a specified member to given data as an element of
- * integer64 type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \param val Value for the member.
- */
+ * \brief Set an element members value.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_INTEGER64. It
+ * sets the value of one member. See \ref snd_ctl_elem_value_t and \ref control
+ * for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the member.
+ * \param val The new value.
+ */
void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int idx, long long val)
{
assert(obj);
@@ -3202,12 +3312,16 @@ void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int id
}
/**
- * \brief Set value of a specified member to given data as an element of
- * enumerated type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \param val Value for the member.
- */
+ * \brief Set an element members value.
+ *
+ * Use this function if the element is of type
+ * SNDRV_CTL_ELEM_TYPE_ENUMERATED. It activates the specified item. See \ref
+ * snd_ctl_elem_value_t and \ref control for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the requested member.
+ * \param val The new index of the item to be activated.
+ */
void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int idx, unsigned int val)
{
assert(obj);
@@ -3216,12 +3330,16 @@ void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int i
}
/**
- * \brief Set value for a specified member to given data as an element of byte
- * type.
- * \param obj Data of an element.
- * \param idx Index of member in the element.
- * \param val Value for the member.
- */
+ * \brief Set an element members value.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BYTE. It
+ * sets the value of one member. See \ref snd_ctl_elem_value_t and \ref control
+ * for more details.
+ *
+ * \param obj The element value object.
+ * \param idx The index of the member.
+ * \param val The new value.
+ */
void snd_ctl_elem_value_set_byte(snd_ctl_elem_value_t *obj, unsigned int idx, unsigned char val)
{
assert(obj);
@@ -3230,10 +3348,17 @@ void snd_ctl_elem_value_set_byte(snd_ctl_elem_value_t *obj, unsigned int idx, un
}
/**
- * \brief Set values to given data as an element of bytes type.
- * \param obj Data of an element.
- * \param data Pointer for byte array.
- * \param size The number of bytes included in the memory block.
+ * \brief Replace the data stored within the element.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BYTES. It
+ * replaces the data stored in the element. Note that "bytes" elements don't
+ * have members. They have only one single block of data.
+ *
+ * See \ref snd_ctl_elem_value_t and \ref control for more details.
+ *
+ * \param obj The element value object.
+ * \param data Pointer to the new data.
+ * \param size The size of the new data, in bytes.
*/
void snd_ctl_elem_set_bytes(snd_ctl_elem_value_t *obj, void *data, size_t size)
{
@@ -3243,10 +3368,17 @@ void snd_ctl_elem_set_bytes(snd_ctl_elem_value_t *obj, void *data, size_t size)
}
/**
- * \brief Get memory block from given data as an element of bytes type.
- * \param obj Data of an element.
- * \return Pointer for byte array.
- */
+ * \brief Get the data stored within the element.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BYTES. It
+ * returns the data stored in the element. Note that "bytes" elements don't have
+ * members. They have only one single block of data.
+ *
+ * See \ref snd_ctl_elem_value_t and \ref control for more details.
+ *
+ * \param obj The element value object.
+ * \return Pointer to the elements data.
+ */
const void * snd_ctl_elem_value_get_bytes(const snd_ctl_elem_value_t *obj)
{
assert(obj);
@@ -3254,11 +3386,17 @@ const void * snd_ctl_elem_value_get_bytes(const snd_ctl_elem_value_t *obj)
}
/**
- * \brief Get value from given data to given pointer as an element of IEC958
- * type.
- * \param obj Data of an element.
- * \param ptr Pointer to IEC958 data.
- */
+ * \brief Get an elements IEC958 data.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_IEC958. Note that
+ * "IEC958" elements don't have members. They have only one single
+ * IEC958 information block.
+ *
+ * See \ref snd_ctl_elem_value_t and \ref control for more details.
+ *
+ * \param obj The element value object.
+ * \param ptr Pointer to an IEC958 structure. The data is stored there.
+ */
void snd_ctl_elem_value_get_iec958(const snd_ctl_elem_value_t *obj, snd_aes_iec958_t *ptr)
{
assert(obj && ptr);
@@ -3266,11 +3404,17 @@ void snd_ctl_elem_value_get_iec958(const snd_ctl_elem_value_t *obj, snd_aes_iec9
}
/**
- * \brief Set value from given pointer to given data as an element of IEC958
- * type.
- * \param obj Data of an element.
- * \param ptr Pointer to IEC958 data.
- */
+ * \brief Set an elements IEC958 data.
+ *
+ * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_IEC958. Note
+ * that "IEC958" elements don't have members. They have only one single IEC958
+ * information block.
+ *
+ * See \ref snd_ctl_elem_value_t and \ref control for more details.
+ *
+ * \param obj The element value object.
+ * \param ptr Pointer to the new IEC958 data.
+ */
void snd_ctl_elem_value_set_iec958(snd_ctl_elem_value_t *obj, const snd_aes_iec958_t *ptr)
{
assert(obj && ptr);
--
2.16.4

View File

@ -1,3 +1,46 @@
-------------------------------------------------------------------
Tue Sep 29 08:57:00 UTC 2020 - Guillaume GARDET <guillaume.gardet@opensuse.org>
- Enable topology support for aarch64
-------------------------------------------------------------------
Wed Sep 23 16:49:23 CEST 2020 - tiwai@suse.de
- Backport upstream fixes:
0001-ucm-substitution-remove-duplicate-allow_empty-assign.patch
0002-ucm-fix-parse_get_safe_name-safe-name-must-be-checke.patch
0003-ucm-substitute-the-merged-tree-completely.patch
0004-ctl-improve-documentation-for-identifier-of-control-.patch
0005-pcm-dmix-make-lockless-operation-optional.patch
0006-pcm-dmix-Fix-semaphore-usage-with-lockless-operation.patch
0007-pcm-iec958-implement-HDMI-HBR-audio-formatting.patch
0008-pcm-iec958-set-channel-status-bits-according-to-rate.patch
0009-conf-pcm-USB-Added-S-PDIF-fix-for-Asus-Xonar-SE.patch
0010-control-ctlparse-fix-enum-values-in-or.patch
0011-conf-USB-Audio-Disable-IEC958-on-Lenovo-ThinkStation.patch
0012-pcm-dmix-fix-access-to-sum-buffer-in-non-interleaved.patch
0014-control-Add-documentation-for-snd_ctl_elem_list_.patch
0015-conf-quote-also-strings-with-and-characters-in-strin.patch
0016-topology-decode-Fix-channel-map-memory-allocation.patch
0017-topology-decode-Fix-infinite-loop-in-decoding-enum-c.patch
0018-topology-decode-Remove-decoding-values-for-enum-cont.patch
0019-topology-decode-Add-enum-control-texts-as-separate-e.patch
0020-topology-decode-Fix-printing-texts-section.patch
0021-topology-decode-Change-declaration-of-enum-decoding-.patch
0022-topology-decode-Fix-decoding-PCM-formats-and-rates.patch
0023-topology-decode-Print-sig_bits-field-in-PCM-capabili.patch
0024-topology-decode-Add-DAI-name-printing.patch
0025-topology-Make-buffer-for-saving-dynamic-size.patch
0026-topology-return-correct-value-in-tplg_save_printf.patch
0027-topology-fix-some-gcc10-warnings-labs-signess.patch
0028-topology-fix-sort_config.patch
0029-topology-fix-the-unaligned-access.patch
0030-topology-improve-the-printf-buffer-management.patch
0031-control-Improve-general-control-interface-documentat.patch
0032-control-Add-documentation-for-snd_ctl_elem_value_.patch
- Build topology library conditionally;
currently it's supported only for little-endian
-------------------------------------------------------------------
Thu Jul 9 16:01:13 CEST 2020 - tiwai@suse.de

View File

@ -25,6 +25,12 @@
%define _udevrulesdir /lib/udev/rules.d/
%endif
%ifarch %ix86 x86_64 %arm aarch64 ppc64le
%define enable_topology 1
%else
%define enable_topology 0
%endif
Name: alsa
Version: 1.2.3.2
Release: 0
@ -47,6 +53,37 @@ Source30: all_notes_off
Source31: all_notes_off.bin
Source32: all_notes_off.mid
Source34: alsa-init.sh
Patch1: 0001-ucm-substitution-remove-duplicate-allow_empty-assign.patch
Patch2: 0002-ucm-fix-parse_get_safe_name-safe-name-must-be-checke.patch
Patch3: 0003-ucm-substitute-the-merged-tree-completely.patch
Patch4: 0004-ctl-improve-documentation-for-identifier-of-control-.patch
Patch5: 0005-pcm-dmix-make-lockless-operation-optional.patch
Patch6: 0006-pcm-dmix-Fix-semaphore-usage-with-lockless-operation.patch
Patch7: 0007-pcm-iec958-implement-HDMI-HBR-audio-formatting.patch
Patch8: 0008-pcm-iec958-set-channel-status-bits-according-to-rate.patch
Patch9: 0009-conf-pcm-USB-Added-S-PDIF-fix-for-Asus-Xonar-SE.patch
Patch10: 0010-control-ctlparse-fix-enum-values-in-or.patch
Patch11: 0011-conf-USB-Audio-Disable-IEC958-on-Lenovo-ThinkStation.patch
Patch12: 0012-pcm-dmix-fix-access-to-sum-buffer-in-non-interleaved.patch
Patch14: 0014-control-Add-documentation-for-snd_ctl_elem_list_.patch
Patch15: 0015-conf-quote-also-strings-with-and-characters-in-strin.patch
Patch16: 0016-topology-decode-Fix-channel-map-memory-allocation.patch
Patch17: 0017-topology-decode-Fix-infinite-loop-in-decoding-enum-c.patch
Patch18: 0018-topology-decode-Remove-decoding-values-for-enum-cont.patch
Patch19: 0019-topology-decode-Add-enum-control-texts-as-separate-e.patch
Patch20: 0020-topology-decode-Fix-printing-texts-section.patch
Patch21: 0021-topology-decode-Change-declaration-of-enum-decoding-.patch
Patch22: 0022-topology-decode-Fix-decoding-PCM-formats-and-rates.patch
Patch23: 0023-topology-decode-Print-sig_bits-field-in-PCM-capabili.patch
Patch24: 0024-topology-decode-Add-DAI-name-printing.patch
Patch25: 0025-topology-Make-buffer-for-saving-dynamic-size.patch
Patch26: 0026-topology-return-correct-value-in-tplg_save_printf.patch
Patch27: 0027-topology-fix-some-gcc10-warnings-labs-signess.patch
Patch28: 0028-topology-fix-sort_config.patch
Patch29: 0029-topology-fix-the-unaligned-access.patch
Patch30: 0030-topology-improve-the-printf-buffer-management.patch
Patch31: 0031-control-Improve-general-control-interface-documentat.patch
Patch32: 0032-control-Add-documentation-for-snd_ctl_elem_value_.patch
# rest suse fixes
Patch101: alsa-lib-ignore-non-accessible-ALSA_CONFIG_PATH.patch
BuildRequires: doxygen
@ -88,6 +125,7 @@ Provides: alsadev = %{version}
This package contains all necessary include files and libraries needed
to develop applications that require ALSA.
%if %enable_topology
%package topology-devel
Summary: Header files for ALSA topology development
License: LGPL-2.1-or-later
@ -98,6 +136,7 @@ Requires: libatopology2 = %{version}
%description topology-devel
This package contains all necessary include files and libraries needed
to develop applications that require ALSA topology.
%endif
%package docs
Summary: Additional Package Documentation for ALSA
@ -121,6 +160,7 @@ Provides: alsa-lib
This package contains the library for ALSA, Advanced Linux Sound
Architecture.
%if %enable_topology
%package -n libatopology2
Summary: ALSA Topology Library
License: LGPL-2.1-or-later
@ -128,9 +168,41 @@ Group: System/Libraries
%description -n libatopology2
This package contains the library for ALSA topology support.
%endif
%prep
%setup -q -n alsa-lib-%{version}
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch101 -p1
%build
@ -144,6 +216,9 @@ autoreconf -fi
--enable-symbolic-functions \
--disable-aload \
--disable-alisp \
%if !%enable_topology
--disable-topology \
%endif
--disable-python
make V=1 %{?_smp_mflags}
# run doxygen
@ -156,6 +231,9 @@ make -C doc doc %{?_smp_mflags}
rm -f %{buildroot}%{_libdir}/*.*a
# rm -f %{buildroot}%{_libdir}/alsa-lib/smixer/*.*a
rm -f %{buildroot}%{_bindir}/aserver
%if !%enable_topology
rm -f %{buildroot}%{_libdir}/pkgconfig/alsa-topology.pc
%endif
#
# install helper scripts
mkdir -p %{buildroot}%{_bindir}
@ -242,8 +320,10 @@ exit 0
%post -n libasound2 -p /sbin/ldconfig
%postun -n libasound2 -p /sbin/ldconfig
%if %enable_topology
%post -n libatopology2 -p /sbin/ldconfig
%postun -n libatopology2 -p /sbin/ldconfig
%endif
%files
%defattr(-, root, root)
@ -266,16 +346,20 @@ exit 0
%{_libdir}/libasound.so
%{_includedir}/sys/*
%{_includedir}/alsa
%if %enable_topology
%exclude %{_includedir}/alsa/topology.h
%endif
%{_includedir}/asoundlib.h
%{_datadir}/aclocal/*.m4
%{_libdir}/pkgconfig/alsa.pc
%if %enable_topology
%files topology-devel
%defattr(-, root, root)
%{_libdir}/libatopology.so
%{_includedir}/alsa/topology.h
%{_libdir}/pkgconfig/alsa-topology.pc
%endif
%files docs
%defattr(-, root, root)
@ -286,8 +370,10 @@ exit 0
%{_libdir}/libasound.so.*
%{_datadir}/alsa
%if %enable_topology
%files -n libatopology2
%defattr(-, root, root)
%{_libdir}/libatopology.so.*
%endif
%changelog