db6034
From 1b436862ed6253629d79edc2e09826efd4e0f4e3 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 2 Nov 2022 15:01:56 +0100
db6034
Subject: [PATCH 01/20] ucm: fix enhanced ID parsing in
db6034
 snd_use_case_parse_ctl_elem_id()
db6034
db6034
Reported-by: Takashi Iwai <tiwai@suse.de>
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/ucm/main.c | 2 +-
db6034
 1 file changed, 1 insertion(+), 1 deletion(-)
db6034
db6034
diff --git a/src/ucm/main.c b/src/ucm/main.c
db6034
index 30ab1e41..28c60565 100644
db6034
--- a/src/ucm/main.c
db6034
+++ b/src/ucm/main.c
db6034
@@ -2793,7 +2793,7 @@ int snd_use_case_parse_ctl_elem_id(snd_ctl_elem_id_t *dst,
db6034
 	    strcmp(ucm_id, "CaptureSwitch"))
db6034
 		return -EINVAL;
db6034
 	snd_ctl_elem_id_clear(dst);
db6034
-	if (strcasestr(ucm_id, "name="))
db6034
+	if (strcasestr(value, "name="))
db6034
 		return __snd_ctl_ascii_elem_id_parse(dst, value, NULL);
db6034
 	iface = SND_CTL_ELEM_IFACE_MIXER;
db6034
 	if (jack_control)
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From aa4f56c3c952269c36464cc0da9db5a1381648fa Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 9 Nov 2022 08:11:42 +0100
db6034
Subject: [PATCH 02/20] pcm: rate - fix the crash in
db6034
 snd_pcm_rate_may_wait_for_avail_min()
db6034
db6034
The pcm argument passed to the conversion function in
db6034
snd_pcm_plugin_may_wait_for_avail_min_conv() should be
db6034
pcm->fast_op_arg.
db6034
db6034
Test command: arecord -Dplughw:x -r12000 -c2 -fS16_LE -M temp.wav
db6034
db6034
Fixes: d9dbb57b ("pcm: rate - rewrite the may_wait_for_avail_min callback for the rate plugin")
db6034
db6034
BugLink: https://lore.kernel.org/alsa-devel/1667793912-18957-1-git-send-email-shengjiu.wang@nxp.com/
db6034
Fixes: https://github.com/alsa-project/alsa-lib/issues/282
db6034
Reported-by: Shengjiu Wang <shengjiu.wang@nxp.com>
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/pcm/pcm_plugin.c | 2 +-
db6034
 1 file changed, 1 insertion(+), 1 deletion(-)
db6034
db6034
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
db6034
index 6bb90b8b..ec64604c 100644
db6034
--- a/src/pcm/pcm_plugin.c
db6034
+++ b/src/pcm/pcm_plugin.c
db6034
@@ -622,7 +622,7 @@ int snd_pcm_plugin_may_wait_for_avail_min_conv(
db6034
 		 * This code is also used by extplug, but extplug does not allow to alter the sampling rate.
db6034
 		 */
db6034
 		if (conv)
db6034
-			needed_slave_avail_min = conv(pcm, needed_slave_avail_min);
db6034
+			needed_slave_avail_min = conv(pcm->fast_op_arg, needed_slave_avail_min);
db6034
 
db6034
 		if (slave->avail_min != needed_slave_avail_min) {
db6034
 			snd_pcm_sw_params_t *swparams;
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 39060852d810461dc8cd1464cfb2ffe84da42d56 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 9 Nov 2022 09:31:34 +0100
db6034
Subject: [PATCH 03/20] pcm: rate - correct the previous fix for
db6034
 snd_pcm_rate_may_wait_for_avail_min()
db6034
db6034
The previous fix in aa4f56c3 was not correct. The root of the cause is
db6034
implementation in snd_pcm_may_wait_for_avail_min() inline function
db6034
where the improper pcm argument is passed to the fast_ops function.
db6034
db6034
Fixes: aa4f56c3 ("pcm: rate - fix the crash in snd_pcm_rate_may_wait_for_avail_min()")
db6034
Fixes: d9dbb57b ("pcm: rate - rewrite the may_wait_for_avail_min callback for the rate plugin")
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/pcm/pcm_local.h  |  2 +-
db6034
 src/pcm/pcm_plugin.c | 10 +++++++---
db6034
 2 files changed, 8 insertions(+), 4 deletions(-)
db6034
db6034
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
db6034
index 8d25971f..ae0c44bf 100644
db6034
--- a/src/pcm/pcm_local.h
db6034
+++ b/src/pcm/pcm_local.h
db6034
@@ -1144,7 +1144,7 @@ static inline int snd_pcm_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes
db6034
 	if (avail >= pcm->avail_min)
db6034
 		return 0;
db6034
 	if (pcm->fast_ops->may_wait_for_avail_min)
db6034
-		return pcm->fast_ops->may_wait_for_avail_min(pcm, avail);
db6034
+		return pcm->fast_ops->may_wait_for_avail_min(pcm->fast_op_arg, avail);
db6034
 	return 1;
db6034
 }
db6034
 
db6034
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
db6034
index ec64604c..b3af1fb7 100644
db6034
--- a/src/pcm/pcm_plugin.c
db6034
+++ b/src/pcm/pcm_plugin.c
db6034
@@ -597,8 +597,12 @@ int snd_pcm_plugin_may_wait_for_avail_min_conv(
db6034
 		 * a) the slave can provide contineous hw_ptr between periods
db6034
 		 * b) avail_min does not match one slave_period
db6034
 		 */
db6034
-		snd_pcm_plugin_t *plugin = pcm->private_data;
db6034
-		snd_pcm_t *slave = plugin->gen.slave;
db6034
+		snd_pcm_generic_t *generic = pcm->private_data;
db6034
+		/*
db6034
+		 * do not use snd_pcm_plugin_t pointer here
db6034
+		 * this code is used from the generic plugins, too
db6034
+		 */
db6034
+		snd_pcm_t *slave = generic->slave;
db6034
 		snd_pcm_uframes_t needed_slave_avail_min;
db6034
 		snd_pcm_sframes_t available;
db6034
 
db6034
@@ -622,7 +626,7 @@ int snd_pcm_plugin_may_wait_for_avail_min_conv(
db6034
 		 * This code is also used by extplug, but extplug does not allow to alter the sampling rate.
db6034
 		 */
db6034
 		if (conv)
db6034
-			needed_slave_avail_min = conv(pcm->fast_op_arg, needed_slave_avail_min);
db6034
+			needed_slave_avail_min = conv(pcm, needed_slave_avail_min);
db6034
 
db6034
 		if (slave->avail_min != needed_slave_avail_min) {
db6034
 			snd_pcm_sw_params_t *swparams;
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 161f47da5f196c291ac0e11d066fa5ff5f79fa04 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 9 Nov 2022 14:37:45 +0100
db6034
Subject: [PATCH 04/20] include: pcm_old.h - use a macro for the symbol
db6034
 versioning
db6034
db6034
Make the header file more readable and error prone.
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 include/pcm_old.h | 133 ++++++++++++++++++++++++----------------------
db6034
 1 file changed, 68 insertions(+), 65 deletions(-)
db6034
db6034
diff --git a/include/pcm_old.h b/include/pcm_old.h
db6034
index e6e050fc..a9f5308f 100644
db6034
--- a/include/pcm_old.h
db6034
+++ b/include/pcm_old.h
db6034
@@ -2,11 +2,14 @@
db6034
  * Old ALSA 0.9.x API
db6034
  */
db6034
 
db6034
+#define ___symbol_version(name, version) \
db6034
+	__asm__ (".symver " #name "," #name "@" version)
db6034
+
db6034
 #ifdef ALSA_PCM_OLD_HW_PARAMS_API
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_access,snd_pcm_hw_params_get_access@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_access_first,snd_pcm_hw_params_set_access_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_access_last,snd_pcm_hw_params_set_access_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_access, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_access_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_access_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_get_access(const snd_pcm_hw_params_t *params);
db6034
 int snd_pcm_hw_params_test_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t val);
db6034
@@ -16,9 +19,9 @@ snd_pcm_access_t snd_pcm_hw_params_set_access_last(snd_pcm_t *pcm, snd_pcm_hw_pa
db6034
 int snd_pcm_hw_params_set_access_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask);
db6034
 void snd_pcm_hw_params_get_access_mask(snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_format,snd_pcm_hw_params_get_format@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_format_first,snd_pcm_hw_params_set_format_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_format_last,snd_pcm_hw_params_set_format_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_format, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_format_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_format_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_get_format(const snd_pcm_hw_params_t *params);
db6034
 int snd_pcm_hw_params_test_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val);
db6034
@@ -28,9 +31,9 @@ snd_pcm_format_t snd_pcm_hw_params_set_format_last(snd_pcm_t *pcm, snd_pcm_hw_pa
db6034
 int snd_pcm_hw_params_set_format_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask);
db6034
 void snd_pcm_hw_params_get_format_mask(snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_subformat,snd_pcm_hw_params_get_subformat@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_subformat_first,snd_pcm_hw_params_set_subformat_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_subformat_last,snd_pcm_hw_params_set_subformat_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_subformat, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_subformat_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_subformat_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_test_subformat(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t val);
db6034
 int snd_pcm_hw_params_get_subformat(const snd_pcm_hw_params_t *params);
db6034
@@ -40,12 +43,12 @@ snd_pcm_subformat_t snd_pcm_hw_params_set_subformat_last(snd_pcm_t *pcm, snd_pcm
db6034
 int snd_pcm_hw_params_set_subformat_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask);
db6034
 void snd_pcm_hw_params_get_subformat_mask(snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_channels,snd_pcm_hw_params_get_channels@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_channels_min,snd_pcm_hw_params_get_channels_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_channels_max,snd_pcm_hw_params_get_channels_max@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_channels_near,snd_pcm_hw_params_set_channels_near@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_channels_first,snd_pcm_hw_params_set_channels_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_channels_last,snd_pcm_hw_params_set_channels_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_channels, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_channels_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_channels_max, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_channels_near, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_channels_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_channels_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_get_channels(const snd_pcm_hw_params_t *params);
db6034
 unsigned int snd_pcm_hw_params_get_channels_min(const snd_pcm_hw_params_t *params);
db6034
@@ -59,12 +62,12 @@ unsigned int snd_pcm_hw_params_set_channels_near(snd_pcm_t *pcm, snd_pcm_hw_para
db6034
 unsigned int snd_pcm_hw_params_set_channels_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
db6034
 unsigned int snd_pcm_hw_params_set_channels_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_rate,snd_pcm_hw_params_get_rate@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_rate_min,snd_pcm_hw_params_get_rate_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_rate_max,snd_pcm_hw_params_get_rate_max@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_rate_near,snd_pcm_hw_params_set_rate_near@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_rate_first,snd_pcm_hw_params_set_rate_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_rate_last,snd_pcm_hw_params_set_rate_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_rate, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_rate_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_rate_max, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_rate_near, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_rate_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_rate_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_get_rate(const snd_pcm_hw_params_t *params, int *dir);
db6034
 unsigned int snd_pcm_hw_params_get_rate_min(const snd_pcm_hw_params_t *params, int *dir);
db6034
@@ -80,12 +83,12 @@ unsigned int snd_pcm_hw_params_set_rate_last(snd_pcm_t *pcm, snd_pcm_hw_params_t
db6034
 int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
db6034
 int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_period_time,snd_pcm_hw_params_get_period_time@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_period_time_min,snd_pcm_hw_params_get_period_time_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_period_time_max,snd_pcm_hw_params_get_period_time_max@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_period_time_near,snd_pcm_hw_params_set_period_time_near@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_period_time_first,snd_pcm_hw_params_set_period_time_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_period_time_last,snd_pcm_hw_params_set_period_time_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_period_time, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_period_time_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_period_time_max, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_period_time_near, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_period_time_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_period_time_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, int *dir);
db6034
 unsigned int snd_pcm_hw_params_get_period_time_min(const snd_pcm_hw_params_t *params, int *dir);
db6034
@@ -99,12 +102,12 @@ unsigned int snd_pcm_hw_params_set_period_time_near(snd_pcm_t *pcm, snd_pcm_hw_p
db6034
 unsigned int snd_pcm_hw_params_set_period_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
db6034
 unsigned int snd_pcm_hw_params_set_period_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_period_size,snd_pcm_hw_params_get_period_size@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_period_size_min,snd_pcm_hw_params_get_period_size_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_period_size_max,snd_pcm_hw_params_get_period_size_max@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_period_size_near,snd_pcm_hw_params_set_period_size_near@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_period_size_first,snd_pcm_hw_params_set_period_size_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_period_size_last,snd_pcm_hw_params_set_period_size_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_period_size, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_period_size_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_period_size_max, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_period_size_near, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_period_size_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_period_size_last, "ALSA_0.9");
db6034
 
db6034
 snd_pcm_sframes_t snd_pcm_hw_params_get_period_size(const snd_pcm_hw_params_t *params, int *dir);
db6034
 snd_pcm_uframes_t snd_pcm_hw_params_get_period_size_min(const snd_pcm_hw_params_t *params, int *dir);
db6034
@@ -119,12 +122,12 @@ snd_pcm_uframes_t snd_pcm_hw_params_set_period_size_first(snd_pcm_t *pcm, snd_pc
db6034
 snd_pcm_uframes_t snd_pcm_hw_params_set_period_size_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
db6034
 int snd_pcm_hw_params_set_period_size_integer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_periods,snd_pcm_hw_params_get_periods@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_periods_min,snd_pcm_hw_params_get_periods_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_periods_max,snd_pcm_hw_params_get_periods_max@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_periods_near,snd_pcm_hw_params_set_periods_near@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_periods_first,snd_pcm_hw_params_set_periods_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_periods_last,snd_pcm_hw_params_set_periods_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_periods, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_periods_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_periods_max, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_periods_near, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_periods_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_periods_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_get_periods(const snd_pcm_hw_params_t *params, int *dir);
db6034
 unsigned int snd_pcm_hw_params_get_periods_min(const snd_pcm_hw_params_t *params, int *dir);
db6034
@@ -139,12 +142,12 @@ unsigned int snd_pcm_hw_params_set_periods_first(snd_pcm_t *pcm, snd_pcm_hw_para
db6034
 unsigned int snd_pcm_hw_params_set_periods_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
db6034
 int snd_pcm_hw_params_set_periods_integer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_buffer_time,snd_pcm_hw_params_get_buffer_time@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_buffer_time_min,snd_pcm_hw_params_get_buffer_time_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_buffer_time_max,snd_pcm_hw_params_get_buffer_time_max@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_buffer_time_near,snd_pcm_hw_params_set_buffer_time_near@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_buffer_time_first,snd_pcm_hw_params_set_buffer_time_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_buffer_time_last,snd_pcm_hw_params_set_buffer_time_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_buffer_time, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_buffer_time_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_buffer_time_max, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_buffer_time_near, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_buffer_time_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_buffer_time_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_get_buffer_time(const snd_pcm_hw_params_t *params, int *dir);
db6034
 unsigned int snd_pcm_hw_params_get_buffer_time_min(const snd_pcm_hw_params_t *params, int *dir);
db6034
@@ -158,12 +161,12 @@ unsigned int snd_pcm_hw_params_set_buffer_time_near(snd_pcm_t *pcm, snd_pcm_hw_p
db6034
 unsigned int snd_pcm_hw_params_set_buffer_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
db6034
 unsigned int snd_pcm_hw_params_set_buffer_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_buffer_size,snd_pcm_hw_params_get_buffer_size@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_buffer_size_min,snd_pcm_hw_params_get_buffer_size_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_buffer_size_max,snd_pcm_hw_params_get_buffer_size_max@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_buffer_size_near,snd_pcm_hw_params_set_buffer_size_near@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_buffer_size_first,snd_pcm_hw_params_set_buffer_size_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_buffer_size_last,snd_pcm_hw_params_set_buffer_size_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_buffer_size, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_buffer_size_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_buffer_size_max, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_buffer_size_near, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_buffer_size_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_buffer_size_last, "ALSA_0.9");
db6034
 
db6034
 snd_pcm_sframes_t snd_pcm_hw_params_get_buffer_size(const snd_pcm_hw_params_t *params);
db6034
 snd_pcm_uframes_t snd_pcm_hw_params_get_buffer_size_min(const snd_pcm_hw_params_t *params);
db6034
@@ -177,12 +180,12 @@ snd_pcm_uframes_t snd_pcm_hw_params_set_buffer_size_near(snd_pcm_t *pcm, snd_pcm
db6034
 snd_pcm_uframes_t snd_pcm_hw_params_set_buffer_size_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
db6034
 snd_pcm_uframes_t snd_pcm_hw_params_set_buffer_size_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
db6034
 
db6034
-asm(".symver snd_pcm_hw_params_get_tick_time,snd_pcm_hw_params_get_tick_time@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_tick_time_min,snd_pcm_hw_params_get_tick_time_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_get_tick_time_max,snd_pcm_hw_params_get_tick_time_max@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_tick_time_near,snd_pcm_hw_params_set_tick_time_near@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_tick_time_first,snd_pcm_hw_params_set_tick_time_first@ALSA_0.9");
db6034
-asm(".symver snd_pcm_hw_params_set_tick_time_last,snd_pcm_hw_params_set_tick_time_last@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_tick_time, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_tick_time_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_get_tick_time_max, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_tick_time_near, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_tick_time_first, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_hw_params_set_tick_time_last, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_hw_params_get_tick_time(const snd_pcm_hw_params_t *params, int *dir);
db6034
 unsigned int snd_pcm_hw_params_get_tick_time_min(const snd_pcm_hw_params_t *params, int *dir);
db6034
@@ -201,14 +204,14 @@ unsigned int snd_pcm_hw_params_set_tick_time_last(snd_pcm_t *pcm, snd_pcm_hw_par
db6034
 
db6034
 #ifdef ALSA_PCM_OLD_SW_PARAMS_API
db6034
 
db6034
-asm(".symver snd_pcm_sw_params_get_tstamp_mode,snd_pcm_sw_params_get_tstamp_mode@ALSA_0.9");
db6034
-asm(".symver snd_pcm_sw_params_get_sleep_min,snd_pcm_sw_params_get_sleep_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_sw_params_get_avail_min,snd_pcm_sw_params_get_avail_min@ALSA_0.9");
db6034
-asm(".symver snd_pcm_sw_params_get_xfer_align,snd_pcm_sw_params_get_xfer_align@ALSA_0.9");
db6034
-asm(".symver snd_pcm_sw_params_get_start_threshold,snd_pcm_sw_params_get_start_threshold@ALSA_0.9");
db6034
-asm(".symver snd_pcm_sw_params_get_stop_threshold,snd_pcm_sw_params_get_stop_threshold@ALSA_0.9");
db6034
-asm(".symver snd_pcm_sw_params_get_silence_threshold,snd_pcm_sw_params_get_silence_threshold@ALSA_0.9");
db6034
-asm(".symver snd_pcm_sw_params_get_silence_size,snd_pcm_sw_params_get_silence_size@ALSA_0.9");
db6034
+___symbol_version(snd_pcm_sw_params_get_tstamp_mode, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_sw_params_get_sleep_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_sw_params_get_avail_min, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_sw_params_get_xfer_align, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_sw_params_get_start_threshold, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_sw_params_get_stop_threshold, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_sw_params_get_silence_threshold, "ALSA_0.9");
db6034
+___symbol_version(snd_pcm_sw_params_get_silence_size, "ALSA_0.9");
db6034
 
db6034
 int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_t val);
db6034
 snd_pcm_tstamp_t snd_pcm_sw_params_get_tstamp_mode(const snd_pcm_sw_params_t *params);
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 152983f01b0bc1178ea0d461ebf66e2d2a8e2e02 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 9 Nov 2022 15:04:06 +0100
db6034
Subject: [PATCH 05/20] include: alsa-symbols.h - use newer gcc symver function
db6034
 attribute
db6034
db6034
Use the symver function attribute for newer gccs (version 11+).
db6034
The symver function attribute was introduced probably earlier
db6034
(gcc-10). We can fix that on demand later.
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 include/alsa-symbols.h | 7 +++++++
db6034
 1 file changed, 7 insertions(+)
db6034
db6034
diff --git a/include/alsa-symbols.h b/include/alsa-symbols.h
db6034
index 344f021a..f8c49103 100644
db6034
--- a/include/alsa-symbols.h
db6034
+++ b/include/alsa-symbols.h
db6034
@@ -29,10 +29,17 @@
db6034
 #define INTERNAL_CONCAT2_2(Pre, Post) Pre##Post
db6034
 #define INTERNAL(Name) INTERNAL_CONCAT2_2(__, Name)
db6034
 
db6034
+#if __GNUC__ > 10
db6034
+#define symbol_version(real, name, version) \
db6034
+	extern __typeof (real) real __attribute__((symver (#name "@" #version)))
db6034
+#define default_symbol_version(real, name, version) \
db6034
+	extern __typeof (real) real __attribute__((symver (#name "@@" #version)))
db6034
+#else
db6034
 #define symbol_version(real, name, version) \
db6034
 	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@" #version)
db6034
 #define default_symbol_version(real, name, version) \
db6034
 	__asm__ (".symver " ASM_NAME(#real) "," ASM_NAME(#name) "@@" #version)
db6034
+#endif
db6034
 
db6034
 #ifdef __clang__
db6034
 #define EXPORT_SYMBOL __attribute__((visibility("default")))
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 78b20e3caa7bba930095e05f3f8cbe665204fcfd Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Mon, 14 Nov 2022 12:36:04 +0100
db6034
Subject: [PATCH 06/20] test: latency - use snd_pcm_format_physical_width()
db6034
db6034
We need to allocate frames using the physical size not
db6034
the sample bit size.
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/topology/ctl.c | 7 ++++++-
db6034
 test/latency.c     | 6 +++---
db6034
 2 files changed, 9 insertions(+), 4 deletions(-)
db6034
db6034
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
db6034
index dd05424d..2c500ffc 100644
db6034
--- a/src/topology/ctl.c
db6034
+++ b/src/topology/ctl.c
db6034
@@ -17,9 +17,13 @@
db6034
            Liam Girdwood <liam.r.girdwood@linux.intel.com>
db6034
 */
db6034
 
db6034
+#define ALSA_PCM_OLD_HW_PARAMS_API 1
db6034
+#define ALSA_PCM_OLD_SW_PARAMS_API 1
db6034
+#include "../../include/asoundlib.h"
db6034
 #include "list.h"
db6034
 #include "tplg_local.h"
db6034
 
db6034
+
db6034
 #define ENUM_VAL_SIZE 	(SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
db6034
 
db6034
 struct ctl_access_elem {
db6034
@@ -71,7 +75,8 @@ static int parse_access_values(snd_config_t *cfg,
db6034
 			}
db6034
 		}
db6034
 	}
db6034
-
db6034
+	return snd_pcm_hw_params_get_channels(NULL);
db6034
+	//return snd_pcm_hw_params_get_access(NULL);
db6034
 	return 0;
db6034
 }
db6034
 
db6034
diff --git a/test/latency.c b/test/latency.c
db6034
index 298bab8a..95b3c0ee 100644
db6034
--- a/test/latency.c
db6034
+++ b/test/latency.c
db6034
@@ -354,7 +354,7 @@ long readbuf(snd_pcm_t *handle, char *buf, long len, size_t *frames, size_t *max
db6034
 		}
db6034
 		// printf("read = %li\n", r);
db6034
 	} else {
db6034
-		int frame_bytes = (snd_pcm_format_width(format) / 8) * channels;
db6034
+		int frame_bytes = (snd_pcm_format_physical_width(format) / 8) * channels;
db6034
 		do {
db6034
 			r = snd_pcm_readi(handle, buf, len);
db6034
 			if (r > 0) {
db6034
@@ -374,7 +374,7 @@ long readbuf(snd_pcm_t *handle, char *buf, long len, size_t *frames, size_t *max
db6034
 long writebuf(snd_pcm_t *handle, char *buf, long len, size_t *frames)
db6034
 {
db6034
 	long r;
db6034
-	int frame_bytes = (snd_pcm_format_width(format) / 8) * channels;
db6034
+	int frame_bytes = (snd_pcm_format_physical_width(format) / 8) * channels;
db6034
 
db6034
 	while (len > 0) {
db6034
 		r = snd_pcm_writei(handle, buf, len);
db6034
@@ -579,7 +579,7 @@ int main(int argc, char *argv[])
db6034
 
db6034
 	loop_limit = loop_sec * rate;
db6034
 	latency = latency_min - 4;
db6034
-	buffer = malloc((latency_max * snd_pcm_format_width(format) / 8) * 2);
db6034
+	buffer = malloc((latency_max * snd_pcm_format_physical_width(format) / 8) * 2);
db6034
 
db6034
 	setscheduler();
db6034
 
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 425e4d1fbea4965ea0fb7529b1ee6cbb47eb7227 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Mon, 14 Nov 2022 14:34:46 +0100
db6034
Subject: [PATCH 07/20] pcm: fix the fast_ops pcm argument for fast_ops
db6034
db6034
The fast_ops callback invocation must always pass the fast_op_arg
db6034
as the pcm argument. Plugins expect that.
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/pcm/pcm.c        | 4 ++--
db6034
 src/pcm/pcm_direct.c | 2 +-
db6034
 src/pcm/pcm_hw.c     | 2 +-
db6034
 src/pcm/pcm_multi.c  | 5 +++--
db6034
 4 files changed, 7 insertions(+), 6 deletions(-)
db6034
db6034
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
db6034
index 927aa055..2b966d44 100644
db6034
--- a/src/pcm/pcm.c
db6034
+++ b/src/pcm/pcm.c
db6034
@@ -1705,7 +1705,7 @@ int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
db6034
 	assert(pcm1);
db6034
 	assert(pcm2);
db6034
 	if (pcm1->fast_ops->link)
db6034
-		err = pcm1->fast_ops->link(pcm1, pcm2);
db6034
+		err = pcm1->fast_ops->link(pcm1->fast_op_arg, pcm2);
db6034
 	else
db6034
 		err = -ENOSYS;
db6034
 	return err;
db6034
@@ -1722,7 +1722,7 @@ int snd_pcm_unlink(snd_pcm_t *pcm)
db6034
 
db6034
 	assert(pcm);
db6034
 	if (pcm->fast_ops->unlink)
db6034
-		err = pcm->fast_ops->unlink(pcm);
db6034
+		err = pcm->fast_ops->unlink(pcm->fast_op_arg);
db6034
 	else
db6034
 		err = -ENOSYS;
db6034
 	return err;
db6034
diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
db6034
index 4803b81b..3cc5305f 100644
db6034
--- a/src/pcm/pcm_direct.c
db6034
+++ b/src/pcm/pcm_direct.c
db6034
@@ -688,7 +688,7 @@ int snd_pcm_direct_check_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm)
db6034
 		 * so don't increment but just update to actual counter
db6034
 		 */
db6034
 		direct->recoveries = direct->shmptr->s.recoveries;
db6034
-		pcm->fast_ops->drop(pcm);
db6034
+		pcm->fast_ops->drop(pcm->fast_op_arg);
db6034
 		/* trigger_tstamp update is missing in drop callbacks */
db6034
 		gettimestamp(&direct->trigger_tstamp, pcm->tstamp_type);
db6034
 		/* no timer clear:
db6034
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c
db6034
index 5dfe32ee..0588ce5e 100644
db6034
--- a/src/pcm/pcm_hw.c
db6034
+++ b/src/pcm/pcm_hw.c
db6034
@@ -838,7 +838,7 @@ static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
db6034
 {
db6034
 	if (pcm2->type != SND_PCM_TYPE_HW) {
db6034
 		if (pcm2->fast_ops->link_slaves)
db6034
-			return pcm2->fast_ops->link_slaves(pcm2, pcm1);
db6034
+			return pcm2->fast_ops->link_slaves(pcm2->fast_op_arg, pcm1);
db6034
 		return -ENOSYS;
db6034
 	}
db6034
 	return hw_link(pcm1, pcm2);
db6034
diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c
db6034
index bec6d06f..3e7ce82c 100644
db6034
--- a/src/pcm/pcm_multi.c
db6034
+++ b/src/pcm/pcm_multi.c
db6034
@@ -759,8 +759,9 @@ static int snd_pcm_multi_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
db6034
 static int snd_pcm_multi_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
db6034
 {
db6034
 	snd_pcm_multi_t *multi = pcm1->private_data;
db6034
-	if (multi->slaves[0].pcm->fast_ops->link)
db6034
-		return multi->slaves[0].pcm->fast_ops->link(multi->slaves[0].pcm, pcm2);
db6034
+	snd_pcm_t *main_pcm = multi->slaves[0].pcm;
db6034
+	if (main_pcm->fast_ops->link)
db6034
+		return main_pcm->fast_ops->link(main_pcm->fast_op_arg, pcm2);
db6034
 	return -ENOSYS;
db6034
 }
db6034
 
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 3e4aeba25bf4a4808183c4b64270f7321b436c13 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Mon, 14 Nov 2022 20:42:10 +0100
db6034
Subject: [PATCH 08/20] test: latency - add more realtime tests
db6034
db6034
Add '-x' and '-X' tests and '-U' - I/O update mode based
db6034
on the system timing.
db6034
db6034
It may be required to check the position updates for the specific hardware.
db6034
Print the real time / stream time differences.
db6034
db6034
Also include code to make valgrind happy (including the wrong memory
db6034
llocation for the stream buffer).
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 test/latency.c | 163 +++++++++++++++++++++++++++++++++++++++++++++----
db6034
 1 file changed, 151 insertions(+), 12 deletions(-)
db6034
db6034
diff --git a/test/latency.c b/test/latency.c
db6034
index 95b3c0ee..91bef1a1 100644
db6034
--- a/test/latency.c
db6034
+++ b/test/latency.c
db6034
@@ -33,10 +33,13 @@
db6034
 #include <sched.h>
db6034
 #include <errno.h>
db6034
 #include <getopt.h>
db6034
+#include <time.h>
db6034
 #include "../include/asoundlib.h"
db6034
 #include <sys/time.h>
db6034
 #include <math.h>
db6034
 
db6034
+typedef struct timespec timestamp_t;
db6034
+
db6034
 char *pdevice = "hw:0,0";
db6034
 char *cdevice = "hw:0,0";
db6034
 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
db6034
@@ -50,10 +53,40 @@ int loop_sec = 30;		/* seconds */
db6034
 int block = 0;			/* block mode */
db6034
 int use_poll = 0;
db6034
 int resample = 1;
db6034
+int sys_latency = 0;		/* data I/O: use system timings instead driver wakeups */
db6034
+int pos_dump = 0;		/* dump positions */
db6034
+int realtime_check = 0;
db6034
 unsigned long loop_limit;
db6034
+snd_pcm_uframes_t playback_buffer_size;
db6034
 
db6034
 snd_output_t *output = NULL;
db6034
 
db6034
+static inline long long frames_to_micro(size_t frames)
db6034
+{
db6034
+	return (long long)((frames * 1000000LL) + (rate / 2)) / rate;
db6034
+}
db6034
+
db6034
+void timestamp_now(timestamp_t *tstamp)
db6034
+{
db6034
+	if (clock_gettime(CLOCK_MONOTONIC_RAW, tstamp))
db6034
+		printf("clock_gettime() failed\n");
db6034
+}
db6034
+
db6034
+long long timestamp_diff_micro(timestamp_t *tstamp)
db6034
+{
db6034
+	timestamp_t now, diff;
db6034
+	timestamp_now(&now;;
db6034
+	if (tstamp->tv_nsec > now.tv_nsec) {
db6034
+		diff.tv_sec = now.tv_sec - tstamp->tv_sec - 1;
db6034
+		diff.tv_nsec = (now.tv_nsec + 1000000000L) - tstamp->tv_nsec;
db6034
+	} else {
db6034
+		diff.tv_sec = now.tv_sec - tstamp->tv_sec;
db6034
+		diff.tv_nsec = now.tv_nsec - tstamp->tv_nsec;
db6034
+	}
db6034
+	/* microseconds */
db6034
+	return (diff.tv_sec * 1000000) + ((diff.tv_nsec + 500L) / 1000L);
db6034
+}
db6034
+
db6034
 int setparams_stream(snd_pcm_t *handle,
db6034
 		     snd_pcm_hw_params_t *params,
db6034
 		     const char *id)
db6034
@@ -96,6 +129,14 @@ int setparams_stream(snd_pcm_t *handle,
db6034
 		printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
db6034
 		return -EINVAL;
db6034
 	}
db6034
+	/* we do not want driver wakeups */
db6034
+	if (sys_latency > 0 && snd_pcm_hw_params_can_disable_period_wakeup(params)) {
db6034
+		err = snd_pcm_hw_params_set_period_wakeup(handle, params, 0);
db6034
+		if (err < 0) {
db6034
+			printf("Cannot disable period wakeups for %s\n", id);
db6034
+			return err;
db6034
+		}
db6034
+	}
db6034
 	return 0;
db6034
 }
db6034
 
db6034
@@ -227,6 +268,7 @@ int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, int *bufsize)
db6034
 		goto __again;
db6034
 
db6034
 	snd_pcm_hw_params_get_buffer_size(p_params, &p_size);
db6034
+	playback_buffer_size = p_size;
db6034
 	if (p_psize * 2 < p_size) {
db6034
                 snd_pcm_hw_params_get_periods_min(p_params, &val, NULL);
db6034
                 if (val > 2) {
db6034
@@ -390,7 +432,7 @@ long writebuf(snd_pcm_t *handle, char *buf, long len, size_t *frames)
db6034
 	}
db6034
 	return 0;
db6034
 }
db6034
-			
db6034
+
db6034
 #define FILTERSWEEP_LFO_CENTER 2000.
db6034
 #define FILTERSWEEP_LFO_DEPTH 1800.
db6034
 #define FILTERSWEEP_LFO_FREQ 0.2
db6034
@@ -434,6 +476,19 @@ void applyeffect(char* buffer,int r)
db6034
 	}
db6034
 }
db6034
 
db6034
+static ssize_t get_avail(snd_pcm_t *pcm)
db6034
+{
db6034
+	ssize_t avail;
db6034
+
db6034
+	while (1) {
db6034
+		avail = snd_pcm_avail(pcm);
db6034
+		if (avail == -EAGAIN)
db6034
+			continue;
db6034
+		break;
db6034
+	}
db6034
+	return avail;
db6034
+}
db6034
+
db6034
 void help(void)
db6034
 {
db6034
 	int k;
db6034
@@ -444,6 +499,7 @@ void help(void)
db6034
 "-C,--cdevice   capture device\n"
db6034
 "-m,--min       minimum latency in frames\n"
db6034
 "-M,--max       maximum latency in frames\n"
db6034
+"-U,--updates   I/O updates in milliseconds (0 = off)\n"
db6034
 "-F,--frames    frames to transfer\n"
db6034
 "-f,--format    sample format\n"
db6034
 "-c,--channels  channels\n"
db6034
@@ -454,6 +510,8 @@ void help(void)
db6034
 "-b,--block     block mode\n"
db6034
 "-p,--poll      use poll (wait for event - reduces CPU usage)\n"
db6034
 "-e,--effect    apply an effect (bandpass filter sweep)\n"
db6034
+"-x,--posdump   dump buffer positions\n"
db6034
+"-X,--realtime  do a realtime check (buffering)\n"
db6034
 );
db6034
         printf("Recognized sample formats are:");
db6034
         for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
db6034
@@ -480,6 +538,7 @@ int main(int argc, char *argv[])
db6034
 		{"cdevice", 1, NULL, 'C'},
db6034
 		{"min", 1, NULL, 'm'},
db6034
 		{"max", 1, NULL, 'M'},
db6034
+		{"updates", 1, NULL, 'U'},
db6034
 		{"frames", 1, NULL, 'F'},
db6034
 		{"format", 1, NULL, 'f'},
db6034
 		{"channels", 1, NULL, 'c'},
db6034
@@ -490,20 +549,23 @@ int main(int argc, char *argv[])
db6034
 		{"block", 0, NULL, 'b'},
db6034
 		{"poll", 0, NULL, 'p'},
db6034
 		{"effect", 0, NULL, 'e'},
db6034
+		{"posdump", 0, NULL, 'x'},
db6034
+		{"realtime", 0, NULL, 'X'},
db6034
 		{NULL, 0, NULL, 0},
db6034
 	};
db6034
 	snd_pcm_t *phandle, *chandle;
db6034
 	char *buffer;
db6034
 	int err, latency, morehelp;
db6034
-	int ok;
db6034
+	int ok, first_avail;
db6034
 	snd_timestamp_t p_tstamp, c_tstamp;
db6034
-	ssize_t r;
db6034
+	ssize_t r, cap_avail, cap_avail_max, pbk_fill, pbk_fill_min;
db6034
 	size_t frames_in, frames_out, in_max;
db6034
+	timestamp_t tstamp_start;
db6034
 	int effect = 0;
db6034
 	morehelp = 0;
db6034
 	while (1) {
db6034
 		int c;
db6034
-		if ((c = getopt_long(argc, argv, "hP:C:m:M:F:f:c:r:B:E:s:bpen", long_option, NULL)) < 0)
db6034
+		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:bpenxX", long_option, NULL)) < 0)
db6034
 			break;
db6034
 		switch (c) {
db6034
 		case 'h':
db6034
@@ -525,6 +587,10 @@ int main(int argc, char *argv[])
db6034
 			err = atoi(optarg) / 2;
db6034
 			latency_max = latency_min > err ? latency_min : err;
db6034
 			break;
db6034
+		case 'U':
db6034
+			err = atoi(optarg);
db6034
+			sys_latency = err <= 0 ? 0 : err;
db6034
+			break;
db6034
 		case 'f':
db6034
 			format = snd_pcm_format_value(optarg);
db6034
 			if (format == SND_PCM_FORMAT_UNKNOWN) {
db6034
@@ -564,6 +630,12 @@ int main(int argc, char *argv[])
db6034
 		case 'n':
db6034
 			resample = 0;
db6034
 			break;
db6034
+		case 'x':
db6034
+			pos_dump = 1;
db6034
+			break;
db6034
+		case 'X':
db6034
+			realtime_check = 1;
db6034
+			break;
db6034
 		}
db6034
 	}
db6034
 
db6034
@@ -579,15 +651,27 @@ int main(int argc, char *argv[])
db6034
 
db6034
 	loop_limit = loop_sec * rate;
db6034
 	latency = latency_min - 4;
db6034
-	buffer = malloc((latency_max * snd_pcm_format_physical_width(format) / 8) * 2);
db6034
+	buffer = malloc((latency_max * 2 * snd_pcm_format_physical_width(format) / 8) * channels);
db6034
+
db6034
+	/* I/O updates based on a system timer */
db6034
+	if (sys_latency > 0) {
db6034
+		block = 0;
db6034
+		use_poll = 0;
db6034
+	}
db6034
 
db6034
 	setscheduler();
db6034
 
db6034
 	printf("Playback device is %s\n", pdevice);
db6034
 	printf("Capture device is %s\n", cdevice);
db6034
-	printf("Parameters are %iHz, %s, %i channels, %s mode\n", rate, snd_pcm_format_name(format), channels, block ? "blocking" : "non-blocking");
db6034
-	printf("Poll mode: %s\n", use_poll ? "yes" : "no");
db6034
-	printf("Loop limit is %lu frames, minimum latency = %i, maximum latency = %i\n", loop_limit, latency_min * 2, latency_max * 2);
db6034
+	printf("Parameters are %iHz, %s, %i channels, %s mode, use poll %s\n",
db6034
+			rate, snd_pcm_format_name(format),
db6034
+			channels, block ? "blocking" : "non-blocking",
db6034
+			use_poll ? "yes" : "no");
db6034
+	printf("Loop limit is %lu frames, minimum latency = %i, maximum latency = %i",
db6034
+			loop_limit, latency_min * 2, latency_max * 2);
db6034
+	if (sys_latency > 0)
db6034
+		printf(", I/O updates %ims", sys_latency);
db6034
+	printf("\n");
db6034
 
db6034
 	if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, block ? 0 : SND_PCM_NONBLOCK)) < 0) {
db6034
 		printf("Playback open error: %s\n", snd_strerror(err));
db6034
@@ -613,6 +697,9 @@ int main(int argc, char *argv[])
db6034
 		y[1] = (float*) malloc(channels*sizeof(float));		
db6034
 		y[2] = (float*) malloc(channels*sizeof(float));		
db6034
 	}
db6034
+
db6034
+	cap_avail_max = 0;
db6034
+	pbk_fill_min = latency * 2;
db6034
 			  
db6034
 	while (1) {
db6034
 		frames_in = frames_out = 0;
db6034
@@ -623,7 +710,7 @@ int main(int argc, char *argv[])
db6034
 			printf("Streams link error: %s\n", snd_strerror(err));
db6034
 			exit(0);
db6034
 		}
db6034
-		if (snd_pcm_format_set_silence(format, buffer, latency*channels) < 0) {
db6034
+		if (snd_pcm_format_set_silence(format, buffer, latency * channels) < 0) {
db6034
 			fprintf(stderr, "silence error\n");
db6034
 			break;
db6034
 		}
db6034
@@ -640,6 +727,8 @@ int main(int argc, char *argv[])
db6034
 			printf("Go error: %s\n", snd_strerror(err));
db6034
 			exit(0);
db6034
 		}
db6034
+		if (realtime_check)
db6034
+			timestamp_now(&tstamp_start);
db6034
 		gettimestamp(phandle, &p_tstamp);
db6034
 		gettimestamp(chandle, &c_tstamp);
db6034
 #if 0
db6034
@@ -651,16 +740,54 @@ int main(int argc, char *argv[])
db6034
 
db6034
 		ok = 1;
db6034
 		in_max = 0;
db6034
+		first_avail = 1;
db6034
 		while (ok && frames_in < loop_limit) {
db6034
-			if (use_poll) {
db6034
+			cap_avail = latency;
db6034
+			if (sys_latency > 0) {
db6034
+				poll(NULL, 0, sys_latency);
db6034
+				cap_avail = get_avail(chandle);
db6034
+				if (cap_avail < 0) {
db6034
+					printf("Avail failed: %s\n", snd_strerror(cap_avail));
db6034
+					ok = 0;
db6034
+					break;
db6034
+				}
db6034
+				if (first_avail && realtime_check) {
db6034
+					long long diff = timestamp_diff_micro(&tstamp_start);
db6034
+					long long pos = frames_to_micro(cap_avail);
db6034
+					printf("POS FIRST CHECK: c=%zd (rt=%lldus)\n", cap_avail, pos - diff);
db6034
+					first_avail = 0;
db6034
+				}
db6034
+			} else if (use_poll) {
db6034
 				/* use poll to wait for next event */
db6034
 				snd_pcm_wait(chandle, 1000);
db6034
 			}
db6034
-			if ((r = readbuf(chandle, buffer, latency, &frames_in, &in_max)) < 0)
db6034
+			if (pos_dump || realtime_check) {
db6034
+				if (sys_latency <= 0)
db6034
+					cap_avail = get_avail(chandle);
db6034
+				pbk_fill = get_avail(phandle);
db6034
+				if (pbk_fill >= 0)
db6034
+					pbk_fill = playback_buffer_size - pbk_fill;
db6034
+				if (cap_avail > cap_avail_max)
db6034
+					cap_avail_max = cap_avail;
db6034
+				if (pbk_fill >= 0 && pbk_fill < pbk_fill_min)
db6034
+					pbk_fill_min = pbk_fill;
db6034
+				if (realtime_check) {
db6034
+					long long diff = timestamp_diff_micro(&tstamp_start);
db6034
+					long long cap_pos = frames_to_micro(frames_in + cap_avail);
db6034
+					long long pbk_pos = frames_to_micro(frames_out - pbk_fill);
db6034
+					printf("POS: p=%zd (min=%zd, rt=%lldus) c=%zd (max=%zd, rt=%lldus)\n",
db6034
+							pbk_fill, pbk_fill_min, pbk_pos - diff,
db6034
+							cap_avail, cap_avail_max, cap_pos - diff);
db6034
+				} else if (pos_dump) {
db6034
+					printf("POS: p=%zd (min=%zd), c=%zd (max=%zd)\n",
db6034
+							pbk_fill, pbk_fill_min, cap_avail, cap_avail_max);
db6034
+				}
db6034
+			}
db6034
+			if ((r = readbuf(chandle, buffer, cap_avail, &frames_in, &in_max)) < 0)
db6034
 				ok = 0;
db6034
 			else {
db6034
 				if (effect)
db6034
-					applyeffect(buffer,r);
db6034
+					applyeffect(buffer, r);
db6034
 			 	if (writebuf(phandle, buffer, r, &frames_out) < 0)
db6034
 					ok = 0;
db6034
 			}
db6034
@@ -677,6 +804,13 @@ int main(int argc, char *argv[])
db6034
 		if (p_tstamp.tv_sec == c_tstamp.tv_sec &&
db6034
 		    p_tstamp.tv_usec == c_tstamp.tv_usec)
db6034
 			printf("Hardware sync\n");
db6034
+		if (realtime_check) {
db6034
+			long long diff = timestamp_diff_micro(&tstamp_start);
db6034
+			long long mtime = frames_to_micro(frames_in);
db6034
+			printf("Elapsed real time: %lldus\n", diff);
db6034
+			printf("Elapsed device time: %lldus\n", mtime);
db6034
+			printf("Test time diff (device - real): %lldus\n", mtime - diff);
db6034
+		}
db6034
 		snd_pcm_drop(chandle);
db6034
 		snd_pcm_nonblock(phandle, 0);
db6034
 		snd_pcm_drain(phandle);
db6034
@@ -698,5 +832,10 @@ int main(int argc, char *argv[])
db6034
 	}
db6034
 	snd_pcm_close(phandle);
db6034
 	snd_pcm_close(chandle);
db6034
+	snd_output_close(output);
db6034
+	snd_config_update_free_global();
db6034
+	free(buffer);
db6034
+	free(pdevice);
db6034
+	free(cdevice);
db6034
 	return 0;
db6034
 }
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From a0836e2af1f2c37b66e723d8caf399e80b76825b Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Mon, 14 Nov 2022 21:26:39 +0100
db6034
Subject: [PATCH 09/20] latency: add timestamps to the POS lines
db6034
db6034
- remove first capture pos line
db6034
- measure the snd_pcm_start() call, too
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 test/latency.c | 17 ++++++-----------
db6034
 1 file changed, 6 insertions(+), 11 deletions(-)
db6034
db6034
diff --git a/test/latency.c b/test/latency.c
db6034
index 91bef1a1..3aff37c1 100644
db6034
--- a/test/latency.c
db6034
+++ b/test/latency.c
db6034
@@ -556,7 +556,7 @@ int main(int argc, char *argv[])
db6034
 	snd_pcm_t *phandle, *chandle;
db6034
 	char *buffer;
db6034
 	int err, latency, morehelp;
db6034
-	int ok, first_avail;
db6034
+	int ok;
db6034
 	snd_timestamp_t p_tstamp, c_tstamp;
db6034
 	ssize_t r, cap_avail, cap_avail_max, pbk_fill, pbk_fill_min;
db6034
 	size_t frames_in, frames_out, in_max;
db6034
@@ -723,12 +723,14 @@ int main(int argc, char *argv[])
db6034
 			break;
db6034
 		}
db6034
 
db6034
+		if (realtime_check)
db6034
+			timestamp_now(&tstamp_start);
db6034
 		if ((err = snd_pcm_start(chandle)) < 0) {
db6034
 			printf("Go error: %s\n", snd_strerror(err));
db6034
 			exit(0);
db6034
 		}
db6034
 		if (realtime_check)
db6034
-			timestamp_now(&tstamp_start);
db6034
+			printf("[%lldus] Stream start\n", timestamp_diff_micro(&tstamp_start));
db6034
 		gettimestamp(phandle, &p_tstamp);
db6034
 		gettimestamp(chandle, &c_tstamp);
db6034
 #if 0
db6034
@@ -740,7 +742,6 @@ int main(int argc, char *argv[])
db6034
 
db6034
 		ok = 1;
db6034
 		in_max = 0;
db6034
-		first_avail = 1;
db6034
 		while (ok && frames_in < loop_limit) {
db6034
 			cap_avail = latency;
db6034
 			if (sys_latency > 0) {
db6034
@@ -751,12 +752,6 @@ int main(int argc, char *argv[])
db6034
 					ok = 0;
db6034
 					break;
db6034
 				}
db6034
-				if (first_avail && realtime_check) {
db6034
-					long long diff = timestamp_diff_micro(&tstamp_start);
db6034
-					long long pos = frames_to_micro(cap_avail);
db6034
-					printf("POS FIRST CHECK: c=%zd (rt=%lldus)\n", cap_avail, pos - diff);
db6034
-					first_avail = 0;
db6034
-				}
db6034
 			} else if (use_poll) {
db6034
 				/* use poll to wait for next event */
db6034
 				snd_pcm_wait(chandle, 1000);
db6034
@@ -775,8 +770,8 @@ int main(int argc, char *argv[])
db6034
 					long long diff = timestamp_diff_micro(&tstamp_start);
db6034
 					long long cap_pos = frames_to_micro(frames_in + cap_avail);
db6034
 					long long pbk_pos = frames_to_micro(frames_out - pbk_fill);
db6034
-					printf("POS: p=%zd (min=%zd, rt=%lldus) c=%zd (max=%zd, rt=%lldus)\n",
db6034
-							pbk_fill, pbk_fill_min, pbk_pos - diff,
db6034
+					printf("[%lldus] POS: p=%zd (min=%zd, rt=%lldus) c=%zd (max=%zd, rt=%lldus)\n",
db6034
+							diff, pbk_fill, pbk_fill_min, pbk_pos - diff,
db6034
 							cap_avail, cap_avail_max, cap_pos - diff);
db6034
 				} else if (pos_dump) {
db6034
 					printf("POS: p=%zd (min=%zd), c=%zd (max=%zd)\n",
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 8b64f22459b6c55ec54f985f35ff701e18800616 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Tue, 15 Nov 2022 17:25:59 +0100
db6034
Subject: [PATCH 10/20] ucm: clarify set_defaults calls
db6034
db6034
- do full reset in snd_use_case_mgr_reload
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/ucm/main.c | 36 +++++++++++++++++++++++++-----------
db6034
 1 file changed, 25 insertions(+), 11 deletions(-)
db6034
db6034
diff --git a/src/ucm/main.c b/src/ucm/main.c
db6034
index 28c60565..4f36648c 100644
db6034
--- a/src/ucm/main.c
db6034
+++ b/src/ucm/main.c
db6034
@@ -998,13 +998,14 @@ static int add_auto_values(snd_use_case_mgr_t *uc_mgr)
db6034
 /**
db6034
  * \brief execute default commands
db6034
  * \param uc_mgr Use case manager
db6034
+ * \param force Force run
db6034
  * \return zero on success, otherwise a negative error code
db6034
  */
db6034
-static int set_defaults(snd_use_case_mgr_t *uc_mgr)
db6034
+static int set_defaults(snd_use_case_mgr_t *uc_mgr, bool force)
db6034
 {
db6034
 	int err;
db6034
 
db6034
-	if (uc_mgr->default_list_executed)
db6034
+	if (!force && uc_mgr->default_list_executed)
db6034
 		return 0;
db6034
 	err = execute_sequence(uc_mgr, NULL, &uc_mgr->default_list,
db6034
 			       &uc_mgr->value_list, NULL, NULL);
db6034
@@ -1351,7 +1352,7 @@ static int set_verb(snd_use_case_mgr_t *uc_mgr,
db6034
 	int err;
db6034
 
db6034
 	if (enable) {
db6034
-		err = set_defaults(uc_mgr);
db6034
+		err = set_defaults(uc_mgr, false);
db6034
 		if (err < 0)
db6034
 			return err;
db6034
 		seq = &verb->enable_list;
db6034
@@ -1435,6 +1436,22 @@ static int set_device(snd_use_case_mgr_t *uc_mgr,
db6034
 	return err;
db6034
 }
db6034
 
db6034
+/**
db6034
+ * \brief Do the full reset
db6034
+ * \param uc_mgr Use case manager
db6034
+ * \return zero on success, otherwise a negative error code
db6034
+ */
db6034
+static int do_reset(snd_use_case_mgr_t *uc_mgr)
db6034
+{
db6034
+	int err;
db6034
+
db6034
+	err = set_defaults(uc_mgr, true);
db6034
+	INIT_LIST_HEAD(&uc_mgr->active_modifiers);
db6034
+	INIT_LIST_HEAD(&uc_mgr->active_devices);
db6034
+	uc_mgr->active_verb = NULL;
db6034
+	return err;
db6034
+}
db6034
+
db6034
 /**
db6034
  * \brief Parse open arguments
db6034
  * \param uc_mgr Use case manager
db6034
@@ -1569,6 +1586,8 @@ int snd_use_case_mgr_reload(snd_use_case_mgr_t *uc_mgr)
db6034
 
db6034
 	pthread_mutex_lock(&uc_mgr->mutex);
db6034
 
db6034
+	do_reset(uc_mgr);
db6034
+
db6034
 	uc_mgr_free_verb(uc_mgr);
db6034
 
db6034
 	uc_mgr->default_list_executed = 0;
db6034
@@ -1633,8 +1652,7 @@ static int dismantle_use_case(snd_use_case_mgr_t *uc_mgr)
db6034
 	}
db6034
 	uc_mgr->active_verb = NULL;
db6034
 
db6034
-	err = execute_sequence(uc_mgr, NULL, &uc_mgr->default_list,
db6034
-			       &uc_mgr->value_list, NULL, NULL);
db6034
+	err = set_defaults(uc_mgr, true);
db6034
 	
db6034
 	return err;
db6034
 }
db6034
@@ -1649,11 +1667,7 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
db6034
 	int err;
db6034
 
db6034
 	pthread_mutex_lock(&uc_mgr->mutex);
db6034
-	err = execute_sequence(uc_mgr, NULL, &uc_mgr->default_list,
db6034
-			       &uc_mgr->value_list, NULL, NULL);
db6034
-	INIT_LIST_HEAD(&uc_mgr->active_modifiers);
db6034
-	INIT_LIST_HEAD(&uc_mgr->active_devices);
db6034
-	uc_mgr->active_verb = NULL;
db6034
+	err = do_reset(uc_mgr);
db6034
 	pthread_mutex_unlock(&uc_mgr->mutex);
db6034
 	return err;
db6034
 }
db6034
@@ -2512,7 +2526,7 @@ static int set_defaults_user(snd_use_case_mgr_t *uc_mgr,
db6034
 		uc_error("error: wrong value for _defaults (%s)", value);
db6034
 		return -EINVAL;
db6034
 	}
db6034
-	return set_defaults(uc_mgr);
db6034
+	return set_defaults(uc_mgr, false);
db6034
 }
db6034
 
db6034
 static int handle_transition_verb(snd_use_case_mgr_t *uc_mgr,
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 9649b64c6f72984c53f469dad8dd4221d307e06d Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Tue, 22 Nov 2022 09:59:04 +0100
db6034
Subject: [PATCH 11/20] ucm: handle empty string also for ${env:} substitution
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/ucm/ucm_subs.c | 8 +++++++-
db6034
 1 file changed, 7 insertions(+), 1 deletion(-)
db6034
db6034
diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c
db6034
index 2261bdc2..e62290ea 100644
db6034
--- a/src/ucm/ucm_subs.c
db6034
+++ b/src/ucm/ucm_subs.c
db6034
@@ -490,7 +490,13 @@ static char *rval_env(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *i
db6034
 {
db6034
 	char *e;
db6034
 
db6034
-	e = getenv(id);
db6034
+	if (*id == '-') {
db6034
+		e = getenv(id + 1);
db6034
+		if (e == NULL)
db6034
+			e = "";
db6034
+	} else {
db6034
+		e = getenv(id);
db6034
+	}
db6034
 	if (e)
db6034
 		return strdup(e);
db6034
 	return NULL;
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From f0f054517c05ff4ef7a1615851a686a3a202b9ff Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 23 Nov 2022 17:56:20 +0100
db6034
Subject: [PATCH 12/20] test: latency - add -y option (I/O usleep)
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 test/latency.c | 13 ++++++++++++-
db6034
 1 file changed, 12 insertions(+), 1 deletion(-)
db6034
db6034
diff --git a/test/latency.c b/test/latency.c
db6034
index 3aff37c1..161d1f68 100644
db6034
--- a/test/latency.c
db6034
+++ b/test/latency.c
db6034
@@ -52,6 +52,7 @@ int latency_max = 2048;		/* in frames / 2 */
db6034
 int loop_sec = 30;		/* seconds */
db6034
 int block = 0;			/* block mode */
db6034
 int use_poll = 0;
db6034
+int usleep_val = 0;
db6034
 int resample = 1;
db6034
 int sys_latency = 0;		/* data I/O: use system timings instead driver wakeups */
db6034
 int pos_dump = 0;		/* dump positions */
db6034
@@ -509,6 +510,8 @@ void help(void)
db6034
 "-s,--seconds   duration of test in seconds\n"
db6034
 "-b,--block     block mode\n"
db6034
 "-p,--poll      use poll (wait for event - reduces CPU usage)\n"
db6034
+"-y,--usleep    sleep for the specified amount of microseconds between\n"
db6034
+"               stream updates (default 0 - off)\n"
db6034
 "-e,--effect    apply an effect (bandpass filter sweep)\n"
db6034
 "-x,--posdump   dump buffer positions\n"
db6034
 "-X,--realtime  do a realtime check (buffering)\n"
db6034
@@ -548,6 +551,7 @@ int main(int argc, char *argv[])
db6034
 		{"seconds", 1, NULL, 's'},
db6034
 		{"block", 0, NULL, 'b'},
db6034
 		{"poll", 0, NULL, 'p'},
db6034
+		{"usleep", 1, NULL, 'y'},
db6034
 		{"effect", 0, NULL, 'e'},
db6034
 		{"posdump", 0, NULL, 'x'},
db6034
 		{"realtime", 0, NULL, 'X'},
db6034
@@ -565,7 +569,7 @@ int main(int argc, char *argv[])
db6034
 	morehelp = 0;
db6034
 	while (1) {
db6034
 		int c;
db6034
-		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:bpenxX", long_option, NULL)) < 0)
db6034
+		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:y:bpenxX", long_option, NULL)) < 0)
db6034
 			break;
db6034
 		switch (c) {
db6034
 		case 'h':
db6034
@@ -624,6 +628,9 @@ int main(int argc, char *argv[])
db6034
 		case 'p':
db6034
 			use_poll = 1;
db6034
 			break;
db6034
+		case 'y':
db6034
+			usleep_val = atoi(optarg);
db6034
+			break;
db6034
 		case 'e':
db6034
 			effect = 1;
db6034
 			break;
db6034
@@ -671,6 +678,8 @@ int main(int argc, char *argv[])
db6034
 			loop_limit, latency_min * 2, latency_max * 2);
db6034
 	if (sys_latency > 0)
db6034
 		printf(", I/O updates %ims", sys_latency);
db6034
+	else if (!block)
db6034
+		printf(", I/O usleep %ius", usleep_val);
db6034
 	printf("\n");
db6034
 
db6034
 	if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, block ? 0 : SND_PCM_NONBLOCK)) < 0) {
db6034
@@ -755,6 +764,8 @@ int main(int argc, char *argv[])
db6034
 			} else if (use_poll) {
db6034
 				/* use poll to wait for next event */
db6034
 				snd_pcm_wait(chandle, 1000);
db6034
+			} else if (usleep_val > 0) {
db6034
+				usleep(usleep_val);
db6034
 			}
db6034
 			if (pos_dump || realtime_check) {
db6034
 				if (sys_latency <= 0)
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 536c93928bc57d941a7cd146dbcbd62df0be2d83 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 23 Nov 2022 19:45:15 +0100
db6034
Subject: [PATCH 13/20] test: latency - usleep should not be used in the block
db6034
 mode
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 test/latency.c | 4 ++--
db6034
 1 file changed, 2 insertions(+), 2 deletions(-)
db6034
db6034
diff --git a/test/latency.c b/test/latency.c
db6034
index 161d1f68..1b4848d6 100644
db6034
--- a/test/latency.c
db6034
+++ b/test/latency.c
db6034
@@ -678,7 +678,7 @@ int main(int argc, char *argv[])
db6034
 			loop_limit, latency_min * 2, latency_max * 2);
db6034
 	if (sys_latency > 0)
db6034
 		printf(", I/O updates %ims", sys_latency);
db6034
-	else if (!block)
db6034
+	else if (!block && !use_poll)
db6034
 		printf(", I/O usleep %ius", usleep_val);
db6034
 	printf("\n");
db6034
 
db6034
@@ -764,7 +764,7 @@ int main(int argc, char *argv[])
db6034
 			} else if (use_poll) {
db6034
 				/* use poll to wait for next event */
db6034
 				snd_pcm_wait(chandle, 1000);
db6034
-			} else if (usleep_val > 0) {
db6034
+			} else if (!block && usleep_val > 0) {
db6034
 				usleep(usleep_val);
db6034
 			}
db6034
 			if (pos_dump || realtime_check) {
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From ea0850f3f3780652869c2b4550576894bc21684f Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Thu, 24 Nov 2022 08:33:47 +0100
db6034
Subject: [PATCH 14/20] test: latency - add --policy option to allow using
db6034
 SCHED_FIFO
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 test/latency.c | 22 +++++++++++++++++-----
db6034
 1 file changed, 17 insertions(+), 5 deletions(-)
db6034
db6034
diff --git a/test/latency.c b/test/latency.c
db6034
index 1b4848d6..3b20e1c1 100644
db6034
--- a/test/latency.c
db6034
+++ b/test/latency.c
db6034
@@ -40,6 +40,7 @@
db6034
 
db6034
 typedef struct timespec timestamp_t;
db6034
 
db6034
+char *sched_policy = "rr";
db6034
 char *pdevice = "hw:0,0";
db6034
 char *cdevice = "hw:0,0";
db6034
 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
db6034
@@ -354,18 +355,24 @@ void gettimestamp(snd_pcm_t *handle, snd_timestamp_t *timestamp)
db6034
 void setscheduler(void)
db6034
 {
db6034
 	struct sched_param sched_param;
db6034
+	int policy = SCHED_RR;
db6034
+	const char *spolicy = "Round Robin";
db6034
 
db6034
+	if (strcasecmp(sched_policy, "fifo") == 0) {
db6034
+		policy = SCHED_FIFO;
db6034
+		spolicy = "FIFO";
db6034
+	}
db6034
 	if (sched_getparam(0, &sched_param) < 0) {
db6034
 		printf("Scheduler getparam failed...\n");
db6034
 		return;
db6034
 	}
db6034
-	sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
db6034
-	if (!sched_setscheduler(0, SCHED_RR, &sched_param)) {
db6034
-		printf("Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority);
db6034
+	sched_param.sched_priority = sched_get_priority_max(policy);
db6034
+	if (!sched_setscheduler(0, policy, &sched_param)) {
db6034
+		printf("Scheduler set to %s with priority %i...\n", spolicy, sched_param.sched_priority);
db6034
 		fflush(stdout);
db6034
 		return;
db6034
 	}
db6034
-	printf("!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority);
db6034
+	printf("!!!Scheduler set to %s with priority %i FAILED!!!\n", spolicy, sched_param.sched_priority);
db6034
 }
db6034
 
db6034
 long timediff(snd_timestamp_t t1, snd_timestamp_t t2)
db6034
@@ -515,6 +522,7 @@ void help(void)
db6034
 "-e,--effect    apply an effect (bandpass filter sweep)\n"
db6034
 "-x,--posdump   dump buffer positions\n"
db6034
 "-X,--realtime  do a realtime check (buffering)\n"
db6034
+"-O,--policy    set scheduler policy (RR or FIFO)\n"
db6034
 );
db6034
         printf("Recognized sample formats are:");
db6034
         for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
db6034
@@ -555,6 +563,7 @@ int main(int argc, char *argv[])
db6034
 		{"effect", 0, NULL, 'e'},
db6034
 		{"posdump", 0, NULL, 'x'},
db6034
 		{"realtime", 0, NULL, 'X'},
db6034
+		{"policy", 1, NULL, 'O'},
db6034
 		{NULL, 0, NULL, 0},
db6034
 	};
db6034
 	snd_pcm_t *phandle, *chandle;
db6034
@@ -569,7 +578,7 @@ int main(int argc, char *argv[])
db6034
 	morehelp = 0;
db6034
 	while (1) {
db6034
 		int c;
db6034
-		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:y:bpenxX", long_option, NULL)) < 0)
db6034
+		if ((c = getopt_long(argc, argv, "hP:C:m:M:U:F:f:c:r:B:E:s:y:O:bpenxX", long_option, NULL)) < 0)
db6034
 			break;
db6034
 		switch (c) {
db6034
 		case 'h':
db6034
@@ -643,6 +652,9 @@ int main(int argc, char *argv[])
db6034
 		case 'X':
db6034
 			realtime_check = 1;
db6034
 			break;
db6034
+		case 'O':
db6034
+			sched_policy = optarg;
db6034
+			break;
db6034
 		}
db6034
 	}
db6034
 
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 75f8e2e73e03f628a4f2ba55ca8aa3e9f50cdbd9 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Thu, 24 Nov 2022 10:55:32 +0100
db6034
Subject: [PATCH 15/20] test: latency - --policy option - allow using
db6034
 SCHED_OTHER
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 test/latency.c | 5 ++++-
db6034
 1 file changed, 4 insertions(+), 1 deletion(-)
db6034
db6034
diff --git a/test/latency.c b/test/latency.c
db6034
index 3b20e1c1..5e67015c 100644
db6034
--- a/test/latency.c
db6034
+++ b/test/latency.c
db6034
@@ -361,6 +361,9 @@ void setscheduler(void)
db6034
 	if (strcasecmp(sched_policy, "fifo") == 0) {
db6034
 		policy = SCHED_FIFO;
db6034
 		spolicy = "FIFO";
db6034
+	} else if (strcasecmp(sched_policy, "other") == 0) {
db6034
+		policy = SCHED_OTHER;
db6034
+		spolicy = "OTHER";
db6034
 	}
db6034
 	if (sched_getparam(0, &sched_param) < 0) {
db6034
 		printf("Scheduler getparam failed...\n");
db6034
@@ -522,7 +525,7 @@ void help(void)
db6034
 "-e,--effect    apply an effect (bandpass filter sweep)\n"
db6034
 "-x,--posdump   dump buffer positions\n"
db6034
 "-X,--realtime  do a realtime check (buffering)\n"
db6034
-"-O,--policy    set scheduler policy (RR or FIFO)\n"
db6034
+"-O,--policy    set scheduler policy (RR, FIFO or OTHER)\n"
db6034
 );
db6034
         printf("Recognized sample formats are:");
db6034
         for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From d28e8cb29485cc93f741b01dc65893c798359963 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Tue, 29 Nov 2022 19:42:13 +0100
db6034
Subject: [PATCH 16/20] topology: ctl - remove the wrong (debug) code
db6034
db6034
This code was commited by mistake. It was used for testing
db6034
of ALSA_PCM_OLD_HW/SW_PARAMS_API.
db6034
db6034
BugLink: https://github.com/thesofproject/sof/issues/6667
db6034
Related-to: 78b20e3c ("test: latency - use snd_pcm_format_physical_width()")
db6034
Reported-by: Jaska Uimonen <jaska.uimonen@linux.intel.com>
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/topology/ctl.c | 7 +------
db6034
 1 file changed, 1 insertion(+), 6 deletions(-)
db6034
db6034
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
db6034
index 2c500ffc..dd05424d 100644
db6034
--- a/src/topology/ctl.c
db6034
+++ b/src/topology/ctl.c
db6034
@@ -17,13 +17,9 @@
db6034
            Liam Girdwood <liam.r.girdwood@linux.intel.com>
db6034
 */
db6034
 
db6034
-#define ALSA_PCM_OLD_HW_PARAMS_API 1
db6034
-#define ALSA_PCM_OLD_SW_PARAMS_API 1
db6034
-#include "../../include/asoundlib.h"
db6034
 #include "list.h"
db6034
 #include "tplg_local.h"
db6034
 
db6034
-
db6034
 #define ENUM_VAL_SIZE 	(SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
db6034
 
db6034
 struct ctl_access_elem {
db6034
@@ -75,8 +71,7 @@ static int parse_access_values(snd_config_t *cfg,
db6034
 			}
db6034
 		}
db6034
 	}
db6034
-	return snd_pcm_hw_params_get_channels(NULL);
db6034
-	//return snd_pcm_hw_params_get_access(NULL);
db6034
+
db6034
 	return 0;
db6034
 }
db6034
 
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From e29413a2205099b2bffe584210d7a2b59f531f90 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 7 Dec 2022 14:49:48 +0100
db6034
Subject: [PATCH 17/20] ucm: execute_sysw - fix possible use-after-free
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/ucm/main.c | 5 +++--
db6034
 1 file changed, 3 insertions(+), 2 deletions(-)
db6034
db6034
diff --git a/src/ucm/main.c b/src/ucm/main.c
db6034
index 4f36648c..2ff4d3f3 100644
db6034
--- a/src/ucm/main.c
db6034
+++ b/src/ucm/main.c
db6034
@@ -572,16 +572,17 @@ static int execute_sysw(const char *sysw)
db6034
 	wlen = write(fd, value, len);
db6034
 	myerrno = errno;
db6034
 	close(fd);
db6034
-	free(s);
db6034
 
db6034
 	if (ignore_error)
db6034
-		return 0;
db6034
+		goto __end;
db6034
 
db6034
 	if (wlen != (ssize_t)len) {
db6034
 		uc_error("unable to write '%s' to '%s': %s", value, path, strerror(myerrno));
db6034
 		return -EINVAL;
db6034
 	}
db6034
 
db6034
+__end:
db6034
+	free(s);
db6034
 	return 0;
db6034
 }
db6034
 
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 13e31fb1ecd5f666ffda09e87ef1aa53b4fae022 Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Wed, 7 Dec 2022 14:54:30 +0100
db6034
Subject: [PATCH 18/20] alsa-lib: conf - fix possible use-after-free in
db6034
 get_char_skip_comments
db6034
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/conf.c | 3 ++-
db6034
 1 file changed, 2 insertions(+), 1 deletion(-)
db6034
db6034
diff --git a/src/conf.c b/src/conf.c
db6034
index eb38c344..65f2e1a7 100644
db6034
--- a/src/conf.c
db6034
+++ b/src/conf.c
db6034
@@ -814,11 +814,12 @@ static int get_char_skip_comments(input_t *input)
db6034
 				closedir(dirp);
db6034
 
db6034
 				err = add_include_path(input->current, str);
db6034
-				free(str);
db6034
 				if (err < 0) {
db6034
 					SNDERR("Cannot add search dir %s", str);
db6034
+					free(str);
db6034
 					return err;
db6034
 				}
db6034
+				free(str);
db6034
 				continue;
db6034
 			}
db6034
 
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 9f2c68cef716aa45942b502a42d94b84289f23bc Mon Sep 17 00:00:00 2001
db6034
From: Jaroslav Kysela <perex@perex.cz>
db6034
Date: Tue, 13 Dec 2022 10:31:32 +0100
db6034
Subject: [PATCH 19/20] pcm: route/softvol use snd_config_get_ireal vs get_real
db6034
 to handle also integers
db6034
db6034
Link: https://lore.kernel.org/alsa-devel/f9a7ad6a256d4ad7a31642dcf875d436@axis.com/
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/pcm/pcm_route.c   | 11 +++--------
db6034
 src/pcm/pcm_softvol.c |  4 ++--
db6034
 2 files changed, 5 insertions(+), 10 deletions(-)
db6034
db6034
diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c
db6034
index d3e5f3ff..21b869cc 100644
db6034
--- a/src/pcm/pcm_route.c
db6034
+++ b/src/pcm/pcm_route.c
db6034
@@ -1182,15 +1182,10 @@ static int _snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_ent
db6034
 				return -EINVAL;
db6034
 			}
db6034
 
db6034
-			err = snd_config_get_real(jnode, &value);
db6034
+			err = snd_config_get_ireal(jnode, &value);
db6034
 			if (err < 0) {
db6034
-				long v;
db6034
-				err = snd_config_get_integer(jnode, &v);
db6034
-				if (err < 0) {
db6034
-					SNDERR("Invalid type for %s", id);
db6034
-					return -EINVAL;
db6034
-				}
db6034
-				value = v;
db6034
+				SNDERR("Invalid type for %s", id);
db6034
+				return -EINVAL;
db6034
 			}
db6034
 
db6034
 			for (k = 0; (int) k < ss; k++) {
db6034
diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c
db6034
index 99d0d32e..3e3dbc79 100644
db6034
--- a/src/pcm/pcm_softvol.c
db6034
+++ b/src/pcm/pcm_softvol.c
db6034
@@ -1190,7 +1190,7 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
db6034
 			continue;
db6034
 		}
db6034
 		if (strcmp(id, "min_dB") == 0) {
db6034
-			err = snd_config_get_real(n, &min_dB);
db6034
+			err = snd_config_get_ireal(n, &min_dB);
db6034
 			if (err < 0) {
db6034
 				SNDERR("Invalid min_dB value");
db6034
 				return err;
db6034
@@ -1198,7 +1198,7 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
db6034
 			continue;
db6034
 		}
db6034
 		if (strcmp(id, "max_dB") == 0) {
db6034
-			err = snd_config_get_real(n, &max_dB);
db6034
+			err = snd_config_get_ireal(n, &max_dB);
db6034
 			if (err < 0) {
db6034
 				SNDERR("Invalid max_dB value");
db6034
 				return err;
db6034
-- 
db6034
2.39.0
db6034
db6034
db6034
From 2e82060ebcd68f5ea1fe3dccc5a6518008132a54 Mon Sep 17 00:00:00 2001
db6034
From: Alan Young <consult.awy@gmail.com>
db6034
Date: Fri, 30 Dec 2022 16:48:14 +0000
db6034
Subject: [PATCH 20/20] pcm: rate: fix last_commit_ptr boundary wrapping
db6034
db6034
Wrap last_commit_ptr using boundary. Was just wrapped to 0, which is
db6034
correct only if the buffer size, and hence the boundary, is an integer
db6034
multiple of the period size.
db6034
db6034
Fixes: 467d69c5bc1 ("Fix CPU hog with combination of rate plugin")
db6034
Fixes: 29041c52207 ("fix infinite draining of the rate plugin in SND_PCM_NONBLOCK mode")
db6034
Link: https://lore.kernel.org/alsa-devel/20221230164814.901457-1-consult.awy@gmail.com/
db6034
Signed-off-by: Alan Young <consult.awy@gmail.com>
db6034
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
db6034
---
db6034
 src/pcm/pcm_rate.c | 4 ++--
db6034
 1 file changed, 2 insertions(+), 2 deletions(-)
db6034
db6034
diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c
db6034
index e5d8eddd..c8076859 100644
db6034
--- a/src/pcm/pcm_rate.c
db6034
+++ b/src/pcm/pcm_rate.c
db6034
@@ -1018,7 +1018,7 @@ static int snd_pcm_rate_sync_playback_area(snd_pcm_t *pcm, snd_pcm_uframes_t app
db6034
 		slave_size -= rate->gen.slave->period_size;
db6034
 		rate->last_commit_ptr += pcm->period_size;
db6034
 		if (rate->last_commit_ptr >= pcm->boundary)
db6034
-			rate->last_commit_ptr = 0;
db6034
+			rate->last_commit_ptr -= pcm->boundary;
db6034
 	}
db6034
 	return 0;
db6034
 }
db6034
@@ -1163,7 +1163,7 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm)
db6034
 			if (commit_err == 1) {
db6034
 				rate->last_commit_ptr += psize;
db6034
 				if (rate->last_commit_ptr >= pcm->boundary)
db6034
-					rate->last_commit_ptr = 0;
db6034
+					rate->last_commit_ptr -= pcm->boundary;
db6034
 			} else if (commit_err == 0) {
db6034
 				if (pcm->mode & SND_PCM_NONBLOCK) {
db6034
 					commit_err = -EAGAIN;
db6034
-- 
db6034
2.39.0
db6034