From 65e2f01b65d1ebb6d5254a244087251792cef35f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 31 May 2021 12:25:18 +0200 Subject: [PATCH 01/10] update to 1.2.5 --- alsa-lib.spec | 11 +++++++---- sources | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/alsa-lib.spec b/alsa-lib.spec index 6519280..2267c37 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -2,14 +2,14 @@ #define prever_dot .rc3 #define postver a -%define version_alsa_lib 1.2.4 -%define version_alsa_ucm 1.2.4 -%define version_alsa_tplg 1.2.4 +%define version_alsa_lib 1.2.5 +%define version_alsa_ucm 1.2.5 +%define version_alsa_tplg 1.2.5 Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 5%{?prever_dot}%{?dist} +Release: 1%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,6 +167,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Mon May 31 2021 Jaroslav Kysela - 1.2.5-1 +- update to 1.2.5 + * Tue Jan 26 2021 Fedora Release Engineering - 1.2.4-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild diff --git a/sources b/sources index 904929f..b10f9d4 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (alsa-lib-1.2.4.tar.bz2) = 12086952dc8f16f1cb6946517858e17b1c3276aeda9ff5703a84bb38aa78eb4c4e9cb4485c5b3f21f174fdbd976b3bcbbc481e85cb2460652858490df51ae844 -SHA512 (alsa-ucm-conf-1.2.4.tar.bz2) = 9043460e92b2ed44757b08b9faca888e8bfae40d84e4ad7e7df44df2bb3b0617e86ef23783973accd62fb6681788262e67212e2bf67178d75781e57a0fa346d2 -SHA512 (alsa-topology-conf-1.2.4.tar.bz2) = e5b367a23f42ed2c2a83f3dd9df264b4e054f5ba7c4be98520418598f0b06a11627498a8a6ef943522b209951645f83bbbbfb32db7c9c8260aa5db08358970cb +SHA512 (alsa-lib-1.2.5.tar.bz2) = d9b53484737a3684aac7e08b4b18400aac10fec1a78a8bf9101944bea2c50710bc7355e9bb0012541b067e2d5ee7b1b818bf1bdbffbb2b2d7ad0eb15efe49725 +SHA512 (alsa-topology-conf-1.2.5.tar.bz2) = 2eb4d8baf2dcbf0b631dd11dbf15bffc51694d9cc6931619e51787f3ba58d1a091d266e6721a3b737c040ec74a28270b93f39fb97f30a3227cf340dd646e5d51 +SHA512 (alsa-ucm-conf-1.2.5.tar.bz2) = f16e8f04018c65de5e24f2a3eb0b3edff26cbce78cc1820c42c46907c903913c571797b59e803ae36b8ec3136487d0a5aacd034e2a8df3e15ed998b7a70152b7 From 7071ae2637fbabd3476a45fbc7da626074fedcc8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 2 Jun 2021 19:21:12 +0200 Subject: [PATCH 02/10] 1.2.5 fixes --- alsa-git.patch | 728 ++++++++++++++++++++++++++++++++++++++++++++ alsa-lib.spec | 5 +- alsa-ucm-conf.patch | 14 + 3 files changed, 746 insertions(+), 1 deletion(-) diff --git a/alsa-git.patch b/alsa-git.patch index e69de29..b42c2d2 100644 --- a/alsa-git.patch +++ b/alsa-git.patch @@ -0,0 +1,728 @@ +From ddfc32abf5697de1618b9e7ffdf57a0f97013090 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 08:49:32 +0200 +Subject: [PATCH 01/18] conf: fix load_for_all_cards() + +The 63f7745b commit is loading the driver specific configuration +multiple times which ends with the array merges (see the bug). + +Introduce the loaded compound which traces the already loaded +driver configurations and skip the multiple load requests. + +Fixes: https://github.com/alsa-project/alsa-lib/issues/143 +Fixes: 63f7745b ("conf: extend load_for_all_cards hook (id/value table)") +Signed-off-by: Jaroslav Kysela +--- + src/conf.c | 33 ++++++++++++++++++++++++++++----- + 1 file changed, 28 insertions(+), 5 deletions(-) + +diff --git a/src/conf.c b/src/conf.c +index f6c80031..d863dec6 100644 +--- a/src/conf.c ++++ b/src/conf.c +@@ -4325,18 +4325,23 @@ static int _snd_config_hook_table(snd_config_t *root, snd_config_t *config, snd_ + int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data ATTRIBUTE_UNUSED) + { + int card = -1, err; ++ snd_config_t *loaded; // trace loaded cards + ++ err = snd_config_top(&loaded); ++ if (err < 0) ++ return err; + do { + err = snd_card_next(&card); + if (err < 0) +- return err; ++ goto __fin_err; + if (card >= 0) { +- snd_config_t *n, *private_data = NULL; ++ snd_config_t *n, *m, *private_data = NULL; + const char *driver; + char *fdriver = NULL; ++ bool load; + err = snd_determine_driver(card, &fdriver); + if (err < 0) +- return err; ++ goto __fin_err; + if (snd_config_search(root, fdriver, &n) >= 0) { + if (snd_config_get_string(n, &driver) < 0) { + if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND) { +@@ -4357,6 +4362,19 @@ int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, + driver = fdriver; + } + __std: ++ load = true; ++ err = snd_config_imake_integer(&m, driver, 1); ++ if (err < 0) ++ goto __err; ++ err = snd_config_add(loaded, m); ++ if (err < 0) { ++ if (err == -EEXIST) { ++ snd_config_delete(m); ++ load = false; ++ } else { ++ goto __err; ++ } ++ } + private_data = _snd_config_hook_private_data(card, driver); + if (!private_data) { + err = -ENOMEM; +@@ -4365,17 +4383,22 @@ int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, + err = _snd_config_hook_table(root, config, private_data); + if (err < 0) + goto __err; +- err = snd_config_hook_load(root, config, &n, private_data); ++ if (load) ++ err = snd_config_hook_load(root, config, &n, private_data); + __err: + if (private_data) + snd_config_delete(private_data); + free(fdriver); + if (err < 0) +- return err; ++ goto __fin_err; + } + } while (card >= 0); ++ snd_config_delete(loaded); + *dst = NULL; + return 0; ++__fin_err: ++ snd_config_delete(loaded); ++ return err; + } + #ifndef DOC_HIDDEN + SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK); +-- +2.30.2 + + +From 0e4ba2ea8c0402f12a645032a14693eb9b1278e6 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 11:09:43 +0200 +Subject: [PATCH 02/18] ucm: add _alibpref to get the private device prefix + +It may be useful to get the device prefix for the local configuration. + +Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1251 +Signed-off-by: Jaroslav Kysela +--- + include/use-case.h | 1 + + src/ucm/main.c | 21 +++++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/include/use-case.h b/include/use-case.h +index ec1a97b0..7890358b 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -258,6 +258,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * - _verb - return current verb + * - _file - return configuration file loaded for current card + * - _alibcfg - return private alsa-lib's configuration for current card ++ * - _alibpref - return private alsa-lib's configuration device prefix for current card + * + * - [=]{NAME}[/[{modifier}|{/device}][/{verb}]] + * - value identifier {NAME} +diff --git a/src/ucm/main.c b/src/ucm/main.c +index 361952f6..3c9ea15d 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -2138,6 +2138,25 @@ static int get_alibcfg(snd_use_case_mgr_t *uc_mgr, char **str) + return 0; + } + ++/** ++ * \brief Get device prefix for private alsa-lib configuration ++ * \param uc_mgr Use case manager ++ * \param str Returned value string ++ * \return Zero on success (value is filled), otherwise a negative error code ++ */ ++static int get_alibpref(snd_use_case_mgr_t *uc_mgr, char **str) ++{ ++ const size_t l = 9; ++ char *s; ++ ++ s = malloc(l); ++ if (s == NULL) ++ return -ENOMEM; ++ snprintf(s, l, "_ucm%04X", uc_mgr->ucm_card_number); ++ *str = s; ++ return 0; ++} ++ + /** + * \brief Get current - string + * \param uc_mgr Use case manager +@@ -2193,6 +2212,8 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr, + + } else if (strcmp(identifier, "_alibcfg") == 0) { + err = get_alibcfg(uc_mgr, (char **)value); ++ } else if (strcmp(identifier, "_alibpref") == 0) { ++ err = get_alibpref(uc_mgr, (char **)value); + } else if (identifier[0] == '_') { + err = -ENOENT; + } else { +-- +2.30.2 + + +From 9621d0bff2e60b43e329ffa5059ab19f2914ec14 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 11:21:54 +0200 +Subject: [PATCH 03/18] ucm: fix _alibpref string (add '.' delimiter to the + end) + +Fixes: 0e4ba2ea ("ucm: add _alibpref to get the private device prefix") +Signed-off-by: Jaroslav Kysela +--- + src/ucm/main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/ucm/main.c b/src/ucm/main.c +index 3c9ea15d..c9b37b68 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -2146,13 +2146,13 @@ static int get_alibcfg(snd_use_case_mgr_t *uc_mgr, char **str) + */ + static int get_alibpref(snd_use_case_mgr_t *uc_mgr, char **str) + { +- const size_t l = 9; ++ const size_t l = 10; + char *s; + + s = malloc(l); + if (s == NULL) + return -ENOMEM; +- snprintf(s, l, "_ucm%04X", uc_mgr->ucm_card_number); ++ snprintf(s, l, "_ucm%04X.", uc_mgr->ucm_card_number); + *str = s; + return 0; + } +-- +2.30.2 + + +From 2a1dafdbe5932260aeb4db359ce5d630b8106889 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:26:47 +0200 +Subject: [PATCH 04/18] conf: remove dead code in snd_config_get_card() + +Signed-off-by: Jaroslav Kysela +--- + src/confmisc.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/confmisc.c b/src/confmisc.c +index 3663d164..a561040c 100644 +--- a/src/confmisc.c ++++ b/src/confmisc.c +@@ -154,10 +154,10 @@ int snd_config_get_card(const snd_config_t *conf) + long v; + int err; + +- if ((err = snd_config_get_integer(conf, &v)) < 0) { ++ if (snd_config_get_integer(conf, &v) < 0) { + if ((err = snd_config_get_string(conf, &str)) < 0) { +- snd_config_get_id(conf, &id); +- SNDERR("Invalid field %s", id); ++ if (snd_config_get_id(conf, &id) >= 0) ++ SNDERR("Invalid field %s", id); + return -EINVAL; + } + err = snd_card_get_index(str); +-- +2.30.2 + + +From 013ec607db9de11b682f2b85d843be062ca0d046 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:28:32 +0200 +Subject: [PATCH 05/18] control: remap - fix uninitialized value in + parse_map_vindex() + +Signed-off-by: Jaroslav Kysela +--- + src/control/control_remap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/control/control_remap.c b/src/control/control_remap.c +index f3d65010..17c6558a 100644 +--- a/src/control/control_remap.c ++++ b/src/control/control_remap.c +@@ -1040,7 +1040,7 @@ static int parse_map_vindex(struct snd_ctl_map_ctl *mctl, snd_config_t *conf) + + snd_config_for_each(i, next, conf) { + snd_config_t *n = snd_config_iterator_entry(i); +- long idx, chn; ++ long idx = -1, chn = -1; + const char *id; + if (snd_config_get_id(n, &id) < 0) + continue; +-- +2.30.2 + + +From 2fee6af9b6e157475159d284af8de1e879bb7a36 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:35:44 +0200 +Subject: [PATCH 06/18] pcm: direct - fix pcmp error path in + _snd_pcm_direct_new() + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_direct.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index 0e5e0421..361805bd 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -2126,24 +2126,20 @@ int _snd_pcm_direct_new(snd_pcm_t **pcmp, snd_pcm_direct_t **_dmix, int type, + dmix->type = type; + + ret = snd_pcm_new(pcmp, type, name, stream, mode); +- if (ret < 0) { +-_err_nosem: +- free(dmix->bindings); +- free(dmix); +- return ret; +- } ++ if (ret < 0) ++ goto _err_nosem; + + while (1) { + ret = snd_pcm_direct_semaphore_create_or_connect(dmix); + if (ret < 0) { + SNDERR("unable to create IPC semaphore"); +- goto _err_nosem; ++ goto _err_nosem_free; + } + ret = snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); + if (ret < 0) { + snd_pcm_direct_semaphore_discard(dmix); + if (--fail_sem_loop <= 0) +- goto _err_nosem; ++ goto _err_nosem_free; + continue; + } + break; +@@ -2153,10 +2149,17 @@ _err_nosem: + if (ret < 0) { + SNDERR("unable to create IPC shm instance"); + snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); +- goto _err_nosem; ++ goto _err_nosem_free; + } else { + *_dmix = dmix; + } + ++ return ret; ++_err_nosem_free: ++ snd_pcm_free(*pcmp); ++ *pcmp = NULL; ++_err_nosem: ++ free(dmix->bindings); ++ free(dmix); + return ret; + } +-- +2.30.2 + + +From eb95cad4e22a0bf2577f1fa4a3f6fd18caed3362 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:37:53 +0200 +Subject: [PATCH 07/18] pcm: remove extra NULL checks in snd_pcm_dmix_open() + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_dmix.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c +index 8747450f..608593f1 100644 +--- a/src/pcm/pcm_dmix.c ++++ b/src/pcm/pcm_dmix.c +@@ -998,7 +998,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, + snd_config_t *root, snd_config_t *sconf, + snd_pcm_stream_t stream, int mode) + { +- snd_pcm_t *pcm = NULL, *spcm = NULL; ++ snd_pcm_t *pcm, *spcm = NULL; + snd_pcm_direct_t *dmix; + int ret, first_instance; + +@@ -1154,12 +1154,9 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, + } else + snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); + _err_nosem: +- if (dmix) { +- free(dmix->bindings); +- free(dmix); +- } +- if (pcm) +- snd_pcm_free(pcm); ++ free(dmix->bindings); ++ free(dmix); ++ snd_pcm_free(pcm); + return ret; + } + +-- +2.30.2 + + +From 01a45aec6fcd5a5378a5b5e0ae0f9dacde2068e4 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:39:32 +0200 +Subject: [PATCH 08/18] pcm: remove extra NULL checks in snd_pcm_dsnoop_open() + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_dsnoop.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c +index fb1b02c2..2c3b9f43 100644 +--- a/src/pcm/pcm_dsnoop.c ++++ b/src/pcm/pcm_dsnoop.c +@@ -564,8 +564,8 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, + snd_config_t *root, snd_config_t *sconf, + snd_pcm_stream_t stream, int mode) + { +- snd_pcm_t *pcm = NULL, *spcm = NULL; +- snd_pcm_direct_t *dsnoop = NULL; ++ snd_pcm_t *pcm, *spcm = NULL; ++ snd_pcm_direct_t *dsnoop; + int ret, first_instance; + + assert(pcmp); +@@ -708,12 +708,9 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, + snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT); + + _err_nosem: +- if (dsnoop) { +- free(dsnoop->bindings); +- free(dsnoop); +- } +- if (pcm) +- snd_pcm_free(pcm); ++ free(dsnoop->bindings); ++ free(dsnoop); ++ snd_pcm_free(pcm); + return ret; + } + +-- +2.30.2 + + +From 74c6382df6cf18b801659d8c5c53407a7ea1f02b Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:46:46 +0200 +Subject: [PATCH 09/18] pcm: remove extra NULL checks in snd_pcm_dshare_open() + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_dshare.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c +index 0f5238a6..a918512b 100644 +--- a/src/pcm/pcm_dshare.c ++++ b/src/pcm/pcm_dshare.c +@@ -690,8 +690,8 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, + snd_config_t *root, snd_config_t *sconf, + snd_pcm_stream_t stream, int mode) + { +- snd_pcm_t *pcm = NULL, *spcm = NULL; +- snd_pcm_direct_t *dshare = NULL; ++ snd_pcm_t *pcm, *spcm = NULL; ++ snd_pcm_direct_t *dshare; + int ret, first_instance; + unsigned int chn; + +@@ -851,12 +851,9 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, + } else + snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT); + _err_nosem: +- if (dshare) { +- free(dshare->bindings); +- free(dshare); +- } +- if (pcm) +- snd_pcm_free(pcm); ++ free(dshare->bindings); ++ free(dshare); ++ snd_pcm_free(pcm); + return ret; + } + +-- +2.30.2 + + +From eabadf545c51d4c88c5f359db73726ec3ac653ba Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:49:29 +0200 +Subject: [PATCH 10/18] pcm: softvol - fix early exit in add_tlv_info() + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_softvol.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c +index e2bdd31a..eea322ca 100644 +--- a/src/pcm/pcm_softvol.c ++++ b/src/pcm/pcm_softvol.c +@@ -711,13 +711,13 @@ static int add_tlv_info(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo, + unsigned int *old_tlv, size_t old_tlv_size) + { + unsigned int tlv[4]; +- if (sizeof(tlv) <= old_tlv_size && memcmp(tlv, old_tlv, sizeof(tlv)) == 0) +- return 0; + tlv[SNDRV_CTL_TLVO_TYPE] = SND_CTL_TLVT_DB_SCALE; + tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(int); + tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = (int)(svol->min_dB * 100); + tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = + (int)((svol->max_dB - svol->min_dB) * 100 / svol->max_val); ++ if (sizeof(tlv) <= old_tlv_size && memcmp(tlv, old_tlv, sizeof(tlv)) == 0) ++ return 0; + return snd_ctl_elem_tlv_write(svol->ctl, &cinfo->id, tlv); + } + +-- +2.30.2 + + +From cf3846d46053b23006e6a9042b586fc78e81af55 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:50:17 +0200 +Subject: [PATCH 11/18] timer: remove dead code in _snd_timer_hw_open() + +--- + src/timer/timer_hw.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/timer/timer_hw.c b/src/timer/timer_hw.c +index cfb77463..fe4e40bb 100644 +--- a/src/timer/timer_hw.c ++++ b/src/timer/timer_hw.c +@@ -330,8 +330,6 @@ int _snd_timer_hw_open(snd_timer_t **timer, char *name, + SNDERR("Unexpected field %s", id); + return -EINVAL; + } +- if (card < 0) +- return -EINVAL; + return snd_timer_hw_open(timer, name, dev_class, dev_sclass, card, device, subdevice, mode); + } + SND_DLSYM_BUILD_VERSION(_snd_timer_hw_open, SND_TIMER_DLSYM_VERSION); +-- +2.30.2 + + +From 200d18cda7a700607c21ad5dc9faaea2a1e27dbd Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:51:13 +0200 +Subject: [PATCH 12/18] ucm: fix error path in execute_cfgsave() + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/ucm/main.c b/src/ucm/main.c +index c9b37b68..42fdaa1d 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -605,8 +605,10 @@ static int execute_cfgsave(snd_use_case_mgr_t *uc_mgr, const char *filename) + uc_error("unable to open file '%s': %s", file, snd_strerror(err)); + goto _err; + } +- if (!config || snd_config_is_empty(config)) ++ if (!config || snd_config_is_empty(config)) { ++ snd_output_close(out); + goto _err; ++ } + if (with_root) { + snd_output_printf(out, "%s ", root); + err = _snd_config_save_node_value(config, out, 0); +-- +2.30.2 + + +From 9b71d53bde21c8bb0d900c17863664e12753d844 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:52:12 +0200 +Subject: [PATCH 13/18] ucm: fix use after free in if_eval_regex_match() + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/ucm_cond.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/ucm/ucm_cond.c b/src/ucm/ucm_cond.c +index 59d1a155..adb0ecd9 100644 +--- a/src/ucm/ucm_cond.c ++++ b/src/ucm/ucm_cond.c +@@ -160,11 +160,12 @@ static int if_eval_regex_match(snd_use_case_mgr_t *uc_mgr, snd_config_t *eval) + if (err < 0) + return err; + err = regcomp(&re, s, options); +- free(s); + if (err) { + uc_error("Regex '%s' compilation failed (code %d)", s, err); ++ free(s); + return -EINVAL; + } ++ free(s); + + err = uc_mgr_get_substituted_value(uc_mgr, &s, string); + if (err < 0) { +-- +2.30.2 + + +From 7764e3e621a4c8a52327833d44e32c8b6fe3a131 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:53:24 +0200 +Subject: [PATCH 14/18] ucm: fix if_eval_path() - access NULL pointer + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/ucm_cond.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ucm/ucm_cond.c b/src/ucm/ucm_cond.c +index adb0ecd9..0ed0b690 100644 +--- a/src/ucm/ucm_cond.c ++++ b/src/ucm/ucm_cond.c +@@ -272,7 +272,7 @@ static int if_eval_control_exists(snd_use_case_mgr_t *uc_mgr, snd_config_t *eval + + static int if_eval_path(snd_use_case_mgr_t *uc_mgr, snd_config_t *eval) + { +- const char *path, *mode = NULL; ++ const char *path, *mode = ""; + int err, amode = F_OK; + + if (uc_mgr->conf_format < 4) { +-- +2.30.2 + + +From 7fcb1aadd56e94f03e51c4747e72d77279151c22 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:56:01 +0200 +Subject: [PATCH 15/18] ucm: find_exec() - fix memory leak (dir) + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/ucm_exec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/ucm/ucm_exec.c b/src/ucm/ucm_exec.c +index a22df8fe..1cdb2633 100644 +--- a/src/ucm/ucm_exec.c ++++ b/src/ucm/ucm_exec.c +@@ -73,6 +73,7 @@ static int find_exec(const char *name, char *out, size_t len) + || !(st.st_mode & S_IEXEC)) + continue; + snd_strlcpy(out, bin, len); ++ closedir(dir); + return 1; + } + closedir(dir); +-- +2.30.2 + + +From 26ab7fc3e4cba416cf51aa0fb48fdddaa0d861ee Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:58:04 +0200 +Subject: [PATCH 16/18] ucm: fix possible NULL pointer dereference in + uc_mgr_exec() + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/ucm_exec.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/ucm/ucm_exec.c b/src/ucm/ucm_exec.c +index 1cdb2633..d83206d0 100644 +--- a/src/ucm/ucm_exec.c ++++ b/src/ucm/ucm_exec.c +@@ -185,7 +185,11 @@ int uc_mgr_exec(const char *prog) + return -EINVAL; + + prog = argv[0]; +- if (argv[0][0] != '/' && argv[0][0] != '.') { ++ if (prog == NULL) { ++ err = -EINVAL; ++ goto __error; ++ } ++ if (prog[0] != '/' && prog[0] != '.') { + if (!find_exec(argv[0], bin, sizeof(bin))) { + err = -ENOEXEC; + goto __error; +-- +2.30.2 + + +From 64a6d4d1e827732bef7c68e1e6d2cb6863b4597c Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 19:59:10 +0200 +Subject: [PATCH 17/18] ucm: check error value in parse_lookup_query() + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/ucm_subs.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c +index c56730c5..0bc4e63f 100644 +--- a/src/ucm/ucm_subs.c ++++ b/src/ucm/ucm_subs.c +@@ -224,7 +224,11 @@ static snd_config_t *parse_lookup_query(const char *query) + uc_error("unable to create memory input buffer"); + return NULL; + } +- snd_config_top(&config); ++ err = snd_config_top(&config); ++ if (err < 0) { ++ snd_input_close(input); ++ return NULL; ++ } + err = snd_config_load(config, input); + snd_input_close(input); + if (err < 0) { +-- +2.30.2 + + +From 30d1d256e792fbabf14c57efb98c489541b19f37 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 2 Jun 2021 20:01:08 +0200 +Subject: [PATCH 18/18] ucm: fix out-of-array access in + rval_device_lookup_init() + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/ucm_subs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c +index 0bc4e63f..20905c3f 100644 +--- a/src/ucm/ucm_subs.c ++++ b/src/ucm/ucm_subs.c +@@ -489,7 +489,7 @@ static int rval_device_lookup_init(snd_use_case_mgr_t *uc_mgr, + uc_error("Missing device type!"); + return -EINVAL; + } +- for (t = types; t; t++) ++ for (t = types; t->name; t++) + if (strcasecmp(t->name, s) == 0) + return t->init(iter, config); + uc_error("Device type '%s' is invalid", s); +-- +2.30.2 + diff --git a/alsa-lib.spec b/alsa-lib.spec index 2267c37..f25538e 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -9,7 +9,7 @@ Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 1%{?prever_dot}%{?dist} +Release: 2%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,6 +167,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Wed Jun 2 2021 Jaroslav Kysela - 1.2.5-2 +- add upstream fixes (conf + ucm) + * Mon May 31 2021 Jaroslav Kysela - 1.2.5-1 - update to 1.2.5 diff --git a/alsa-ucm-conf.patch b/alsa-ucm-conf.patch index e69de29..dedf95f 100644 --- a/alsa-ucm-conf.patch +++ b/alsa-ucm-conf.patch @@ -0,0 +1,14 @@ +diff --git a/ucm2/HDA-Intel/HDA-Intel.conf b/ucm2/HDA-Intel/HDA-Intel.conf +index 5794e72..8a8e0e7 100644 +--- a/ucm2/HDA-Intel/HDA-Intel.conf ++++ b/ucm2/HDA-Intel/HDA-Intel.conf +@@ -1,4 +1,4 @@ +-Syntax 3 ++Syntax 4 + + Define.Use "" # a non-empty string to use UCM configuration for HDA devices + +-- +2.30.2 + + From 2e32cc95a0deb6bc06d02c2ff272663fe8e20b27 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 14 Jun 2021 13:51:54 +0200 Subject: [PATCH 03/10] update to 1.2.5.1 --- alsa-git.patch | 728 -------------------------------------------- alsa-lib.spec | 9 +- alsa-ucm-conf.patch | 14 - sources | 4 +- 4 files changed, 8 insertions(+), 747 deletions(-) diff --git a/alsa-git.patch b/alsa-git.patch index b42c2d2..e69de29 100644 --- a/alsa-git.patch +++ b/alsa-git.patch @@ -1,728 +0,0 @@ -From ddfc32abf5697de1618b9e7ffdf57a0f97013090 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 08:49:32 +0200 -Subject: [PATCH 01/18] conf: fix load_for_all_cards() - -The 63f7745b commit is loading the driver specific configuration -multiple times which ends with the array merges (see the bug). - -Introduce the loaded compound which traces the already loaded -driver configurations and skip the multiple load requests. - -Fixes: https://github.com/alsa-project/alsa-lib/issues/143 -Fixes: 63f7745b ("conf: extend load_for_all_cards hook (id/value table)") -Signed-off-by: Jaroslav Kysela ---- - src/conf.c | 33 ++++++++++++++++++++++++++++----- - 1 file changed, 28 insertions(+), 5 deletions(-) - -diff --git a/src/conf.c b/src/conf.c -index f6c80031..d863dec6 100644 ---- a/src/conf.c -+++ b/src/conf.c -@@ -4325,18 +4325,23 @@ static int _snd_config_hook_table(snd_config_t *root, snd_config_t *config, snd_ - int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data ATTRIBUTE_UNUSED) - { - int card = -1, err; -+ snd_config_t *loaded; // trace loaded cards - -+ err = snd_config_top(&loaded); -+ if (err < 0) -+ return err; - do { - err = snd_card_next(&card); - if (err < 0) -- return err; -+ goto __fin_err; - if (card >= 0) { -- snd_config_t *n, *private_data = NULL; -+ snd_config_t *n, *m, *private_data = NULL; - const char *driver; - char *fdriver = NULL; -+ bool load; - err = snd_determine_driver(card, &fdriver); - if (err < 0) -- return err; -+ goto __fin_err; - if (snd_config_search(root, fdriver, &n) >= 0) { - if (snd_config_get_string(n, &driver) < 0) { - if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND) { -@@ -4357,6 +4362,19 @@ int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, - driver = fdriver; - } - __std: -+ load = true; -+ err = snd_config_imake_integer(&m, driver, 1); -+ if (err < 0) -+ goto __err; -+ err = snd_config_add(loaded, m); -+ if (err < 0) { -+ if (err == -EEXIST) { -+ snd_config_delete(m); -+ load = false; -+ } else { -+ goto __err; -+ } -+ } - private_data = _snd_config_hook_private_data(card, driver); - if (!private_data) { - err = -ENOMEM; -@@ -4365,17 +4383,22 @@ int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, - err = _snd_config_hook_table(root, config, private_data); - if (err < 0) - goto __err; -- err = snd_config_hook_load(root, config, &n, private_data); -+ if (load) -+ err = snd_config_hook_load(root, config, &n, private_data); - __err: - if (private_data) - snd_config_delete(private_data); - free(fdriver); - if (err < 0) -- return err; -+ goto __fin_err; - } - } while (card >= 0); -+ snd_config_delete(loaded); - *dst = NULL; - return 0; -+__fin_err: -+ snd_config_delete(loaded); -+ return err; - } - #ifndef DOC_HIDDEN - SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK); --- -2.30.2 - - -From 0e4ba2ea8c0402f12a645032a14693eb9b1278e6 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 11:09:43 +0200 -Subject: [PATCH 02/18] ucm: add _alibpref to get the private device prefix - -It may be useful to get the device prefix for the local configuration. - -Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1251 -Signed-off-by: Jaroslav Kysela ---- - include/use-case.h | 1 + - src/ucm/main.c | 21 +++++++++++++++++++++ - 2 files changed, 22 insertions(+) - -diff --git a/include/use-case.h b/include/use-case.h -index ec1a97b0..7890358b 100644 ---- a/include/use-case.h -+++ b/include/use-case.h -@@ -258,6 +258,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, - * - _verb - return current verb - * - _file - return configuration file loaded for current card - * - _alibcfg - return private alsa-lib's configuration for current card -+ * - _alibpref - return private alsa-lib's configuration device prefix for current card - * - * - [=]{NAME}[/[{modifier}|{/device}][/{verb}]] - * - value identifier {NAME} -diff --git a/src/ucm/main.c b/src/ucm/main.c -index 361952f6..3c9ea15d 100644 ---- a/src/ucm/main.c -+++ b/src/ucm/main.c -@@ -2138,6 +2138,25 @@ static int get_alibcfg(snd_use_case_mgr_t *uc_mgr, char **str) - return 0; - } - -+/** -+ * \brief Get device prefix for private alsa-lib configuration -+ * \param uc_mgr Use case manager -+ * \param str Returned value string -+ * \return Zero on success (value is filled), otherwise a negative error code -+ */ -+static int get_alibpref(snd_use_case_mgr_t *uc_mgr, char **str) -+{ -+ const size_t l = 9; -+ char *s; -+ -+ s = malloc(l); -+ if (s == NULL) -+ return -ENOMEM; -+ snprintf(s, l, "_ucm%04X", uc_mgr->ucm_card_number); -+ *str = s; -+ return 0; -+} -+ - /** - * \brief Get current - string - * \param uc_mgr Use case manager -@@ -2193,6 +2212,8 @@ int snd_use_case_get(snd_use_case_mgr_t *uc_mgr, - - } else if (strcmp(identifier, "_alibcfg") == 0) { - err = get_alibcfg(uc_mgr, (char **)value); -+ } else if (strcmp(identifier, "_alibpref") == 0) { -+ err = get_alibpref(uc_mgr, (char **)value); - } else if (identifier[0] == '_') { - err = -ENOENT; - } else { --- -2.30.2 - - -From 9621d0bff2e60b43e329ffa5059ab19f2914ec14 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 11:21:54 +0200 -Subject: [PATCH 03/18] ucm: fix _alibpref string (add '.' delimiter to the - end) - -Fixes: 0e4ba2ea ("ucm: add _alibpref to get the private device prefix") -Signed-off-by: Jaroslav Kysela ---- - src/ucm/main.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/ucm/main.c b/src/ucm/main.c -index 3c9ea15d..c9b37b68 100644 ---- a/src/ucm/main.c -+++ b/src/ucm/main.c -@@ -2146,13 +2146,13 @@ static int get_alibcfg(snd_use_case_mgr_t *uc_mgr, char **str) - */ - static int get_alibpref(snd_use_case_mgr_t *uc_mgr, char **str) - { -- const size_t l = 9; -+ const size_t l = 10; - char *s; - - s = malloc(l); - if (s == NULL) - return -ENOMEM; -- snprintf(s, l, "_ucm%04X", uc_mgr->ucm_card_number); -+ snprintf(s, l, "_ucm%04X.", uc_mgr->ucm_card_number); - *str = s; - return 0; - } --- -2.30.2 - - -From 2a1dafdbe5932260aeb4db359ce5d630b8106889 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:26:47 +0200 -Subject: [PATCH 04/18] conf: remove dead code in snd_config_get_card() - -Signed-off-by: Jaroslav Kysela ---- - src/confmisc.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/confmisc.c b/src/confmisc.c -index 3663d164..a561040c 100644 ---- a/src/confmisc.c -+++ b/src/confmisc.c -@@ -154,10 +154,10 @@ int snd_config_get_card(const snd_config_t *conf) - long v; - int err; - -- if ((err = snd_config_get_integer(conf, &v)) < 0) { -+ if (snd_config_get_integer(conf, &v) < 0) { - if ((err = snd_config_get_string(conf, &str)) < 0) { -- snd_config_get_id(conf, &id); -- SNDERR("Invalid field %s", id); -+ if (snd_config_get_id(conf, &id) >= 0) -+ SNDERR("Invalid field %s", id); - return -EINVAL; - } - err = snd_card_get_index(str); --- -2.30.2 - - -From 013ec607db9de11b682f2b85d843be062ca0d046 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:28:32 +0200 -Subject: [PATCH 05/18] control: remap - fix uninitialized value in - parse_map_vindex() - -Signed-off-by: Jaroslav Kysela ---- - src/control/control_remap.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/control/control_remap.c b/src/control/control_remap.c -index f3d65010..17c6558a 100644 ---- a/src/control/control_remap.c -+++ b/src/control/control_remap.c -@@ -1040,7 +1040,7 @@ static int parse_map_vindex(struct snd_ctl_map_ctl *mctl, snd_config_t *conf) - - snd_config_for_each(i, next, conf) { - snd_config_t *n = snd_config_iterator_entry(i); -- long idx, chn; -+ long idx = -1, chn = -1; - const char *id; - if (snd_config_get_id(n, &id) < 0) - continue; --- -2.30.2 - - -From 2fee6af9b6e157475159d284af8de1e879bb7a36 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:35:44 +0200 -Subject: [PATCH 06/18] pcm: direct - fix pcmp error path in - _snd_pcm_direct_new() - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_direct.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c -index 0e5e0421..361805bd 100644 ---- a/src/pcm/pcm_direct.c -+++ b/src/pcm/pcm_direct.c -@@ -2126,24 +2126,20 @@ int _snd_pcm_direct_new(snd_pcm_t **pcmp, snd_pcm_direct_t **_dmix, int type, - dmix->type = type; - - ret = snd_pcm_new(pcmp, type, name, stream, mode); -- if (ret < 0) { --_err_nosem: -- free(dmix->bindings); -- free(dmix); -- return ret; -- } -+ if (ret < 0) -+ goto _err_nosem; - - while (1) { - ret = snd_pcm_direct_semaphore_create_or_connect(dmix); - if (ret < 0) { - SNDERR("unable to create IPC semaphore"); -- goto _err_nosem; -+ goto _err_nosem_free; - } - ret = snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); - if (ret < 0) { - snd_pcm_direct_semaphore_discard(dmix); - if (--fail_sem_loop <= 0) -- goto _err_nosem; -+ goto _err_nosem_free; - continue; - } - break; -@@ -2153,10 +2149,17 @@ _err_nosem: - if (ret < 0) { - SNDERR("unable to create IPC shm instance"); - snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); -- goto _err_nosem; -+ goto _err_nosem_free; - } else { - *_dmix = dmix; - } - -+ return ret; -+_err_nosem_free: -+ snd_pcm_free(*pcmp); -+ *pcmp = NULL; -+_err_nosem: -+ free(dmix->bindings); -+ free(dmix); - return ret; - } --- -2.30.2 - - -From eb95cad4e22a0bf2577f1fa4a3f6fd18caed3362 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:37:53 +0200 -Subject: [PATCH 07/18] pcm: remove extra NULL checks in snd_pcm_dmix_open() - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dmix.c | 11 ++++------- - 1 file changed, 4 insertions(+), 7 deletions(-) - -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index 8747450f..608593f1 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -998,7 +998,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, - snd_config_t *root, snd_config_t *sconf, - snd_pcm_stream_t stream, int mode) - { -- snd_pcm_t *pcm = NULL, *spcm = NULL; -+ snd_pcm_t *pcm, *spcm = NULL; - snd_pcm_direct_t *dmix; - int ret, first_instance; - -@@ -1154,12 +1154,9 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, - } else - snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); - _err_nosem: -- if (dmix) { -- free(dmix->bindings); -- free(dmix); -- } -- if (pcm) -- snd_pcm_free(pcm); -+ free(dmix->bindings); -+ free(dmix); -+ snd_pcm_free(pcm); - return ret; - } - --- -2.30.2 - - -From 01a45aec6fcd5a5378a5b5e0ae0f9dacde2068e4 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:39:32 +0200 -Subject: [PATCH 08/18] pcm: remove extra NULL checks in snd_pcm_dsnoop_open() - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dsnoop.c | 13 +++++-------- - 1 file changed, 5 insertions(+), 8 deletions(-) - -diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c -index fb1b02c2..2c3b9f43 100644 ---- a/src/pcm/pcm_dsnoop.c -+++ b/src/pcm/pcm_dsnoop.c -@@ -564,8 +564,8 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, - snd_config_t *root, snd_config_t *sconf, - snd_pcm_stream_t stream, int mode) - { -- snd_pcm_t *pcm = NULL, *spcm = NULL; -- snd_pcm_direct_t *dsnoop = NULL; -+ snd_pcm_t *pcm, *spcm = NULL; -+ snd_pcm_direct_t *dsnoop; - int ret, first_instance; - - assert(pcmp); -@@ -708,12 +708,9 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, - snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT); - - _err_nosem: -- if (dsnoop) { -- free(dsnoop->bindings); -- free(dsnoop); -- } -- if (pcm) -- snd_pcm_free(pcm); -+ free(dsnoop->bindings); -+ free(dsnoop); -+ snd_pcm_free(pcm); - return ret; - } - --- -2.30.2 - - -From 74c6382df6cf18b801659d8c5c53407a7ea1f02b Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:46:46 +0200 -Subject: [PATCH 09/18] pcm: remove extra NULL checks in snd_pcm_dshare_open() - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dshare.c | 13 +++++-------- - 1 file changed, 5 insertions(+), 8 deletions(-) - -diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c -index 0f5238a6..a918512b 100644 ---- a/src/pcm/pcm_dshare.c -+++ b/src/pcm/pcm_dshare.c -@@ -690,8 +690,8 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, - snd_config_t *root, snd_config_t *sconf, - snd_pcm_stream_t stream, int mode) - { -- snd_pcm_t *pcm = NULL, *spcm = NULL; -- snd_pcm_direct_t *dshare = NULL; -+ snd_pcm_t *pcm, *spcm = NULL; -+ snd_pcm_direct_t *dshare; - int ret, first_instance; - unsigned int chn; - -@@ -851,12 +851,9 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, - } else - snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT); - _err_nosem: -- if (dshare) { -- free(dshare->bindings); -- free(dshare); -- } -- if (pcm) -- snd_pcm_free(pcm); -+ free(dshare->bindings); -+ free(dshare); -+ snd_pcm_free(pcm); - return ret; - } - --- -2.30.2 - - -From eabadf545c51d4c88c5f359db73726ec3ac653ba Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:49:29 +0200 -Subject: [PATCH 10/18] pcm: softvol - fix early exit in add_tlv_info() - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_softvol.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c -index e2bdd31a..eea322ca 100644 ---- a/src/pcm/pcm_softvol.c -+++ b/src/pcm/pcm_softvol.c -@@ -711,13 +711,13 @@ static int add_tlv_info(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo, - unsigned int *old_tlv, size_t old_tlv_size) - { - unsigned int tlv[4]; -- if (sizeof(tlv) <= old_tlv_size && memcmp(tlv, old_tlv, sizeof(tlv)) == 0) -- return 0; - tlv[SNDRV_CTL_TLVO_TYPE] = SND_CTL_TLVT_DB_SCALE; - tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(int); - tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = (int)(svol->min_dB * 100); - tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = - (int)((svol->max_dB - svol->min_dB) * 100 / svol->max_val); -+ if (sizeof(tlv) <= old_tlv_size && memcmp(tlv, old_tlv, sizeof(tlv)) == 0) -+ return 0; - return snd_ctl_elem_tlv_write(svol->ctl, &cinfo->id, tlv); - } - --- -2.30.2 - - -From cf3846d46053b23006e6a9042b586fc78e81af55 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:50:17 +0200 -Subject: [PATCH 11/18] timer: remove dead code in _snd_timer_hw_open() - ---- - src/timer/timer_hw.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/src/timer/timer_hw.c b/src/timer/timer_hw.c -index cfb77463..fe4e40bb 100644 ---- a/src/timer/timer_hw.c -+++ b/src/timer/timer_hw.c -@@ -330,8 +330,6 @@ int _snd_timer_hw_open(snd_timer_t **timer, char *name, - SNDERR("Unexpected field %s", id); - return -EINVAL; - } -- if (card < 0) -- return -EINVAL; - return snd_timer_hw_open(timer, name, dev_class, dev_sclass, card, device, subdevice, mode); - } - SND_DLSYM_BUILD_VERSION(_snd_timer_hw_open, SND_TIMER_DLSYM_VERSION); --- -2.30.2 - - -From 200d18cda7a700607c21ad5dc9faaea2a1e27dbd Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:51:13 +0200 -Subject: [PATCH 12/18] ucm: fix error path in execute_cfgsave() - -Signed-off-by: Jaroslav Kysela ---- - src/ucm/main.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/ucm/main.c b/src/ucm/main.c -index c9b37b68..42fdaa1d 100644 ---- a/src/ucm/main.c -+++ b/src/ucm/main.c -@@ -605,8 +605,10 @@ static int execute_cfgsave(snd_use_case_mgr_t *uc_mgr, const char *filename) - uc_error("unable to open file '%s': %s", file, snd_strerror(err)); - goto _err; - } -- if (!config || snd_config_is_empty(config)) -+ if (!config || snd_config_is_empty(config)) { -+ snd_output_close(out); - goto _err; -+ } - if (with_root) { - snd_output_printf(out, "%s ", root); - err = _snd_config_save_node_value(config, out, 0); --- -2.30.2 - - -From 9b71d53bde21c8bb0d900c17863664e12753d844 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:52:12 +0200 -Subject: [PATCH 13/18] ucm: fix use after free in if_eval_regex_match() - -Signed-off-by: Jaroslav Kysela ---- - src/ucm/ucm_cond.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/ucm/ucm_cond.c b/src/ucm/ucm_cond.c -index 59d1a155..adb0ecd9 100644 ---- a/src/ucm/ucm_cond.c -+++ b/src/ucm/ucm_cond.c -@@ -160,11 +160,12 @@ static int if_eval_regex_match(snd_use_case_mgr_t *uc_mgr, snd_config_t *eval) - if (err < 0) - return err; - err = regcomp(&re, s, options); -- free(s); - if (err) { - uc_error("Regex '%s' compilation failed (code %d)", s, err); -+ free(s); - return -EINVAL; - } -+ free(s); - - err = uc_mgr_get_substituted_value(uc_mgr, &s, string); - if (err < 0) { --- -2.30.2 - - -From 7764e3e621a4c8a52327833d44e32c8b6fe3a131 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:53:24 +0200 -Subject: [PATCH 14/18] ucm: fix if_eval_path() - access NULL pointer - -Signed-off-by: Jaroslav Kysela ---- - src/ucm/ucm_cond.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ucm/ucm_cond.c b/src/ucm/ucm_cond.c -index adb0ecd9..0ed0b690 100644 ---- a/src/ucm/ucm_cond.c -+++ b/src/ucm/ucm_cond.c -@@ -272,7 +272,7 @@ static int if_eval_control_exists(snd_use_case_mgr_t *uc_mgr, snd_config_t *eval - - static int if_eval_path(snd_use_case_mgr_t *uc_mgr, snd_config_t *eval) - { -- const char *path, *mode = NULL; -+ const char *path, *mode = ""; - int err, amode = F_OK; - - if (uc_mgr->conf_format < 4) { --- -2.30.2 - - -From 7fcb1aadd56e94f03e51c4747e72d77279151c22 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:56:01 +0200 -Subject: [PATCH 15/18] ucm: find_exec() - fix memory leak (dir) - -Signed-off-by: Jaroslav Kysela ---- - src/ucm/ucm_exec.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/ucm/ucm_exec.c b/src/ucm/ucm_exec.c -index a22df8fe..1cdb2633 100644 ---- a/src/ucm/ucm_exec.c -+++ b/src/ucm/ucm_exec.c -@@ -73,6 +73,7 @@ static int find_exec(const char *name, char *out, size_t len) - || !(st.st_mode & S_IEXEC)) - continue; - snd_strlcpy(out, bin, len); -+ closedir(dir); - return 1; - } - closedir(dir); --- -2.30.2 - - -From 26ab7fc3e4cba416cf51aa0fb48fdddaa0d861ee Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:58:04 +0200 -Subject: [PATCH 16/18] ucm: fix possible NULL pointer dereference in - uc_mgr_exec() - -Signed-off-by: Jaroslav Kysela ---- - src/ucm/ucm_exec.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/src/ucm/ucm_exec.c b/src/ucm/ucm_exec.c -index 1cdb2633..d83206d0 100644 ---- a/src/ucm/ucm_exec.c -+++ b/src/ucm/ucm_exec.c -@@ -185,7 +185,11 @@ int uc_mgr_exec(const char *prog) - return -EINVAL; - - prog = argv[0]; -- if (argv[0][0] != '/' && argv[0][0] != '.') { -+ if (prog == NULL) { -+ err = -EINVAL; -+ goto __error; -+ } -+ if (prog[0] != '/' && prog[0] != '.') { - if (!find_exec(argv[0], bin, sizeof(bin))) { - err = -ENOEXEC; - goto __error; --- -2.30.2 - - -From 64a6d4d1e827732bef7c68e1e6d2cb6863b4597c Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 19:59:10 +0200 -Subject: [PATCH 17/18] ucm: check error value in parse_lookup_query() - -Signed-off-by: Jaroslav Kysela ---- - src/ucm/ucm_subs.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c -index c56730c5..0bc4e63f 100644 ---- a/src/ucm/ucm_subs.c -+++ b/src/ucm/ucm_subs.c -@@ -224,7 +224,11 @@ static snd_config_t *parse_lookup_query(const char *query) - uc_error("unable to create memory input buffer"); - return NULL; - } -- snd_config_top(&config); -+ err = snd_config_top(&config); -+ if (err < 0) { -+ snd_input_close(input); -+ return NULL; -+ } - err = snd_config_load(config, input); - snd_input_close(input); - if (err < 0) { --- -2.30.2 - - -From 30d1d256e792fbabf14c57efb98c489541b19f37 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Wed, 2 Jun 2021 20:01:08 +0200 -Subject: [PATCH 18/18] ucm: fix out-of-array access in - rval_device_lookup_init() - -Signed-off-by: Jaroslav Kysela ---- - src/ucm/ucm_subs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c -index 0bc4e63f..20905c3f 100644 ---- a/src/ucm/ucm_subs.c -+++ b/src/ucm/ucm_subs.c -@@ -489,7 +489,7 @@ static int rval_device_lookup_init(snd_use_case_mgr_t *uc_mgr, - uc_error("Missing device type!"); - return -EINVAL; - } -- for (t = types; t; t++) -+ for (t = types; t->name; t++) - if (strcasecmp(t->name, s) == 0) - return t->init(iter, config); - uc_error("Device type '%s' is invalid", s); --- -2.30.2 - diff --git a/alsa-lib.spec b/alsa-lib.spec index f25538e..d923688 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -2,14 +2,14 @@ #define prever_dot .rc3 #define postver a -%define version_alsa_lib 1.2.5 -%define version_alsa_ucm 1.2.5 +%define version_alsa_lib 1.2.5.1 +%define version_alsa_ucm 1.2.5.1 %define version_alsa_tplg 1.2.5 Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 2%{?prever_dot}%{?dist} +Release: 1%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,6 +167,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Mon Jun 14 2021 Jaroslav Kysela - 1.2.5.1-1 +- update to 1.2.5.1 + * Wed Jun 2 2021 Jaroslav Kysela - 1.2.5-2 - add upstream fixes (conf + ucm) diff --git a/alsa-ucm-conf.patch b/alsa-ucm-conf.patch index dedf95f..e69de29 100644 --- a/alsa-ucm-conf.patch +++ b/alsa-ucm-conf.patch @@ -1,14 +0,0 @@ -diff --git a/ucm2/HDA-Intel/HDA-Intel.conf b/ucm2/HDA-Intel/HDA-Intel.conf -index 5794e72..8a8e0e7 100644 ---- a/ucm2/HDA-Intel/HDA-Intel.conf -+++ b/ucm2/HDA-Intel/HDA-Intel.conf -@@ -1,4 +1,4 @@ --Syntax 3 -+Syntax 4 - - Define.Use "" # a non-empty string to use UCM configuration for HDA devices - --- -2.30.2 - - diff --git a/sources b/sources index b10f9d4..ddf88ed 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (alsa-lib-1.2.5.tar.bz2) = d9b53484737a3684aac7e08b4b18400aac10fec1a78a8bf9101944bea2c50710bc7355e9bb0012541b067e2d5ee7b1b818bf1bdbffbb2b2d7ad0eb15efe49725 +SHA512 (alsa-lib-1.2.5.1.tar.bz2) = 01998ffa449e925ff552c13aea47f9540903afdc533086067c78dcaba4d239c347180d3d28bb0000e6d19b7779c7249fcc77a30057930ca22d18ba55e163fa1c SHA512 (alsa-topology-conf-1.2.5.tar.bz2) = 2eb4d8baf2dcbf0b631dd11dbf15bffc51694d9cc6931619e51787f3ba58d1a091d266e6721a3b737c040ec74a28270b93f39fb97f30a3227cf340dd646e5d51 -SHA512 (alsa-ucm-conf-1.2.5.tar.bz2) = f16e8f04018c65de5e24f2a3eb0b3edff26cbce78cc1820c42c46907c903913c571797b59e803ae36b8ec3136487d0a5aacd034e2a8df3e15ed998b7a70152b7 +SHA512 (alsa-ucm-conf-1.2.5.1.tar.bz2) = 774d6da1a0ee6fb1fcd764c1d4b3eb5812a35508cf27db71f6c82784f125eca207992da9081d25783fecb31e548d8b34124d4b3b3d506e33215b76ea48f71012 From 2e98a65eac75dedaf59369b196ce48eb2a2b6f4d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 31 Aug 2021 12:00:40 +0200 Subject: [PATCH 04/10] ucm fixes for 1.2.5.1 --- alsa-git.patch | 1916 ++++++++++++++++++++++++++++++++++++++++++++++++ alsa-lib.spec | 5 +- 2 files changed, 1920 insertions(+), 1 deletion(-) diff --git a/alsa-git.patch b/alsa-git.patch index e69de29..f88de1b 100644 --- a/alsa-git.patch +++ b/alsa-git.patch @@ -0,0 +1,1916 @@ +From 81e7923fbfad45b2f353a4d6e3053af51f5f7d0b Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 15 Jun 2021 23:21:42 +0200 +Subject: [PATCH 01/20] control: empty - fix the static build + +Reported-by: Jan Palus +Fixes: https://github.com/alsa-project/alsa-lib/issues/157 +Signed-off-by: Jaroslav Kysela +--- + src/control/control_empty.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/control/control_empty.c b/src/control/control_empty.c +index 49d1026c..c9b048c1 100644 +--- a/src/control/control_empty.c ++++ b/src/control/control_empty.c +@@ -30,7 +30,7 @@ + + #ifndef PIC + /* entry for static linking */ +-const char *_snd_module_ctl_empty = ""; ++const char *_snd_module_control_empty = ""; + #endif + + /*! \page control_plugins +-- +2.31.1 + + +From 5089358aa99d698bd846b05c1890a09613d740b3 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 17 Jun 2021 10:20:25 +0200 +Subject: [PATCH 02/20] pcm: rate: Refactoring temporary buffer allocations + +Introduce common helpers to allocate and release the temporary buffers +and the associated snd_pcm_channel. Now two allocated objects are +used instead of one malloc to be split. + +Also, change the snd_pcm_channel set up to be in interleaved mode. +This will be necessary in the following change in the rate plugin. + +Signed-off-by: Takashi Iwai +--- + src/pcm/pcm_rate.c | 80 ++++++++++++++++++++++++++++------------------ + 1 file changed, 49 insertions(+), 31 deletions(-) + +diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c +index 770aafea..1e996134 100644 +--- a/src/pcm/pcm_rate.c ++++ b/src/pcm/pcm_rate.c +@@ -76,6 +76,45 @@ struct _snd_pcm_rate { + + #endif /* DOC_HIDDEN */ + ++/* allocate a channel area and a temporary buffer for the given size */ ++static snd_pcm_channel_area_t * ++rate_alloc_tmp_buf(snd_pcm_rate_t *rate, snd_pcm_format_t format, ++ unsigned int channels, unsigned int frames) ++{ ++ snd_pcm_channel_area_t *ap; ++ int width = snd_pcm_format_physical_width(format); ++ int i; ++ ++ ap = malloc(sizeof(*ap) * channels); ++ if (!ap) ++ return NULL; ++ ap->addr = malloc(frames * channels * width / 8); ++ if (!ap->addr) { ++ free(ap); ++ return NULL; ++ } ++ ++ /* set up in interleaved format */ ++ for (i = 0; i < channels; i++) { ++ ap[i].addr = ap[0].addr + (i * width) / 8; ++ ap[i].first = 0; ++ ap[i].step = width * channels; ++ } ++ ++ return ap; ++} ++ ++static void rate_free_tmp_buf(snd_pcm_channel_area_t **ptr) ++{ ++ snd_pcm_channel_area_t *c = *ptr; ++ ++ if (c) { ++ free(c->addr); ++ free(c); ++ *ptr = NULL; ++ } ++} ++ + static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params) + { + snd_pcm_rate_t *rate = pcm->private_data; +@@ -286,28 +325,13 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + if (err < 0) + return err; + +- rate->pareas = malloc(2 * channels * sizeof(*rate->pareas)); +- if (rate->pareas == NULL) ++ rate->pareas = rate_alloc_tmp_buf(rate, cinfo->format, channels, ++ cinfo->period_size); ++ rate->sareas = rate_alloc_tmp_buf(rate, sinfo->format, channels, ++ sinfo->period_size); ++ if (!rate->pareas || !rate->sareas) + goto error; + +- cwidth = snd_pcm_format_physical_width(cinfo->format); +- swidth = snd_pcm_format_physical_width(sinfo->format); +- rate->pareas[0].addr = malloc(((cwidth * channels * cinfo->period_size) / 8) + +- ((swidth * channels * sinfo->period_size) / 8)); +- if (rate->pareas[0].addr == NULL) +- goto error; +- +- rate->sareas = rate->pareas + channels; +- rate->sareas[0].addr = (char *)rate->pareas[0].addr + ((cwidth * channels * cinfo->period_size) / 8); +- for (chn = 0; chn < channels; chn++) { +- rate->pareas[chn].addr = (char *)rate->pareas[0].addr + (cwidth * chn * cinfo->period_size) / 8; +- rate->pareas[chn].first = 0; +- rate->pareas[chn].step = cwidth; +- rate->sareas[chn].addr = (char *)rate->sareas[0].addr + (swidth * chn * sinfo->period_size) / 8; +- rate->sareas[chn].first = 0; +- rate->sareas[chn].step = swidth; +- } +- + if (rate->ops.convert_s16) { + rate->get_idx = snd_pcm_linear_get_index(rate->info.in.format, SND_PCM_FORMAT_S16); + rate->put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, rate->info.out.format); +@@ -322,11 +346,8 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + return 0; + + error: +- if (rate->pareas) { +- free(rate->pareas[0].addr); +- free(rate->pareas); +- rate->pareas = NULL; +- } ++ rate_free_tmp_buf(&rate->pareas); ++ rate_free_tmp_buf(&rate->sareas); + if (rate->ops.free) + rate->ops.free(rate->obj); + return -ENOMEM; +@@ -335,12 +356,9 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + static int snd_pcm_rate_hw_free(snd_pcm_t *pcm) + { + snd_pcm_rate_t *rate = pcm->private_data; +- if (rate->pareas) { +- free(rate->pareas[0].addr); +- free(rate->pareas); +- rate->pareas = NULL; +- rate->sareas = NULL; +- } ++ ++ rate_free_tmp_buf(&rate->pareas); ++ rate_free_tmp_buf(&rate->sareas); + if (rate->ops.free) + rate->ops.free(rate->obj); + free(rate->src_buf); +-- +2.31.1 + + +From 119d9c1678b1193f8b969a6483cae1f7bf95e609 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 17 Jun 2021 10:03:17 +0200 +Subject: [PATCH 03/20] pcm: rate: Improve the support multiple formats + +This patch extends the PCM rate plugin for allowing its converter +plugin to deal with multiple formats. Currently, the converter plugin +is allowed to take different formats only when convert callback is +defined. And for this way (so far only the standard linear rate +plugin does), all linear formats have to be handled, and it's +cumbersome. + +OTOH, most other rate plugins are implemented with convert_s16 +callback, which accepts only S16 format. This is often not ideal +because many converter engines can handle 32bit formats. Also, the +target format is often 32bit format, hence this would require +additional conversion even if the converter engine can output 32bit +natively. + +In this patch, for addressing the problems above, the rate plugin API +is extended in the following way: + +- The new get_supported_formats callback is added; this stores the bit + masks of the supported input and output formats, as well as the + behavior flags. Currently only linear formats are allowed. +- When the plugin accepts only the interleaved stream, set + SND_PCM_RATE_FLAG_INTERLEAVED flag bit. Otherwise the code has to + handle snd_pcm_channel_area at each call. +- When both input and output formats have to be identical, pass + SND_PCM_RATE_FLAG_SYNC_FORMATS flag bit. +- When the converter wants to process different formats, use convert + callback instead of convert_s16. You can put both in the ops for + compatibility, too. + The input and output formats are found in the info argument of init + callback. +- Now the PCM rate plugin core will skip the temporary buffer + allocation and conversions for pre- and post-process if not needed + (i.e. matching with the requested input or output format). + +The rate plugin API version is bumped to 0x010003. + +Signed-off-by: Takashi Iwai +--- + include/pcm_rate.h | 36 ++++- + src/pcm/pcm_rate.c | 358 +++++++++++++++++++++++++++------------------ + 2 files changed, 251 insertions(+), 143 deletions(-) + +diff --git a/include/pcm_rate.h b/include/pcm_rate.h +index 4171fb9d..48473ed4 100644 +--- a/include/pcm_rate.h ++++ b/include/pcm_rate.h +@@ -38,7 +38,7 @@ extern "C" { + /** + * Protocol version + */ +-#define SND_PCM_RATE_PLUGIN_VERSION 0x010002 ++#define SND_PCM_RATE_PLUGIN_VERSION 0x010003 + + /** hw_params information for a single side */ + typedef struct snd_pcm_rate_side_info { +@@ -55,6 +55,11 @@ typedef struct snd_pcm_rate_info { + unsigned int channels; + } snd_pcm_rate_info_t; + ++enum { ++ SND_PCM_RATE_FLAG_INTERLEAVED = (1U << 0), /** only interleaved format */ ++ SND_PCM_RATE_FLAG_SYNC_FORMATS = (1U << 1), /** both input and output formats have to be identical */ ++}; ++ + /** Callback table of rate-converter */ + typedef struct snd_pcm_rate_ops { + /** +@@ -114,6 +119,13 @@ typedef struct snd_pcm_rate_ops { + * new ops since version 0x010002 + */ + void (*dump)(void *obj, snd_output_t *out); ++ /** ++ * get the supported input and output formats (optional); ++ * new ops since version 0x010003 ++ */ ++ int (*get_supported_formats)(void *obj, uint64_t *in_formats, ++ uint64_t *out_formats, ++ unsigned int *flags); + } snd_pcm_rate_ops_t; + + /** open function type */ +@@ -147,6 +159,28 @@ typedef struct snd_pcm_rate_old_ops { + snd_pcm_uframes_t (*input_frames)(void *obj, snd_pcm_uframes_t frames); + snd_pcm_uframes_t (*output_frames)(void *obj, snd_pcm_uframes_t frames); + } snd_pcm_rate_old_ops_t; ++ ++/* old rate_ops for protocol version 0x010002 */ ++typedef struct snd_pcm_rate_v2_ops { ++ void (*close)(void *obj); ++ int (*init)(void *obj, snd_pcm_rate_info_t *info); ++ void (*free)(void *obj); ++ void (*reset)(void *obj); ++ int (*adjust_pitch)(void *obj, snd_pcm_rate_info_t *info); ++ void (*convert)(void *obj, ++ const snd_pcm_channel_area_t *dst_areas, ++ snd_pcm_uframes_t dst_offset, unsigned int dst_frames, ++ const snd_pcm_channel_area_t *src_areas, ++ snd_pcm_uframes_t src_offset, unsigned int src_frames); ++ void (*convert_s16)(void *obj, int16_t *dst, unsigned int dst_frames, ++ const int16_t *src, unsigned int src_frames); ++ snd_pcm_uframes_t (*input_frames)(void *obj, snd_pcm_uframes_t frames); ++ snd_pcm_uframes_t (*output_frames)(void *obj, snd_pcm_uframes_t frames); ++ unsigned int version; ++ int (*get_supported_rates)(void *obj, unsigned int *rate_min, ++ unsigned int *rate_max); ++ void (*dump)(void *obj, snd_output_t *out); ++} snd_pcm_rate_v2_ops_t; + #endif + + #ifdef __cplusplus +diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c +index 1e996134..13111d29 100644 +--- a/src/pcm/pcm_rate.c ++++ b/src/pcm/pcm_rate.c +@@ -62,18 +62,22 @@ struct _snd_pcm_rate { + void *open_func; + void *obj; + snd_pcm_rate_ops_t ops; +- unsigned int get_idx; +- unsigned int put_idx; +- int16_t *src_buf; +- int16_t *dst_buf; ++ unsigned int src_conv_idx; ++ unsigned int dst_conv_idx; ++ snd_pcm_channel_area_t *src_buf; ++ snd_pcm_channel_area_t *dst_buf; + int start_pending; /* start is triggered but not commited to slave */ + snd_htimestamp_t trigger_tstamp; + unsigned int plugin_version; + unsigned int rate_min, rate_max; ++ snd_pcm_format_t orig_in_format; ++ snd_pcm_format_t orig_out_format; ++ uint64_t in_formats; ++ uint64_t out_formats; ++ unsigned int format_flags; + }; + + #define SND_PCM_RATE_PLUGIN_VERSION_OLD 0x010001 /* old rate plugin */ +- + #endif /* DOC_HIDDEN */ + + /* allocate a channel area and a temporary buffer for the given size */ +@@ -274,12 +278,84 @@ static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm, + snd_pcm_generic_hw_refine); + } + ++/* evaluate the best matching available format to the given format */ ++static int get_best_format(uint64_t mask, snd_pcm_format_t orig) ++{ ++ int pwidth = snd_pcm_format_physical_width(orig); ++ int width = snd_pcm_format_width(orig); ++ int signd = snd_pcm_format_signed(orig); ++ int best_score = -1; ++ int match = -1; ++ int f, score; ++ ++ for (f = 0; f <= SND_PCM_FORMAT_LAST; f++) { ++ if (!(mask & (1ULL << f))) ++ continue; ++ score = 0; ++ if (snd_pcm_format_linear(f)) { ++ if (snd_pcm_format_physical_width(f) == pwidth) ++ score++; ++ if (snd_pcm_format_physical_width(f) >= pwidth) ++ score++; ++ if (snd_pcm_format_width(f) == width) ++ score++; ++ if (snd_pcm_format_signed(f) == signd) ++ score++; ++ } ++ if (score > best_score) { ++ match = f; ++ best_score = score; ++ } ++ } ++ ++ return match; ++} ++ ++/* set up the input and output formats from the available lists */ ++static int choose_preferred_format(snd_pcm_rate_t *rate) ++{ ++ uint64_t in_mask = rate->in_formats; ++ uint64_t out_mask = rate->out_formats; ++ int in, out; ++ ++ if (!in_mask || !out_mask) ++ return 0; ++ ++ if (rate->orig_in_format == rate->orig_out_format) ++ if (in_mask & out_mask & (1ULL << rate->orig_in_format)) ++ return 0; /* nothing changed */ ++ ++ repeat: ++ in = get_best_format(in_mask, rate->orig_in_format); ++ out = get_best_format(out_mask, rate->orig_out_format); ++ if (in < 0 || out < 0) ++ return -ENOENT; ++ ++ if ((rate->format_flags & SND_PCM_RATE_FLAG_SYNC_FORMATS) && ++ in != out) { ++ if (out_mask & (1ULL << in)) ++ out = in; ++ else if (in_mask & (1ULL << out)) ++ in = out; ++ else { ++ in_mask &= ~(1ULL << in); ++ out_mask &= ~(1ULL << out); ++ goto repeat; ++ } ++ } ++ ++ rate->info.in.format = in; ++ rate->info.out.format = out; ++ return 0; ++} ++ + static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + { + snd_pcm_rate_t *rate = pcm->private_data; + snd_pcm_t *slave = rate->gen.slave; + snd_pcm_rate_side_info_t *sinfo, *cinfo; +- unsigned int channels, cwidth, swidth, chn; ++ unsigned int channels, cwidth, swidth, chn, acc; ++ int need_src_buf, need_dst_buf; + int err = snd_pcm_hw_params_slave(pcm, params, + snd_pcm_rate_hw_refine_cchange, + snd_pcm_rate_hw_refine_sprepare, +@@ -308,6 +384,9 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + if (err < 0) + return err; + err = INTERNAL(snd_pcm_hw_params_get_channels)(params, &channels); ++ if (err < 0) ++ return err; ++ err = INTERNAL(snd_pcm_hw_params_get_access)(params, &acc); + if (err < 0) + return err; + +@@ -321,36 +400,80 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + SNDMSG("rate plugin already in use"); + return -EBUSY; + } +- err = rate->ops.init(rate->obj, &rate->info); +- if (err < 0) +- return err; + + rate->pareas = rate_alloc_tmp_buf(rate, cinfo->format, channels, + cinfo->period_size); + rate->sareas = rate_alloc_tmp_buf(rate, sinfo->format, channels, + sinfo->period_size); +- if (!rate->pareas || !rate->sareas) +- goto error; +- +- if (rate->ops.convert_s16) { +- rate->get_idx = snd_pcm_linear_get_index(rate->info.in.format, SND_PCM_FORMAT_S16); +- rate->put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, rate->info.out.format); +- free(rate->src_buf); +- rate->src_buf = malloc(channels * rate->info.in.period_size * 2); +- free(rate->dst_buf); +- rate->dst_buf = malloc(channels * rate->info.out.period_size * 2); +- if (! rate->src_buf || ! rate->dst_buf) ++ if (!rate->pareas || !rate->sareas) { ++ err = -ENOMEM; ++ goto error_pareas; ++ } ++ ++ rate->orig_in_format = rate->info.in.format; ++ rate->orig_out_format = rate->info.out.format; ++ if (choose_preferred_format(rate) < 0) { ++ SNDERR("No matching format in rate plugin"); ++ err = -EINVAL; ++ goto error_pareas; ++ } ++ ++ err = rate->ops.init(rate->obj, &rate->info); ++ if (err < 0) ++ goto error_init; ++ ++ rate_free_tmp_buf(&rate->src_buf); ++ rate_free_tmp_buf(&rate->dst_buf); ++ ++ need_src_buf = need_dst_buf = 0; ++ ++ if ((rate->format_flags & SND_PCM_RATE_FLAG_INTERLEAVED) && ++ !(acc == SND_PCM_ACCESS_MMAP_INTERLEAVED || ++ acc == SND_PCM_ACCESS_RW_INTERLEAVED)) { ++ need_src_buf = need_dst_buf = 1; ++ } else { ++ if (rate->orig_in_format != rate->info.in.format) ++ need_src_buf = 1; ++ if (rate->orig_out_format != rate->info.out.format) ++ need_dst_buf = 1; ++ } ++ ++ if (need_src_buf) { ++ rate->src_conv_idx = ++ snd_pcm_linear_convert_index(rate->orig_in_format, ++ rate->info.in.format); ++ rate->src_buf = rate_alloc_tmp_buf(rate, rate->info.in.format, ++ channels, rate->info.in.period_size); ++ if (!rate->src_buf) { ++ err = -ENOMEM; + goto error; ++ } ++ } ++ ++ if (need_dst_buf) { ++ rate->dst_conv_idx = ++ snd_pcm_linear_convert_index(rate->info.out.format, ++ rate->orig_out_format); ++ rate->dst_buf = rate_alloc_tmp_buf(rate, rate->info.out.format, ++ channels, rate->info.out.period_size); ++ if (!rate->dst_buf) { ++ err = -ENOMEM; ++ goto error; ++ } + } + + return 0; + + error: +- rate_free_tmp_buf(&rate->pareas); +- rate_free_tmp_buf(&rate->sareas); ++ rate_free_tmp_buf(&rate->src_buf); ++ rate_free_tmp_buf(&rate->dst_buf); ++ error_init: + if (rate->ops.free) + rate->ops.free(rate->obj); +- return -ENOMEM; ++ error_pareas: ++ rate_free_tmp_buf(&rate->pareas); ++ rate_free_tmp_buf(&rate->sareas); ++ return err; + } + + static int snd_pcm_rate_hw_free(snd_pcm_t *pcm) +@@ -361,9 +484,8 @@ static int snd_pcm_rate_hw_free(snd_pcm_t *pcm) + rate_free_tmp_buf(&rate->sareas); + if (rate->ops.free) + rate->ops.free(rate->obj); +- free(rate->src_buf); +- free(rate->dst_buf); +- rate->src_buf = rate->dst_buf = NULL; ++ rate_free_tmp_buf(&rate->src_buf); ++ rate_free_tmp_buf(&rate->dst_buf); + return snd_pcm_hw_free(rate->gen.slave); + } + +@@ -444,82 +566,6 @@ static int snd_pcm_rate_init(snd_pcm_t *pcm) + return 0; + } + +-static void convert_to_s16(snd_pcm_rate_t *rate, int16_t *buf, +- const snd_pcm_channel_area_t *areas, +- snd_pcm_uframes_t offset, unsigned int frames, +- unsigned int channels) +-{ +-#ifndef DOC_HIDDEN +-#define GET16_LABELS +-#include "plugin_ops.h" +-#undef GET16_LABELS +-#endif /* DOC_HIDDEN */ +- void *get = get16_labels[rate->get_idx]; +- const char *src; +- int16_t sample; +- const char *srcs[channels]; +- int src_step[channels]; +- unsigned int c; +- +- for (c = 0; c < channels; c++) { +- srcs[c] = snd_pcm_channel_area_addr(areas + c, offset); +- src_step[c] = snd_pcm_channel_area_step(areas + c); +- } +- +- while (frames--) { +- for (c = 0; c < channels; c++) { +- src = srcs[c]; +- goto *get; +-#ifndef DOC_HIDDEN +-#define GET16_END after_get +-#include "plugin_ops.h" +-#undef GET16_END +-#endif /* DOC_HIDDEN */ +- after_get: +- *buf++ = sample; +- srcs[c] += src_step[c]; +- } +- } +-} +- +-static void convert_from_s16(snd_pcm_rate_t *rate, const int16_t *buf, +- const snd_pcm_channel_area_t *areas, +- snd_pcm_uframes_t offset, unsigned int frames, +- unsigned int channels) +-{ +-#ifndef DOC_HIDDEN +-#define PUT16_LABELS +-#include "plugin_ops.h" +-#undef PUT16_LABELS +-#endif /* DOC_HIDDEN */ +- void *put = put16_labels[rate->put_idx]; +- char *dst; +- int16_t sample; +- char *dsts[channels]; +- int dst_step[channels]; +- unsigned int c; +- +- for (c = 0; c < channels; c++) { +- dsts[c] = snd_pcm_channel_area_addr(areas + c, offset); +- dst_step[c] = snd_pcm_channel_area_step(areas + c); +- } +- +- while (frames--) { +- for (c = 0; c < channels; c++) { +- dst = dsts[c]; +- sample = *buf++; +- goto *put; +-#ifndef DOC_HIDDEN +-#define PUT16_END after_put +-#include "plugin_ops.h" +-#undef PUT16_END +-#endif /* DOC_HIDDEN */ +- after_put: +- dsts[c] += dst_step[c]; +- } +- } +-} +- + static void do_convert(const snd_pcm_channel_area_t *dst_areas, + snd_pcm_uframes_t dst_offset, unsigned int dst_frames, + const snd_pcm_channel_area_t *src_areas, +@@ -527,28 +573,40 @@ static void do_convert(const snd_pcm_channel_area_t *dst_areas, + unsigned int channels, + snd_pcm_rate_t *rate) + { +- if (rate->ops.convert_s16) { +- const int16_t *src; +- int16_t *dst; +- if (! rate->src_buf) +- src = (int16_t *)src_areas->addr + src_offset * channels; +- else { +- convert_to_s16(rate, rate->src_buf, src_areas, src_offset, +- src_frames, channels); +- src = rate->src_buf; +- } +- if (! rate->dst_buf) +- dst = (int16_t *)dst_areas->addr + dst_offset * channels; +- else +- dst = rate->dst_buf; +- rate->ops.convert_s16(rate->obj, dst, dst_frames, src, src_frames); +- if (dst == rate->dst_buf) +- convert_from_s16(rate, rate->dst_buf, dst_areas, dst_offset, +- dst_frames, channels); ++ const snd_pcm_channel_area_t *out_areas; ++ snd_pcm_uframes_t out_offset; ++ ++ if (rate->dst_buf) { ++ out_areas = rate->dst_buf; ++ out_offset = 0; + } else { +- rate->ops.convert(rate->obj, dst_areas, dst_offset, dst_frames, +- src_areas, src_offset, src_frames); ++ out_areas = dst_areas; ++ out_offset = dst_offset; ++ } ++ ++ if (rate->src_buf) { ++ snd_pcm_linear_convert(rate->src_buf, 0, ++ src_areas, src_offset, ++ channels, src_frames, ++ rate->src_conv_idx); ++ src_areas = rate->src_buf; ++ src_offset = 0; + } ++ ++ if (rate->ops.convert) ++ rate->ops.convert(rate->obj, out_areas, out_offset, dst_frames, ++ src_areas, src_offset, src_frames); ++ else ++ rate->ops.convert_s16(rate->obj, ++ snd_pcm_channel_area_addr(out_areas, out_offset), ++ dst_frames, ++ snd_pcm_channel_area_addr(src_areas, src_offset), ++ src_frames); ++ if (rate->dst_buf) ++ snd_pcm_linear_convert(dst_areas, dst_offset, ++ rate->dst_buf, 0, ++ channels, dst_frames, ++ rate->dst_conv_idx); + } + + static inline void +@@ -1276,6 +1334,30 @@ const snd_config_t *snd_pcm_rate_get_default_converter(snd_config_t *root) + return NULL; + } + ++static void rate_initial_setup(snd_pcm_rate_t *rate) ++{ ++ if (rate->plugin_version == SND_PCM_RATE_PLUGIN_VERSION) ++ rate->plugin_version = rate->ops.version; ++ ++ if (rate->plugin_version >= 0x010002 && ++ rate->ops.get_supported_rates) ++ rate->ops.get_supported_rates(rate->obj, ++ &rate->rate_min, ++ &rate->rate_max); ++ ++ if (rate->plugin_version >= 0x010003 && ++ rate->ops.get_supported_formats) { ++ rate->ops.get_supported_formats(rate->obj, ++ &rate->in_formats, ++ &rate->out_formats, ++ &rate->format_flags); ++ } else if (!rate->ops.convert && rate->ops.convert_s16) { ++ rate->in_formats = rate->out_formats = ++ 1ULL << SND_PCM_FORMAT_S16; ++ rate->format_flags = SND_PCM_RATE_FLAG_INTERLEAVED; ++ } ++} ++ + #ifdef PIC + static int is_builtin_plugin(const char *type) + { +@@ -1301,20 +1383,11 @@ static int rate_open_func(snd_pcm_rate_t *rate, const char *type, const snd_conf + lib = lib_name; + } + +- rate->rate_min = SND_PCM_PLUGIN_RATE_MIN; +- rate->rate_max = SND_PCM_PLUGIN_RATE_MAX; +- rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION; +- + open_conf_func = snd_dlobj_cache_get(lib, open_conf_name, NULL, verbose && converter_conf != NULL); + if (open_conf_func) { + err = open_conf_func(SND_PCM_RATE_PLUGIN_VERSION, + &rate->obj, &rate->ops, converter_conf); + if (!err) { +- rate->plugin_version = rate->ops.version; +- if (rate->ops.get_supported_rates) +- rate->ops.get_supported_rates(rate->obj, +- &rate->rate_min, +- &rate->rate_max); + rate->open_func = open_conf_func; + return 0; + } else { +@@ -1330,23 +1403,18 @@ static int rate_open_func(snd_pcm_rate_t *rate, const char *type, const snd_conf + rate->open_func = open_func; + + err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops); +- if (!err) { +- rate->plugin_version = rate->ops.version; +- if (rate->ops.get_supported_rates) +- rate->ops.get_supported_rates(rate->obj, +- &rate->rate_min, +- &rate->rate_max); ++ if (!err) + return 0; +- } + + /* try to open with the old protocol version */ + rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION_OLD; + err = open_func(SND_PCM_RATE_PLUGIN_VERSION_OLD, + &rate->obj, &rate->ops); +- if (err) { +- snd_dlobj_cache_put(open_func); +- rate->open_func = NULL; +- } ++ if (!err) ++ return 0; ++ ++ snd_dlobj_cache_put(open_func); ++ rate->open_func = NULL; + return err; + } + #endif +@@ -1417,6 +1485,10 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, + rate->srate = srate; + rate->sformat = sformat; + ++ rate->rate_min = SND_PCM_PLUGIN_RATE_MIN; ++ rate->rate_max = SND_PCM_PLUGIN_RATE_MAX; ++ rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION; ++ + err = snd_pcm_new(&pcm, SND_PCM_TYPE_RATE, name, slave->stream, slave->mode); + if (err < 0) { + free(rate); +@@ -1496,6 +1568,8 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, + return err; + } + ++ rate_initial_setup(rate); ++ + pcm->ops = &snd_pcm_rate_ops; + pcm->fast_ops = &snd_pcm_rate_fast_ops; + pcm->private_data = rate; +-- +2.31.1 + + +From 3f737a2a2c8d20e78dea3ea836997f9d74f602a0 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 18 Jun 2021 11:35:30 +0200 +Subject: [PATCH 04/20] pcm: improve docs for snd_pcm_sw_params_get_avail_min() + and snd_pcm_status_get_avail_max() + +Fixes: https://github.com/alsa-project/alsa-lib/issues/44 +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c +index 09df0f12..892abf98 100644 +--- a/src/pcm/pcm.c ++++ b/src/pcm/pcm.c +@@ -6500,6 +6500,9 @@ int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, + * \param params Software configuration container + * \param val returned minimum available frames to consider PCM ready + * \return 0 otherwise a negative error code ++ * ++ * This is a threshold value when the PCM stream is considered as ready for ++ * another read/write operation or poll event. + */ + #ifndef DOXYGEN + EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_avail_min)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val) +@@ -6960,6 +6963,8 @@ snd_pcm_uframes_t snd_pcm_status_get_avail(const snd_pcm_status_t *obj) + /** + * \brief Get maximum number of frames available from a PCM status container after last #snd_pcm_status call + * \return Maximum number of frames ready to be read/written ++ * ++ * This value returns the peak for the available frames between #snd_pcm_status calls. + */ + snd_pcm_uframes_t snd_pcm_status_get_avail_max(const snd_pcm_status_t *obj) + { +-- +2.31.1 + + +From 212c6c18c4317af48c007a0866efc029b9c3a593 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 21 Jun 2021 09:23:02 +0200 +Subject: [PATCH 05/20] pcm: dmix - use pcm_frame_diff() in + snd_pcm_dmix_sync_ptr0() + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_dmix.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c +index 608593f1..0d0d0bff 100644 +--- a/src/pcm/pcm_dmix.c ++++ b/src/pcm/pcm_dmix.c +@@ -393,17 +393,13 @@ static int snd_pcm_dmix_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr + + old_slave_hw_ptr = dmix->slave_hw_ptr; + dmix->slave_hw_ptr = slave_hw_ptr; +- diff = slave_hw_ptr - old_slave_hw_ptr; ++ diff = pcm_frame_diff(slave_hw_ptr, old_slave_hw_ptr, dmix->slave_boundary); + if (diff == 0) /* fast path */ + return 0; + if (dmix->state != SND_PCM_STATE_RUNNING && + dmix->state != SND_PCM_STATE_DRAINING) + /* not really started yet - don't update hw_ptr */ + return 0; +- if (diff < 0) { +- slave_hw_ptr += dmix->slave_boundary; +- diff = slave_hw_ptr - old_slave_hw_ptr; +- } + dmix->hw_ptr += diff; + dmix->hw_ptr %= pcm->boundary; + if (pcm->stop_threshold >= pcm->boundary) /* don't care */ +-- +2.31.1 + + +From dd609ef9684987d3ca61d5c5cc3c77589ff9c29f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 21 Jun 2021 09:28:41 +0200 +Subject: [PATCH 06/20] pcm: direct plugins - fix hw_ptr in the status callback + +The parent hw_ptr may be in another range (boundary limit). +Set the correct value for the caller. + +BugLink: https://github.com/alsa-project/alsa-lib/issues/155 +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_dmix.c | 1 + + src/pcm/pcm_dshare.c | 1 + + src/pcm/pcm_dsnoop.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c +index 0d0d0bff..94dbb1e0 100644 +--- a/src/pcm/pcm_dmix.c ++++ b/src/pcm/pcm_dmix.c +@@ -491,6 +491,7 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status) + } + + status->state = snd_pcm_dmix_state(pcm); ++ status->hw_ptr = *pcm->hw.ptr; /* boundary may be different */ + status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */ + status->trigger_tstamp = dmix->trigger_tstamp; + status->avail = snd_pcm_mmap_playback_avail(pcm); +diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c +index a918512b..01814dc8 100644 +--- a/src/pcm/pcm_dshare.c ++++ b/src/pcm/pcm_dshare.c +@@ -243,6 +243,7 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status) + break; + } + status->state = snd_pcm_dshare_state(pcm); ++ status->hw_ptr = *pcm->hw.ptr; /* boundary may be different */ + status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */ + status->trigger_tstamp = dshare->trigger_tstamp; + status->avail = snd_pcm_mmap_playback_avail(pcm); +diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c +index 2c3b9f43..3f28df99 100644 +--- a/src/pcm/pcm_dsnoop.c ++++ b/src/pcm/pcm_dsnoop.c +@@ -193,6 +193,7 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status) + snd_pcm_status(dsnoop->spcm, status); + state = snd_pcm_state(dsnoop->spcm); + status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state; ++ status->hw_ptr = *pcm->hw.ptr; /* boundary may be different */ + status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */ + status->trigger_tstamp = dsnoop->trigger_tstamp; + status->avail = snd_pcm_mmap_capture_avail(pcm); +-- +2.31.1 + + +From a5e11f9a810391777ea7750f04ba66f9c9e624de Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 21 Jun 2021 14:21:26 +0200 +Subject: [PATCH 07/20] pcm: Move snd_pcm_channel_area_addr() and _step() to + public header + +Used in the rate plugins commonly. + +Signed-off-by: Takashi Iwai +--- + include/pcm.h | 23 +++++++++++++++++++++++ + src/pcm/pcm_local.h | 13 ------------- + 2 files changed, 23 insertions(+), 13 deletions(-) + +diff --git a/include/pcm.h b/include/pcm.h +index e300b951..b5a514fa 100644 +--- a/include/pcm.h ++++ b/include/pcm.h +@@ -1173,6 +1173,29 @@ int snd_pcm_areas_copy_wrap(const snd_pcm_channel_area_t *dst_channels, + snd_pcm_uframes_t frames, + const snd_pcm_format_t format); + ++/** ++ * \brief get the address of the given PCM channel area ++ * \param area PCM channel area ++ * \param offset Offset in frames ++ * ++ * Returns the pointer corresponding to the given offset on the channel area. ++ */ ++static inline void *snd_pcm_channel_area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset) ++{ ++ return (char *)area->addr + (area->first + area->step * offset) / 8; ++} ++ ++/** ++ * \brief get the step size of the given PCM channel area in bytes ++ * \param area PCM channel area ++ * ++ * Returns the step size in bytes from the given channel area. ++ */ ++static inline unsigned int snd_pcm_channel_area_step(const snd_pcm_channel_area_t *area) ++{ ++ return area->step / 8; ++} ++ + /** \} */ + + /** +diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h +index a63f4be0..6f03365c 100644 +--- a/src/pcm/pcm_local.h ++++ b/src/pcm/pcm_local.h +@@ -632,19 +632,6 @@ static inline snd_pcm_sframes_t snd_pcm_mmap_delay(snd_pcm_t *pcm) + return snd_pcm_mmap_capture_delay(pcm); + } + +-static inline void *snd_pcm_channel_area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset) +-{ +- unsigned int bitofs = area->first + area->step * offset; +- assert(bitofs % 8 == 0); +- return (char *) area->addr + bitofs / 8; +-} +- +-static inline unsigned int snd_pcm_channel_area_step(const snd_pcm_channel_area_t *area) +-{ +- assert(area->step % 8 == 0); +- return area->step / 8; +-} +- + static inline snd_pcm_sframes_t _snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) + { + /* lock handled in the callback */ +-- +2.31.1 + + +From e0e084659083c2ab75d5c894f24227ea2f67010f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 21 Jun 2021 15:14:18 +0200 +Subject: [PATCH 08/20] pcm: direct plugins - fix bad memory access when + channel bindings do not match hw + +Fix and cleanup snd_pcm_direct_check_interleave() function. +Add requested / hardware channel check and use goto when the interleaved + +Fixes: https://github.com/alsa-project/alsa-lib/issues/117 +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_direct.c | 40 +++++++++++++++++----------------------- + 1 file changed, 17 insertions(+), 23 deletions(-) + +diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c +index d50503e3..90417b2f 100644 +--- a/src/pcm/pcm_direct.c ++++ b/src/pcm/pcm_direct.c +@@ -1627,43 +1627,37 @@ int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix) + int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm) + { + unsigned int chn, channels; +- int bits, interleaved = 1; ++ int bits; + const snd_pcm_channel_area_t *dst_areas; + const snd_pcm_channel_area_t *src_areas; + + bits = snd_pcm_format_physical_width(pcm->format); + if ((bits % 8) != 0) +- interleaved = 0; ++ goto __nointerleaved; + channels = dmix->channels; ++ if (channels != dmix->spcm->channels) ++ goto __nointerleaved; + dst_areas = snd_pcm_mmap_areas(dmix->spcm); + src_areas = snd_pcm_mmap_areas(pcm); + for (chn = 1; chn < channels; chn++) { +- if (dst_areas[chn-1].addr != dst_areas[chn].addr) { +- interleaved = 0; +- break; +- } +- if (src_areas[chn-1].addr != src_areas[chn].addr) { +- interleaved = 0; +- break; +- } ++ if (dst_areas[chn-1].addr != dst_areas[chn].addr) ++ goto __nointerleaved; ++ if (src_areas[chn-1].addr != src_areas[chn].addr) ++ goto __nointerleaved; + } + for (chn = 0; chn < channels; chn++) { +- if (dmix->bindings && dmix->bindings[chn] != chn) { +- interleaved = 0; +- break; +- } ++ if (dmix->bindings && dmix->bindings[chn] != chn) ++ goto __nointerleaved; + if (dst_areas[chn].first != chn * bits || +- dst_areas[chn].step != channels * bits) { +- interleaved = 0; +- break; +- } ++ dst_areas[chn].step != channels * bits) ++ goto __nointerleaved; + if (src_areas[chn].first != chn * bits || +- src_areas[chn].step != channels * bits) { +- interleaved = 0; +- break; +- } ++ src_areas[chn].step != channels * bits) ++ goto __nointerleaved; + } +- return dmix->interleaved = interleaved; ++ return dmix->interleaved = 1; ++__nointerleaved: ++ return dmix->interleaved = 0; + } + + /* +-- +2.31.1 + + +From ccc14ae897d170156f1c2905ea5d18a3295e7b36 Mon Sep 17 00:00:00 2001 +From: "Tanjeff-N. Moos" +Date: Thu, 17 Jun 2021 10:36:38 +0200 +Subject: [PATCH 09/20] control: Add documentation for snd_ctl_card_* and + friends. + +In this patch series, I added a description about control interface +handling and how control interfaces are identified. + +In addition, I added/improved Doxygen documentation for the +snd_ctl_card_info_t type and related corresponding functions, +e.g. snd_ctl_card_info(). I also documented other card-related like +snd_card_next(). + +Along the way I did minor documentation improvements. + +Signed-off-by: Tanjeff-N. Moos +Signed-off-by: Takashi Iwai +--- + include/control.h | 40 +++++++++- + src/control/cards.c | 56 +++++++++----- + src/control/control.c | 175 +++++++++++++++++++++++++++++++----------- + 3 files changed, 202 insertions(+), 69 deletions(-) + +diff --git a/include/control.h b/include/control.h +index ccf906e2..9ebb4905 100644 +--- a/include/control.h ++++ b/include/control.h +@@ -50,7 +50,32 @@ typedef struct snd_aes_iec958 { + unsigned char dig_subframe[4]; /**< AES/IEC958 subframe bits */ + } snd_aes_iec958_t; + +-/** CTL card info container */ ++/** \brief CTL card info container. ++ * ++ * This type contains meta information about a sound card, such as the index, ++ * name, longname, etc. ++ * ++ * \par Memory management ++ * ++ * Before using a snd_ctl_card_info_t object, it must be allocated using ++ * snd_ctl_card_info_alloca() or snd_ctl_card_info_malloc(). When using the ++ * latter, it must be freed again using snd_ctl_card_info_free(). ++ * ++ * A card info object can be zeroed out using snd_ctl_card_info_clear(). ++ * ++ * A card info object can be copied to another one using ++ * snd_ctl_card_info_copy(). ++ * ++ * \par Obtaining the Information ++ * ++ * To obtain the card information, it must first be opened using ++ * snd_ctl_open(), and a snd_ctl_card_info_t container must be ++ * allocated. Then, the information can be read using ++ * snd_ctl_card_info_get_card(). ++ * ++ * Thereafter, the card properties can be read using the ++ * snd_ctl_card_info_get_*() functions. ++ */ + typedef struct _snd_ctl_card_info snd_ctl_card_info_t; + + /** CTL element identifier container */ +@@ -442,11 +467,20 @@ void snd_ctl_elem_id_set_name(snd_ctl_elem_id_t *obj, const char *val); + void snd_ctl_elem_id_set_index(snd_ctl_elem_id_t *obj, unsigned int val); + + size_t snd_ctl_card_info_sizeof(void); ++ + /** \hideinitializer +- * \brief allocate an invalid #snd_ctl_card_info_t using standard alloca +- * \param ptr returned pointer ++ * \brief Allocate an invalid #snd_ctl_card_info_t on the stack. ++ * ++ * Allocate space for a card info object on the stack. The allocated ++ * memory need not be freed, because it is on the stack. ++ * ++ * See snd_ctl_card_info_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_card_info_alloca(ptr) __snd_alloca(ptr, snd_ctl_card_info) ++ + int snd_ctl_card_info_malloc(snd_ctl_card_info_t **ptr); + void snd_ctl_card_info_free(snd_ctl_card_info_t *obj); + void snd_ctl_card_info_clear(snd_ctl_card_info_t *obj); +diff --git a/src/control/cards.c b/src/control/cards.c +index e57457c2..8226c42d 100644 +--- a/src/control/cards.c ++++ b/src/control/cards.c +@@ -77,8 +77,8 @@ static int snd_card_load1(int card) + + /** + * \brief Try to load the driver for a card. +- * \param card Card number. +- * \return 1 if driver is present, zero if driver is not present ++ * \param card Card index. ++ * \return 1 if driver is present, zero if driver is not present. + */ + int snd_card_load(int card) + { +@@ -86,14 +86,24 @@ int snd_card_load(int card) + } + + /** +- * \brief Try to determine the next card. +- * \param rcard pointer to card number +- * \result zero if success, otherwise a negative error code ++ * \brief Iterate over physical sound cards. ++ * ++ * This function takes the index of a physical sound card and sets it to the ++ * index of the next card. If index is -1, it is set to the index of the first ++ * card. After the last card, the index is set to -1. ++ * ++ * For example, if you have 2 sound cards (with index 0 and 1), the index will ++ * be modified as follows: ++ * ++ * - -1 --> 0 ++ * - 0 --> 1 ++ * - 1 --> -1 ++ * ++ * This does not work for virtual sound cards. + * +- * Tries to determine the next card from given card number. +- * If card number is -1, then the first available card is +- * returned. If the result card number is -1, no more cards +- * are available. ++ * \param rcard Index of current card. The index of the next card is stored ++ * here. ++ * \result zero if success, otherwise a negative error code. + */ + int snd_card_next(int *rcard) + { +@@ -114,13 +124,18 @@ int snd_card_next(int *rcard) + } + + /** +- * \brief Convert card string to an integer value. +- * \param string String containing card identifier +- * \return zero if success, otherwise a negative error code ++ * \brief Convert a card string to the card index. + * +- * The accepted format is an integer value in ASCII representation +- * or the card identifier (the id parameter for sound-card drivers). +- * The control device name like /dev/snd/controlC0 is accepted, too. ++ * This works only for physical sound cards, not for virtual cards. ++ * ++ * \param string A string identifying the card. ++ * \return The index of the card. On error, a a negative error code ++ * is returned. ++ * ++ * The accepted formats for "string" are: ++ * - The index of the card (as listed in /proc/asound/cards), given as string ++ * - The ID of the card (as listed in /proc/asound/cards) ++ * - The control device name (like /dev/snd/controlC0) + */ + int snd_card_get_index(const char *string) + { +@@ -163,8 +178,9 @@ int snd_card_get_index(const char *string) + + /** + * \brief Obtain the card name. +- * \param card Card number +- * \param name Result - card name corresponding to card number ++ * ++ * \param card The index of the card. ++ * \param name Result - card name corresponding to card index. + * \result zero if success, otherwise a negative error code + * + * The value returned in name is allocated with strdup and should be +@@ -193,9 +209,9 @@ int snd_card_get_name(int card, char **name) + + /** + * \brief Obtain the card long name. +- * \param card Card number +- * \param name Result - card long name corresponding to card number +- * \result zero if success, otherwise a negative error code ++ * \param card Index of the card. ++ * \param name Result - card long name corresponding to card index. ++ * \result Zero if success, otherwise a negative error code. + * + * The value returned in name is allocated with strdup and should be + * freed when no longer used. +diff --git a/src/control/control.c b/src/control/control.c +index ed986e54..7cf4decb 100644 +--- a/src/control/control.c ++++ b/src/control/control.c +@@ -33,8 +33,50 @@ +

Control interface is designed to access primitive controls. There is + also an interface for notifying about control and structure changes. + ++ + \section control_general_overview General overview + ++In Alsa, there are physical sound cards, such as USB headsets, and ++virtual sound cards, such as "pulse", which represents the PulseAudio ++Sound system. Each sound card offers a control interface, making its ++settings (e.g. volume knobs) available. The complete list of available ++control interfaces can be obtained using snd_device_name_hint(), ++giving -1 as card index and "ctl" as interface type. Each returned ++NAME hint identifies a control interface. ++ ++Sound cards have an ID (a string), an index (an int, sometimes called ++the "card number"), a name, a longname, a mixername and a "components" ++property. The file /proc/asound/cards lists most of these properties ++for physical sound cards. Virtual sound cards are not listed in that ++file. The format is: ++ ++\verbatim ++index [ID ] Driver - name ++ longname ++\endverbatim ++ ++Note that the mixername and components are not listed. ++ ++ ++\subsection control_cards_id Identifying and Opening Control Interfaces ++ ++To work with a control interface, is must be opened first, using ++snd_ctl_open(). This function takes the interface name. ++ ++For physical sound cards, the control interface can be identified ++using the string "hw:" (e.g. `hw:2`). The NAME hint - which is ++"hw:CARD=" - can also be used. Further, its device file (something ++like `/dev/snd/controlC0`) is also acceptable. Either of them can be ++given to snd_ctl_open(). ++ ++For virtual sound cards, the NAME hint is given to snd_ctl_open(). ++ ++The functions snd_card_get_index(), snd_card_get_name() and ++snd_card_get_longname() can be used to find an identifying property ++when another one is already known. ++ ++\section control_elements Elements ++ + In ALSA control feature, each sound card can have control elements. The elements + are managed according to below model. + +@@ -65,7 +107,7 @@ are managed according to below model. + of userspace applications and drivers in kernel. + + +-\section identifying_elements Identifying Elements ++\subsection identifying_elements Identifying Elements + + Each element has the following identifying properties: + +@@ -84,7 +126,7 @@ 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. The short numid is used to reduce the lookup time. + +-\section element_lists Element Lists ++\subsection 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 +@@ -93,7 +135,7 @@ elements the card has), and the identifying properties of the elements + element lists. + + +-\section working_with_elements Working with Elements ++\subsection 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 +@@ -108,7 +150,7 @@ 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 ++\subsection 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 +@@ -329,10 +371,15 @@ int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe) + + + /** +- * \brief Get card related information +- * \param ctl CTL handle +- * \param info Card info pointer +- * \return 0 on success otherwise a negative error code ++ * \brief Get information about the sound card. ++ * ++ * Obtain information about the sound card previously opened using ++ * snd_ctl_open(). The object "info" must be allocated prior to calling this ++ * function. See snd_ctl_card_info_t for details. ++ * ++ * \param ctl The CTL handle. ++ * \param info The card information is stored here. ++ * \return 0 on success, otherwise a negative error code. + */ + int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info) + { +@@ -1508,11 +1555,13 @@ int _snd_ctl_open_named_child(snd_ctl_t **pctl, const char *name, + #endif + + /** +- * \brief Opens a CTL +- * \param ctlp Returned CTL handle +- * \param name ASCII identifier of the CTL handle +- * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC) +- * \return 0 on success otherwise a negative error code ++ * \brief Opens a sound card. ++ * ++ * \param ctlp Returned CTL handle. ++ * \param name A string identifying the card (See \ref control_cards_id). ++ * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC). ++ * ++ * \return 0 on success otherwise a negative error code. + */ + int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode) + { +@@ -2027,8 +2076,8 @@ void snd_ctl_elem_id_set_index(snd_ctl_elem_id_t *obj, unsigned int val) + } + + /** +- * \brief get size of #snd_ctl_card_info_t +- * \return size in bytes ++ * \brief get size of #snd_ctl_card_info_t. ++ * \return Size in bytes. + */ + size_t snd_ctl_card_info_sizeof() + { +@@ -2036,9 +2085,16 @@ size_t snd_ctl_card_info_sizeof() + } + + /** +- * \brief allocate an invalid #snd_ctl_card_info_t using standard malloc +- * \param ptr returned pointer +- * \return 0 on success otherwise negative error code ++ * \brief Allocate an invalid #snd_ctl_card_info_t on the heap. ++ * ++ * Allocate space for a card info object on the heap. The allocated memory ++ * must be freed using snd_ctl_card_info_free(). ++ * ++ * See snd_ctl_card_info_t for details. ++ * ++ * \param ptr Pointer to a snd_ctl_card_info_t pointer. The address ++ * of the allocated space will be returned here. ++ * \return 0 on success, otherwise a negative error code. + */ + int snd_ctl_card_info_malloc(snd_ctl_card_info_t **ptr) + { +@@ -2050,8 +2106,10 @@ int snd_ctl_card_info_malloc(snd_ctl_card_info_t **ptr) + } + + /** +- * \brief frees a previously allocated #snd_ctl_card_info_t +- * \param obj pointer to object to free ++ * \brief Free an #snd_ctl_card_info_t previously allocated using ++ * snd_ctl_card_info_malloc(). ++ * ++ * \param obj Pointer to the snd_ctl_card_info_t. + */ + void snd_ctl_card_info_free(snd_ctl_card_info_t *obj) + { +@@ -2059,8 +2117,11 @@ void snd_ctl_card_info_free(snd_ctl_card_info_t *obj) + } + + /** +- * \brief clear given #snd_ctl_card_info_t object +- * \param obj pointer to object to clear ++ * \brief Clear given card info object. ++ * ++ * See snd_ctl_elem_value_t for details. ++ * ++ * \param obj Card info object. + */ + void snd_ctl_card_info_clear(snd_ctl_card_info_t *obj) + { +@@ -2068,9 +2129,10 @@ void snd_ctl_card_info_clear(snd_ctl_card_info_t *obj) + } + + /** +- * \brief copy one #snd_ctl_card_info_t to another +- * \param dst pointer to destination +- * \param src pointer to source ++ * \brief Bitwise copy of a #snd_ctl_card_info_t object. ++ * ++ * \param dst Pointer to destination. ++ * \param src Pointer to source. + */ + void snd_ctl_card_info_copy(snd_ctl_card_info_t *dst, const snd_ctl_card_info_t *src) + { +@@ -2079,9 +2141,12 @@ void snd_ctl_card_info_copy(snd_ctl_card_info_t *dst, const snd_ctl_card_info_t + } + + /** +- * \brief Get card number from a CTL card info +- * \param obj CTL card info +- * \return card number ++ * \brief Get the sound card index from the given info object. ++ * ++ * See snd_ctl_card_info_t for more details. ++ * ++ * \param obj The card info object. ++ * \return Sound card index. + */ + int snd_ctl_card_info_get_card(const snd_ctl_card_info_t *obj) + { +@@ -2090,9 +2155,12 @@ int snd_ctl_card_info_get_card(const snd_ctl_card_info_t *obj) + } + + /** +- * \brief Get card identifier from a CTL card info +- * \param obj CTL card info +- * \return card identifier ++ * \brief Get the sound card ID from the given info object. ++ * ++ * See snd_ctl_card_info_t for more details. ++ * ++ * \param obj The card info object. ++ * \return Sound card ID. + */ + const char *snd_ctl_card_info_get_id(const snd_ctl_card_info_t *obj) + { +@@ -2101,9 +2169,12 @@ const char *snd_ctl_card_info_get_id(const snd_ctl_card_info_t *obj) + } + + /** +- * \brief Get card driver name from a CTL card info +- * \param obj CTL card info +- * \return card driver name ++ * \brief Get the sound card driver from the given info object. ++ * ++ * See snd_ctl_card_info_t for more details. ++ * ++ * \param obj The card info object. ++ * \return The sound card driver. + */ + const char *snd_ctl_card_info_get_driver(const snd_ctl_card_info_t *obj) + { +@@ -2112,9 +2183,12 @@ const char *snd_ctl_card_info_get_driver(const snd_ctl_card_info_t *obj) + } + + /** +- * \brief Get card name from a CTL card info +- * \param obj CTL card info +- * \return card name ++ * \brief Get the sound card name from the given info object. ++ * ++ * See snd_ctl_card_info_t for more details. ++ * ++ * \param obj The card info object. ++ * \return Sound card name. + */ + const char *snd_ctl_card_info_get_name(const snd_ctl_card_info_t *obj) + { +@@ -2123,9 +2197,12 @@ const char *snd_ctl_card_info_get_name(const snd_ctl_card_info_t *obj) + } + + /** +- * \brief Get card long name from a CTL card info +- * \param obj CTL card info +- * \return card long name ++ * \brief Get the sound cards long name from the given info object. ++ * ++ * See snd_ctl_card_info_t for more details. ++ * ++ * \param obj The card info object. ++ * \return Sound cards long name. + */ + const char *snd_ctl_card_info_get_longname(const snd_ctl_card_info_t *obj) + { +@@ -2134,9 +2211,12 @@ const char *snd_ctl_card_info_get_longname(const snd_ctl_card_info_t *obj) + } + + /** +- * \brief Get card mixer name from a CTL card info +- * \param obj CTL card info +- * \return card mixer name ++ * \brief Get the sound card mixer name from the given info object. ++ * ++ * See snd_ctl_card_info_t for more details. ++ * ++ * \param obj The card info object. ++ * \return Sound card mixer name. + */ + const char *snd_ctl_card_info_get_mixername(const snd_ctl_card_info_t *obj) + { +@@ -2145,9 +2225,12 @@ const char *snd_ctl_card_info_get_mixername(const snd_ctl_card_info_t *obj) + } + + /** +- * \brief Get card component list from a CTL card info +- * \param obj CTL card info +- * \return card mixer identifier ++ * \brief Get the sound cards "components" property from the given info object. ++ * ++ * See snd_ctl_card_info_t for more details. ++ * ++ * \param obj The card info object. ++ * \return Sound cards "components" property. + */ + const char *snd_ctl_card_info_get_components(const snd_ctl_card_info_t *obj) + { +-- +2.31.1 + + +From 7ba3f888d07cafbad04391b915db23408c663dad Mon Sep 17 00:00:00 2001 +From: "Tanjeff-N. Moos" +Date: Thu, 17 Jun 2021 10:36:39 +0200 +Subject: [PATCH 10/20] control: Minor documentation fixes. + +Signed-off-by: Tanjeff-N. Moos +Signed-off-by: Takashi Iwai +--- + include/control.h | 9 +++++++-- + src/control/cards.c | 5 ++++- + src/control/control.c | 2 +- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/include/control.h b/include/control.h +index 9ebb4905..e386ecec 100644 +--- a/include/control.h ++++ b/include/control.h +@@ -155,7 +155,7 @@ 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. +@@ -167,6 +167,11 @@ typedef struct _snd_ctl_elem_info snd_ctl_elem_info_t; + * using the latter, it must be freed again using + * snd_ctl_elem_value_free(). + * ++ * A value object can be zeroed out using snd_ctl_elem_value_clear(). ++ * ++ * A value object can be copied to another one using ++ * snd_ctl_elem_value_copy(). ++ * + * \par Identifier + * + * Then, the ID must be filled. It is sufficient to fill only the +@@ -621,7 +626,7 @@ size_t snd_ctl_elem_value_sizeof(void); + * \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. ++ * memory need not be freed, because it is on the stack. + * + * See snd_ctl_elem_value_t for details. + * +diff --git a/src/control/cards.c b/src/control/cards.c +index 8226c42d..6145ebcd 100644 +--- a/src/control/cards.c ++++ b/src/control/cards.c +@@ -147,6 +147,7 @@ int snd_card_get_index(const char *string) + return -EINVAL; + if ((isdigit(*string) && *(string + 1) == 0) || + (isdigit(*string) && isdigit(*(string + 1)) && *(string + 2) == 0)) { ++ /* We got an index */ + if (sscanf(string, "%i", &card) != 1) + return -EINVAL; + if (card < 0 || card >= SND_MAX_CARDS) +@@ -156,8 +157,10 @@ int snd_card_get_index(const char *string) + return card; + return err; + } +- if (string[0] == '/') /* device name */ ++ if (string[0] == '/') ++ /* We got a device name */ + return snd_card_load2(string); ++ /* We got in ID */ + for (card = 0; card < SND_MAX_CARDS; card++) { + #ifdef SUPPORT_ALOAD + if (! snd_card_load(card)) +diff --git a/src/control/control.c b/src/control/control.c +index 7cf4decb..91415b51 100644 +--- a/src/control/control.c ++++ b/src/control/control.c +@@ -3127,7 +3127,7 @@ size_t snd_ctl_elem_value_sizeof() + /** + * \brief Allocate an invalid #snd_ctl_elem_value_t on the heap. + * +- * Allocate space for a value object on the head. The allocated memory ++ * Allocate space for a value object on the heap. The allocated memory + * must be freed using snd_ctl_elem_value_free(). + * + * See snd_ctl_elem_value_t for details. +-- +2.31.1 + + +From f4f29d42be8b8ad60ea4c5697374adad4bfe6868 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 28 Jun 2021 12:08:53 +0200 +Subject: [PATCH 11/20] fix build with --disable-ucm + +Link: https://mailman.alsa-project.org/pipermail/alsa-devel/2021-June/186729.html +Reported-by: Michael Forney +Signed-off-by: Jaroslav Kysela +--- + include/local.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/include/local.h b/include/local.h +index 4e7d88a0..7cfcec53 100644 +--- a/include/local.h ++++ b/include/local.h +@@ -374,6 +374,8 @@ int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in, + void *INTERNAL(snd_dlopen)(const char *name, int mode, char *errbuf, size_t errbuflen); + #endif + ++#ifdef BUILD_UCM ++ + const char *uc_mgr_alibcfg_by_device(snd_config_t **config, const char *name); + + static inline int _snd_is_ucm_device(const char *name) +@@ -381,4 +383,12 @@ static inline int _snd_is_ucm_device(const char *name) + return name && name[0] == '_' && name[1] == 'u' && name[2] == 'c' && name[3] == 'm'; + } + ++#else ++ ++static inline const char *uc_mgr_alibcfg_by_device(snd_config_t **config, const char *name) { return NULL; } ++static inline int _snd_is_ucm_device(const char *name) { return 0; } ++ ++ ++#endif ++ + #endif +-- +2.31.1 + + +From 1a1f0fb244c477c430e156da878475ef57d198f9 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 28 Jun 2021 12:11:54 +0200 +Subject: [PATCH 12/20] pcm: rate - fix some gcc warnings + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_rate.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c +index 13111d29..c45895a9 100644 +--- a/src/pcm/pcm_rate.c ++++ b/src/pcm/pcm_rate.c +@@ -82,12 +82,12 @@ struct _snd_pcm_rate { + + /* allocate a channel area and a temporary buffer for the given size */ + static snd_pcm_channel_area_t * +-rate_alloc_tmp_buf(snd_pcm_rate_t *rate, snd_pcm_format_t format, ++rate_alloc_tmp_buf(snd_pcm_format_t format, + unsigned int channels, unsigned int frames) + { + snd_pcm_channel_area_t *ap; + int width = snd_pcm_format_physical_width(format); +- int i; ++ unsigned int i; + + ap = malloc(sizeof(*ap) * channels); + if (!ap) +@@ -354,7 +354,7 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + snd_pcm_rate_t *rate = pcm->private_data; + snd_pcm_t *slave = rate->gen.slave; + snd_pcm_rate_side_info_t *sinfo, *cinfo; +- unsigned int channels, cwidth, swidth, chn, acc; ++ unsigned int channels, acc; + int need_src_buf, need_dst_buf; + int err = snd_pcm_hw_params_slave(pcm, params, + snd_pcm_rate_hw_refine_cchange, +@@ -401,9 +401,9 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + return -EBUSY; + } + +- rate->pareas = rate_alloc_tmp_buf(rate, cinfo->format, channels, ++ rate->pareas = rate_alloc_tmp_buf(cinfo->format, channels, + cinfo->period_size); +- rate->sareas = rate_alloc_tmp_buf(rate, sinfo->format, channels, ++ rate->sareas = rate_alloc_tmp_buf(sinfo->format, channels, + sinfo->period_size); + if (!rate->pareas || !rate->sareas) { + err = -ENOMEM; +@@ -442,7 +442,7 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + rate->src_conv_idx = + snd_pcm_linear_convert_index(rate->orig_in_format, + rate->info.in.format); +- rate->src_buf = rate_alloc_tmp_buf(rate, rate->info.in.format, ++ rate->src_buf = rate_alloc_tmp_buf(rate->info.in.format, + channels, rate->info.in.period_size); + if (!rate->src_buf) { + err = -ENOMEM; +@@ -454,7 +454,7 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) + rate->dst_conv_idx = + snd_pcm_linear_convert_index(rate->info.out.format, + rate->orig_out_format); +- rate->dst_buf = rate_alloc_tmp_buf(rate, rate->info.out.format, ++ rate->dst_buf = rate_alloc_tmp_buf(rate->info.out.format, + channels, rate->info.out.period_size); + if (!rate->dst_buf) { + err = -ENOMEM; +-- +2.31.1 + + +From e47c11822d6b459a9b3704b3ee6a4a5c9a1b85be Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 29 Jun 2021 18:02:27 +0200 +Subject: [PATCH 13/20] control: remap - assign right name to the child handle + for no-op + +Fixes: https://github.com/alsa-project/alsa-utils/issues/100 +Signed-off-by: Jaroslav Kysela +--- + src/control/control_remap.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/control/control_remap.c b/src/control/control_remap.c +index a85c1725..81524014 100644 +--- a/src/control/control_remap.c ++++ b/src/control/control_remap.c +@@ -1173,6 +1173,10 @@ int snd_ctl_remap_open(snd_ctl_t **handlep, const char *name, snd_config_t *rema + /* no-op check, remove the plugin */ + if (priv->map_items == 0 && priv->remap_items == 0) { + remap_free(priv); ++ free(child->name); ++ child->name = name ? strdup(name) : NULL; ++ if (name && !child->name) ++ return -ENOMEM; + *handlep = child; + return 0; + } +-- +2.31.1 + + +From 23a191a82c693456e61431ab699cddc1e5782a26 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 29 Jun 2021 19:31:28 +0200 +Subject: [PATCH 14/20] control: remap - assign right name to the child handle + for no-op (2nd case) + +Fixes: https://github.com/alsa-project/alsa-utils/issues/100 +Signed-off-by: Jaroslav Kysela +--- + src/control/control_remap.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/control/control_remap.c b/src/control/control_remap.c +index 81524014..4914f960 100644 +--- a/src/control/control_remap.c ++++ b/src/control/control_remap.c +@@ -1154,6 +1154,10 @@ int snd_ctl_remap_open(snd_ctl_t **handlep, const char *name, snd_config_t *rema + snd_ctl_t *ctl; + int result, err; + ++ /* no-op, remove the plugin */ ++ if (!remap && !map) ++ goto _noop; ++ + priv = calloc(1, sizeof(*priv)); + if (priv == NULL) + return -ENOMEM; +@@ -1173,6 +1177,7 @@ int snd_ctl_remap_open(snd_ctl_t **handlep, const char *name, snd_config_t *rema + /* no-op check, remove the plugin */ + if (priv->map_items == 0 && priv->remap_items == 0) { + remap_free(priv); ++ _noop: + free(child->name); + child->name = name ? strdup(name) : NULL; + if (name && !child->name) +@@ -1316,11 +1321,6 @@ int _snd_ctl_remap_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd + err = _snd_ctl_open_child(&cctl, root, child, mode, conf); + if (err < 0) + return err; +- /* no-op, remove the plugin */ +- if (!remap && !map) { +- *handlep = cctl; +- return 0; +- } + err = snd_ctl_remap_open(handlep, name, remap, map, cctl, mode); + if (err < 0) + snd_ctl_close(cctl); +-- +2.31.1 + + +From 7d40a76ef5494e08af00fa4e7bfefbd43aba4827 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 31 Aug 2021 09:25:12 +0200 +Subject: [PATCH 19/20] ucm: avoid zero card instance number + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/utils.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/ucm/utils.c b/src/ucm/utils.c +index f3a8c9ba..10b21c34 100644 +--- a/src/ucm/utils.c ++++ b/src/ucm/utils.c +@@ -780,6 +780,9 @@ int uc_mgr_card_open(snd_use_case_mgr_t *uc_mgr) + while (uc_mgr_card_find(ucm_card_assign)) { + ucm_card_assign++; + ucm_card_assign &= 0xffff; ++ /* avoid zero card instance number */ ++ if (ucm_card_assign == 0) ++ ucm_card_assign++; + if (ucm_card_assign == prev) { + pthread_mutex_unlock(&ucm_cards_mutex); + return -ENOMEM; +-- +2.31.1 + + +From 4a52ae4c329ae17117375a4b85b80f37994a4044 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 31 Aug 2021 09:40:42 +0200 +Subject: [PATCH 20/20] ucm: fix the parsing of the hexadecimal prefix + +The safe_strtol() function use strtol() which expects +to have the '0x' prefix for the hexadecimal number (when +base argument is zero). + +BugLink: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1553 +Signed-off-by: Jaroslav Kysela +--- + src/ucm/utils.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/ucm/utils.c b/src/ucm/utils.c +index 10b21c34..2fbc4c8c 100644 +--- a/src/ucm/utils.c ++++ b/src/ucm/utils.c +@@ -811,7 +811,7 @@ void uc_mgr_card_close(snd_use_case_mgr_t *uc_mgr) + */ + const char *uc_mgr_alibcfg_by_device(snd_config_t **top, const char *name) + { +- char buf[5]; ++ char buf[7]; + long card_num; + snd_config_t *config; + snd_use_case_mgr_t *uc_mgr; +@@ -819,8 +819,10 @@ const char *uc_mgr_alibcfg_by_device(snd_config_t **top, const char *name) + + if (strncmp(name, "_ucm", 4) || strlen(name) < 12 || name[8] != '.') + return NULL; +- strncpy(buf, name + 4, 4); +- buf[4] = '\0'; ++ buf[0] = '0'; ++ buf[1] = 'x'; ++ strncpy(buf + 2, name + 4, 4); ++ buf[6] = '\0'; + err = safe_strtol(buf, &card_num); + if (err < 0 || card_num < 0 || card_num > 0xffff) + return NULL; +-- +2.31.1 + diff --git a/alsa-lib.spec b/alsa-lib.spec index d923688..8ff5b53 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -9,7 +9,7 @@ Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 1%{?prever_dot}%{?dist} +Release: 2%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,6 +167,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Tue Aug 31 2021 Jaroslav Kysela - 1.2.5.1-2 +- add UCM related fixes + * Mon Jun 14 2021 Jaroslav Kysela - 1.2.5.1-1 - update to 1.2.5.1 From 3aa0c13e226bab7eef802e24c0a2b49eee340620 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 6 Dec 2021 13:17:48 +0100 Subject: [PATCH 05/10] update to 1.2.6 --- alsa-git.patch | 1916 ------------------------------------------------ alsa-lib.spec | 9 +- sources | 4 +- 3 files changed, 8 insertions(+), 1921 deletions(-) diff --git a/alsa-git.patch b/alsa-git.patch index f88de1b..e69de29 100644 --- a/alsa-git.patch +++ b/alsa-git.patch @@ -1,1916 +0,0 @@ -From 81e7923fbfad45b2f353a4d6e3053af51f5f7d0b Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Tue, 15 Jun 2021 23:21:42 +0200 -Subject: [PATCH 01/20] control: empty - fix the static build - -Reported-by: Jan Palus -Fixes: https://github.com/alsa-project/alsa-lib/issues/157 -Signed-off-by: Jaroslav Kysela ---- - src/control/control_empty.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/control/control_empty.c b/src/control/control_empty.c -index 49d1026c..c9b048c1 100644 ---- a/src/control/control_empty.c -+++ b/src/control/control_empty.c -@@ -30,7 +30,7 @@ - - #ifndef PIC - /* entry for static linking */ --const char *_snd_module_ctl_empty = ""; -+const char *_snd_module_control_empty = ""; - #endif - - /*! \page control_plugins --- -2.31.1 - - -From 5089358aa99d698bd846b05c1890a09613d740b3 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Thu, 17 Jun 2021 10:20:25 +0200 -Subject: [PATCH 02/20] pcm: rate: Refactoring temporary buffer allocations - -Introduce common helpers to allocate and release the temporary buffers -and the associated snd_pcm_channel. Now two allocated objects are -used instead of one malloc to be split. - -Also, change the snd_pcm_channel set up to be in interleaved mode. -This will be necessary in the following change in the rate plugin. - -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_rate.c | 80 ++++++++++++++++++++++++++++------------------ - 1 file changed, 49 insertions(+), 31 deletions(-) - -diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c -index 770aafea..1e996134 100644 ---- a/src/pcm/pcm_rate.c -+++ b/src/pcm/pcm_rate.c -@@ -76,6 +76,45 @@ struct _snd_pcm_rate { - - #endif /* DOC_HIDDEN */ - -+/* allocate a channel area and a temporary buffer for the given size */ -+static snd_pcm_channel_area_t * -+rate_alloc_tmp_buf(snd_pcm_rate_t *rate, snd_pcm_format_t format, -+ unsigned int channels, unsigned int frames) -+{ -+ snd_pcm_channel_area_t *ap; -+ int width = snd_pcm_format_physical_width(format); -+ int i; -+ -+ ap = malloc(sizeof(*ap) * channels); -+ if (!ap) -+ return NULL; -+ ap->addr = malloc(frames * channels * width / 8); -+ if (!ap->addr) { -+ free(ap); -+ return NULL; -+ } -+ -+ /* set up in interleaved format */ -+ for (i = 0; i < channels; i++) { -+ ap[i].addr = ap[0].addr + (i * width) / 8; -+ ap[i].first = 0; -+ ap[i].step = width * channels; -+ } -+ -+ return ap; -+} -+ -+static void rate_free_tmp_buf(snd_pcm_channel_area_t **ptr) -+{ -+ snd_pcm_channel_area_t *c = *ptr; -+ -+ if (c) { -+ free(c->addr); -+ free(c); -+ *ptr = NULL; -+ } -+} -+ - static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params) - { - snd_pcm_rate_t *rate = pcm->private_data; -@@ -286,28 +325,13 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - if (err < 0) - return err; - -- rate->pareas = malloc(2 * channels * sizeof(*rate->pareas)); -- if (rate->pareas == NULL) -+ rate->pareas = rate_alloc_tmp_buf(rate, cinfo->format, channels, -+ cinfo->period_size); -+ rate->sareas = rate_alloc_tmp_buf(rate, sinfo->format, channels, -+ sinfo->period_size); -+ if (!rate->pareas || !rate->sareas) - goto error; - -- cwidth = snd_pcm_format_physical_width(cinfo->format); -- swidth = snd_pcm_format_physical_width(sinfo->format); -- rate->pareas[0].addr = malloc(((cwidth * channels * cinfo->period_size) / 8) + -- ((swidth * channels * sinfo->period_size) / 8)); -- if (rate->pareas[0].addr == NULL) -- goto error; -- -- rate->sareas = rate->pareas + channels; -- rate->sareas[0].addr = (char *)rate->pareas[0].addr + ((cwidth * channels * cinfo->period_size) / 8); -- for (chn = 0; chn < channels; chn++) { -- rate->pareas[chn].addr = (char *)rate->pareas[0].addr + (cwidth * chn * cinfo->period_size) / 8; -- rate->pareas[chn].first = 0; -- rate->pareas[chn].step = cwidth; -- rate->sareas[chn].addr = (char *)rate->sareas[0].addr + (swidth * chn * sinfo->period_size) / 8; -- rate->sareas[chn].first = 0; -- rate->sareas[chn].step = swidth; -- } -- - if (rate->ops.convert_s16) { - rate->get_idx = snd_pcm_linear_get_index(rate->info.in.format, SND_PCM_FORMAT_S16); - rate->put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, rate->info.out.format); -@@ -322,11 +346,8 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - return 0; - - error: -- if (rate->pareas) { -- free(rate->pareas[0].addr); -- free(rate->pareas); -- rate->pareas = NULL; -- } -+ rate_free_tmp_buf(&rate->pareas); -+ rate_free_tmp_buf(&rate->sareas); - if (rate->ops.free) - rate->ops.free(rate->obj); - return -ENOMEM; -@@ -335,12 +356,9 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - static int snd_pcm_rate_hw_free(snd_pcm_t *pcm) - { - snd_pcm_rate_t *rate = pcm->private_data; -- if (rate->pareas) { -- free(rate->pareas[0].addr); -- free(rate->pareas); -- rate->pareas = NULL; -- rate->sareas = NULL; -- } -+ -+ rate_free_tmp_buf(&rate->pareas); -+ rate_free_tmp_buf(&rate->sareas); - if (rate->ops.free) - rate->ops.free(rate->obj); - free(rate->src_buf); --- -2.31.1 - - -From 119d9c1678b1193f8b969a6483cae1f7bf95e609 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Thu, 17 Jun 2021 10:03:17 +0200 -Subject: [PATCH 03/20] pcm: rate: Improve the support multiple formats - -This patch extends the PCM rate plugin for allowing its converter -plugin to deal with multiple formats. Currently, the converter plugin -is allowed to take different formats only when convert callback is -defined. And for this way (so far only the standard linear rate -plugin does), all linear formats have to be handled, and it's -cumbersome. - -OTOH, most other rate plugins are implemented with convert_s16 -callback, which accepts only S16 format. This is often not ideal -because many converter engines can handle 32bit formats. Also, the -target format is often 32bit format, hence this would require -additional conversion even if the converter engine can output 32bit -natively. - -In this patch, for addressing the problems above, the rate plugin API -is extended in the following way: - -- The new get_supported_formats callback is added; this stores the bit - masks of the supported input and output formats, as well as the - behavior flags. Currently only linear formats are allowed. -- When the plugin accepts only the interleaved stream, set - SND_PCM_RATE_FLAG_INTERLEAVED flag bit. Otherwise the code has to - handle snd_pcm_channel_area at each call. -- When both input and output formats have to be identical, pass - SND_PCM_RATE_FLAG_SYNC_FORMATS flag bit. -- When the converter wants to process different formats, use convert - callback instead of convert_s16. You can put both in the ops for - compatibility, too. - The input and output formats are found in the info argument of init - callback. -- Now the PCM rate plugin core will skip the temporary buffer - allocation and conversions for pre- and post-process if not needed - (i.e. matching with the requested input or output format). - -The rate plugin API version is bumped to 0x010003. - -Signed-off-by: Takashi Iwai ---- - include/pcm_rate.h | 36 ++++- - src/pcm/pcm_rate.c | 358 +++++++++++++++++++++++++++------------------ - 2 files changed, 251 insertions(+), 143 deletions(-) - -diff --git a/include/pcm_rate.h b/include/pcm_rate.h -index 4171fb9d..48473ed4 100644 ---- a/include/pcm_rate.h -+++ b/include/pcm_rate.h -@@ -38,7 +38,7 @@ extern "C" { - /** - * Protocol version - */ --#define SND_PCM_RATE_PLUGIN_VERSION 0x010002 -+#define SND_PCM_RATE_PLUGIN_VERSION 0x010003 - - /** hw_params information for a single side */ - typedef struct snd_pcm_rate_side_info { -@@ -55,6 +55,11 @@ typedef struct snd_pcm_rate_info { - unsigned int channels; - } snd_pcm_rate_info_t; - -+enum { -+ SND_PCM_RATE_FLAG_INTERLEAVED = (1U << 0), /** only interleaved format */ -+ SND_PCM_RATE_FLAG_SYNC_FORMATS = (1U << 1), /** both input and output formats have to be identical */ -+}; -+ - /** Callback table of rate-converter */ - typedef struct snd_pcm_rate_ops { - /** -@@ -114,6 +119,13 @@ typedef struct snd_pcm_rate_ops { - * new ops since version 0x010002 - */ - void (*dump)(void *obj, snd_output_t *out); -+ /** -+ * get the supported input and output formats (optional); -+ * new ops since version 0x010003 -+ */ -+ int (*get_supported_formats)(void *obj, uint64_t *in_formats, -+ uint64_t *out_formats, -+ unsigned int *flags); - } snd_pcm_rate_ops_t; - - /** open function type */ -@@ -147,6 +159,28 @@ typedef struct snd_pcm_rate_old_ops { - snd_pcm_uframes_t (*input_frames)(void *obj, snd_pcm_uframes_t frames); - snd_pcm_uframes_t (*output_frames)(void *obj, snd_pcm_uframes_t frames); - } snd_pcm_rate_old_ops_t; -+ -+/* old rate_ops for protocol version 0x010002 */ -+typedef struct snd_pcm_rate_v2_ops { -+ void (*close)(void *obj); -+ int (*init)(void *obj, snd_pcm_rate_info_t *info); -+ void (*free)(void *obj); -+ void (*reset)(void *obj); -+ int (*adjust_pitch)(void *obj, snd_pcm_rate_info_t *info); -+ void (*convert)(void *obj, -+ const snd_pcm_channel_area_t *dst_areas, -+ snd_pcm_uframes_t dst_offset, unsigned int dst_frames, -+ const snd_pcm_channel_area_t *src_areas, -+ snd_pcm_uframes_t src_offset, unsigned int src_frames); -+ void (*convert_s16)(void *obj, int16_t *dst, unsigned int dst_frames, -+ const int16_t *src, unsigned int src_frames); -+ snd_pcm_uframes_t (*input_frames)(void *obj, snd_pcm_uframes_t frames); -+ snd_pcm_uframes_t (*output_frames)(void *obj, snd_pcm_uframes_t frames); -+ unsigned int version; -+ int (*get_supported_rates)(void *obj, unsigned int *rate_min, -+ unsigned int *rate_max); -+ void (*dump)(void *obj, snd_output_t *out); -+} snd_pcm_rate_v2_ops_t; - #endif - - #ifdef __cplusplus -diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c -index 1e996134..13111d29 100644 ---- a/src/pcm/pcm_rate.c -+++ b/src/pcm/pcm_rate.c -@@ -62,18 +62,22 @@ struct _snd_pcm_rate { - void *open_func; - void *obj; - snd_pcm_rate_ops_t ops; -- unsigned int get_idx; -- unsigned int put_idx; -- int16_t *src_buf; -- int16_t *dst_buf; -+ unsigned int src_conv_idx; -+ unsigned int dst_conv_idx; -+ snd_pcm_channel_area_t *src_buf; -+ snd_pcm_channel_area_t *dst_buf; - int start_pending; /* start is triggered but not commited to slave */ - snd_htimestamp_t trigger_tstamp; - unsigned int plugin_version; - unsigned int rate_min, rate_max; -+ snd_pcm_format_t orig_in_format; -+ snd_pcm_format_t orig_out_format; -+ uint64_t in_formats; -+ uint64_t out_formats; -+ unsigned int format_flags; - }; - - #define SND_PCM_RATE_PLUGIN_VERSION_OLD 0x010001 /* old rate plugin */ -- - #endif /* DOC_HIDDEN */ - - /* allocate a channel area and a temporary buffer for the given size */ -@@ -274,12 +278,84 @@ static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm, - snd_pcm_generic_hw_refine); - } - -+/* evaluate the best matching available format to the given format */ -+static int get_best_format(uint64_t mask, snd_pcm_format_t orig) -+{ -+ int pwidth = snd_pcm_format_physical_width(orig); -+ int width = snd_pcm_format_width(orig); -+ int signd = snd_pcm_format_signed(orig); -+ int best_score = -1; -+ int match = -1; -+ int f, score; -+ -+ for (f = 0; f <= SND_PCM_FORMAT_LAST; f++) { -+ if (!(mask & (1ULL << f))) -+ continue; -+ score = 0; -+ if (snd_pcm_format_linear(f)) { -+ if (snd_pcm_format_physical_width(f) == pwidth) -+ score++; -+ if (snd_pcm_format_physical_width(f) >= pwidth) -+ score++; -+ if (snd_pcm_format_width(f) == width) -+ score++; -+ if (snd_pcm_format_signed(f) == signd) -+ score++; -+ } -+ if (score > best_score) { -+ match = f; -+ best_score = score; -+ } -+ } -+ -+ return match; -+} -+ -+/* set up the input and output formats from the available lists */ -+static int choose_preferred_format(snd_pcm_rate_t *rate) -+{ -+ uint64_t in_mask = rate->in_formats; -+ uint64_t out_mask = rate->out_formats; -+ int in, out; -+ -+ if (!in_mask || !out_mask) -+ return 0; -+ -+ if (rate->orig_in_format == rate->orig_out_format) -+ if (in_mask & out_mask & (1ULL << rate->orig_in_format)) -+ return 0; /* nothing changed */ -+ -+ repeat: -+ in = get_best_format(in_mask, rate->orig_in_format); -+ out = get_best_format(out_mask, rate->orig_out_format); -+ if (in < 0 || out < 0) -+ return -ENOENT; -+ -+ if ((rate->format_flags & SND_PCM_RATE_FLAG_SYNC_FORMATS) && -+ in != out) { -+ if (out_mask & (1ULL << in)) -+ out = in; -+ else if (in_mask & (1ULL << out)) -+ in = out; -+ else { -+ in_mask &= ~(1ULL << in); -+ out_mask &= ~(1ULL << out); -+ goto repeat; -+ } -+ } -+ -+ rate->info.in.format = in; -+ rate->info.out.format = out; -+ return 0; -+} -+ - static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - { - snd_pcm_rate_t *rate = pcm->private_data; - snd_pcm_t *slave = rate->gen.slave; - snd_pcm_rate_side_info_t *sinfo, *cinfo; -- unsigned int channels, cwidth, swidth, chn; -+ unsigned int channels, cwidth, swidth, chn, acc; -+ int need_src_buf, need_dst_buf; - int err = snd_pcm_hw_params_slave(pcm, params, - snd_pcm_rate_hw_refine_cchange, - snd_pcm_rate_hw_refine_sprepare, -@@ -308,6 +384,9 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - if (err < 0) - return err; - err = INTERNAL(snd_pcm_hw_params_get_channels)(params, &channels); -+ if (err < 0) -+ return err; -+ err = INTERNAL(snd_pcm_hw_params_get_access)(params, &acc); - if (err < 0) - return err; - -@@ -321,36 +400,80 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - SNDMSG("rate plugin already in use"); - return -EBUSY; - } -- err = rate->ops.init(rate->obj, &rate->info); -- if (err < 0) -- return err; - - rate->pareas = rate_alloc_tmp_buf(rate, cinfo->format, channels, - cinfo->period_size); - rate->sareas = rate_alloc_tmp_buf(rate, sinfo->format, channels, - sinfo->period_size); -- if (!rate->pareas || !rate->sareas) -- goto error; -- -- if (rate->ops.convert_s16) { -- rate->get_idx = snd_pcm_linear_get_index(rate->info.in.format, SND_PCM_FORMAT_S16); -- rate->put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, rate->info.out.format); -- free(rate->src_buf); -- rate->src_buf = malloc(channels * rate->info.in.period_size * 2); -- free(rate->dst_buf); -- rate->dst_buf = malloc(channels * rate->info.out.period_size * 2); -- if (! rate->src_buf || ! rate->dst_buf) -+ if (!rate->pareas || !rate->sareas) { -+ err = -ENOMEM; -+ goto error_pareas; -+ } -+ -+ rate->orig_in_format = rate->info.in.format; -+ rate->orig_out_format = rate->info.out.format; -+ if (choose_preferred_format(rate) < 0) { -+ SNDERR("No matching format in rate plugin"); -+ err = -EINVAL; -+ goto error_pareas; -+ } -+ -+ err = rate->ops.init(rate->obj, &rate->info); -+ if (err < 0) -+ goto error_init; -+ -+ rate_free_tmp_buf(&rate->src_buf); -+ rate_free_tmp_buf(&rate->dst_buf); -+ -+ need_src_buf = need_dst_buf = 0; -+ -+ if ((rate->format_flags & SND_PCM_RATE_FLAG_INTERLEAVED) && -+ !(acc == SND_PCM_ACCESS_MMAP_INTERLEAVED || -+ acc == SND_PCM_ACCESS_RW_INTERLEAVED)) { -+ need_src_buf = need_dst_buf = 1; -+ } else { -+ if (rate->orig_in_format != rate->info.in.format) -+ need_src_buf = 1; -+ if (rate->orig_out_format != rate->info.out.format) -+ need_dst_buf = 1; -+ } -+ -+ if (need_src_buf) { -+ rate->src_conv_idx = -+ snd_pcm_linear_convert_index(rate->orig_in_format, -+ rate->info.in.format); -+ rate->src_buf = rate_alloc_tmp_buf(rate, rate->info.in.format, -+ channels, rate->info.in.period_size); -+ if (!rate->src_buf) { -+ err = -ENOMEM; - goto error; -+ } -+ } -+ -+ if (need_dst_buf) { -+ rate->dst_conv_idx = -+ snd_pcm_linear_convert_index(rate->info.out.format, -+ rate->orig_out_format); -+ rate->dst_buf = rate_alloc_tmp_buf(rate, rate->info.out.format, -+ channels, rate->info.out.period_size); -+ if (!rate->dst_buf) { -+ err = -ENOMEM; -+ goto error; -+ } - } - - return 0; - - error: -- rate_free_tmp_buf(&rate->pareas); -- rate_free_tmp_buf(&rate->sareas); -+ rate_free_tmp_buf(&rate->src_buf); -+ rate_free_tmp_buf(&rate->dst_buf); -+ error_init: - if (rate->ops.free) - rate->ops.free(rate->obj); -- return -ENOMEM; -+ error_pareas: -+ rate_free_tmp_buf(&rate->pareas); -+ rate_free_tmp_buf(&rate->sareas); -+ return err; - } - - static int snd_pcm_rate_hw_free(snd_pcm_t *pcm) -@@ -361,9 +484,8 @@ static int snd_pcm_rate_hw_free(snd_pcm_t *pcm) - rate_free_tmp_buf(&rate->sareas); - if (rate->ops.free) - rate->ops.free(rate->obj); -- free(rate->src_buf); -- free(rate->dst_buf); -- rate->src_buf = rate->dst_buf = NULL; -+ rate_free_tmp_buf(&rate->src_buf); -+ rate_free_tmp_buf(&rate->dst_buf); - return snd_pcm_hw_free(rate->gen.slave); - } - -@@ -444,82 +566,6 @@ static int snd_pcm_rate_init(snd_pcm_t *pcm) - return 0; - } - --static void convert_to_s16(snd_pcm_rate_t *rate, int16_t *buf, -- const snd_pcm_channel_area_t *areas, -- snd_pcm_uframes_t offset, unsigned int frames, -- unsigned int channels) --{ --#ifndef DOC_HIDDEN --#define GET16_LABELS --#include "plugin_ops.h" --#undef GET16_LABELS --#endif /* DOC_HIDDEN */ -- void *get = get16_labels[rate->get_idx]; -- const char *src; -- int16_t sample; -- const char *srcs[channels]; -- int src_step[channels]; -- unsigned int c; -- -- for (c = 0; c < channels; c++) { -- srcs[c] = snd_pcm_channel_area_addr(areas + c, offset); -- src_step[c] = snd_pcm_channel_area_step(areas + c); -- } -- -- while (frames--) { -- for (c = 0; c < channels; c++) { -- src = srcs[c]; -- goto *get; --#ifndef DOC_HIDDEN --#define GET16_END after_get --#include "plugin_ops.h" --#undef GET16_END --#endif /* DOC_HIDDEN */ -- after_get: -- *buf++ = sample; -- srcs[c] += src_step[c]; -- } -- } --} -- --static void convert_from_s16(snd_pcm_rate_t *rate, const int16_t *buf, -- const snd_pcm_channel_area_t *areas, -- snd_pcm_uframes_t offset, unsigned int frames, -- unsigned int channels) --{ --#ifndef DOC_HIDDEN --#define PUT16_LABELS --#include "plugin_ops.h" --#undef PUT16_LABELS --#endif /* DOC_HIDDEN */ -- void *put = put16_labels[rate->put_idx]; -- char *dst; -- int16_t sample; -- char *dsts[channels]; -- int dst_step[channels]; -- unsigned int c; -- -- for (c = 0; c < channels; c++) { -- dsts[c] = snd_pcm_channel_area_addr(areas + c, offset); -- dst_step[c] = snd_pcm_channel_area_step(areas + c); -- } -- -- while (frames--) { -- for (c = 0; c < channels; c++) { -- dst = dsts[c]; -- sample = *buf++; -- goto *put; --#ifndef DOC_HIDDEN --#define PUT16_END after_put --#include "plugin_ops.h" --#undef PUT16_END --#endif /* DOC_HIDDEN */ -- after_put: -- dsts[c] += dst_step[c]; -- } -- } --} -- - static void do_convert(const snd_pcm_channel_area_t *dst_areas, - snd_pcm_uframes_t dst_offset, unsigned int dst_frames, - const snd_pcm_channel_area_t *src_areas, -@@ -527,28 +573,40 @@ static void do_convert(const snd_pcm_channel_area_t *dst_areas, - unsigned int channels, - snd_pcm_rate_t *rate) - { -- if (rate->ops.convert_s16) { -- const int16_t *src; -- int16_t *dst; -- if (! rate->src_buf) -- src = (int16_t *)src_areas->addr + src_offset * channels; -- else { -- convert_to_s16(rate, rate->src_buf, src_areas, src_offset, -- src_frames, channels); -- src = rate->src_buf; -- } -- if (! rate->dst_buf) -- dst = (int16_t *)dst_areas->addr + dst_offset * channels; -- else -- dst = rate->dst_buf; -- rate->ops.convert_s16(rate->obj, dst, dst_frames, src, src_frames); -- if (dst == rate->dst_buf) -- convert_from_s16(rate, rate->dst_buf, dst_areas, dst_offset, -- dst_frames, channels); -+ const snd_pcm_channel_area_t *out_areas; -+ snd_pcm_uframes_t out_offset; -+ -+ if (rate->dst_buf) { -+ out_areas = rate->dst_buf; -+ out_offset = 0; - } else { -- rate->ops.convert(rate->obj, dst_areas, dst_offset, dst_frames, -- src_areas, src_offset, src_frames); -+ out_areas = dst_areas; -+ out_offset = dst_offset; -+ } -+ -+ if (rate->src_buf) { -+ snd_pcm_linear_convert(rate->src_buf, 0, -+ src_areas, src_offset, -+ channels, src_frames, -+ rate->src_conv_idx); -+ src_areas = rate->src_buf; -+ src_offset = 0; - } -+ -+ if (rate->ops.convert) -+ rate->ops.convert(rate->obj, out_areas, out_offset, dst_frames, -+ src_areas, src_offset, src_frames); -+ else -+ rate->ops.convert_s16(rate->obj, -+ snd_pcm_channel_area_addr(out_areas, out_offset), -+ dst_frames, -+ snd_pcm_channel_area_addr(src_areas, src_offset), -+ src_frames); -+ if (rate->dst_buf) -+ snd_pcm_linear_convert(dst_areas, dst_offset, -+ rate->dst_buf, 0, -+ channels, dst_frames, -+ rate->dst_conv_idx); - } - - static inline void -@@ -1276,6 +1334,30 @@ const snd_config_t *snd_pcm_rate_get_default_converter(snd_config_t *root) - return NULL; - } - -+static void rate_initial_setup(snd_pcm_rate_t *rate) -+{ -+ if (rate->plugin_version == SND_PCM_RATE_PLUGIN_VERSION) -+ rate->plugin_version = rate->ops.version; -+ -+ if (rate->plugin_version >= 0x010002 && -+ rate->ops.get_supported_rates) -+ rate->ops.get_supported_rates(rate->obj, -+ &rate->rate_min, -+ &rate->rate_max); -+ -+ if (rate->plugin_version >= 0x010003 && -+ rate->ops.get_supported_formats) { -+ rate->ops.get_supported_formats(rate->obj, -+ &rate->in_formats, -+ &rate->out_formats, -+ &rate->format_flags); -+ } else if (!rate->ops.convert && rate->ops.convert_s16) { -+ rate->in_formats = rate->out_formats = -+ 1ULL << SND_PCM_FORMAT_S16; -+ rate->format_flags = SND_PCM_RATE_FLAG_INTERLEAVED; -+ } -+} -+ - #ifdef PIC - static int is_builtin_plugin(const char *type) - { -@@ -1301,20 +1383,11 @@ static int rate_open_func(snd_pcm_rate_t *rate, const char *type, const snd_conf - lib = lib_name; - } - -- rate->rate_min = SND_PCM_PLUGIN_RATE_MIN; -- rate->rate_max = SND_PCM_PLUGIN_RATE_MAX; -- rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION; -- - open_conf_func = snd_dlobj_cache_get(lib, open_conf_name, NULL, verbose && converter_conf != NULL); - if (open_conf_func) { - err = open_conf_func(SND_PCM_RATE_PLUGIN_VERSION, - &rate->obj, &rate->ops, converter_conf); - if (!err) { -- rate->plugin_version = rate->ops.version; -- if (rate->ops.get_supported_rates) -- rate->ops.get_supported_rates(rate->obj, -- &rate->rate_min, -- &rate->rate_max); - rate->open_func = open_conf_func; - return 0; - } else { -@@ -1330,23 +1403,18 @@ static int rate_open_func(snd_pcm_rate_t *rate, const char *type, const snd_conf - rate->open_func = open_func; - - err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops); -- if (!err) { -- rate->plugin_version = rate->ops.version; -- if (rate->ops.get_supported_rates) -- rate->ops.get_supported_rates(rate->obj, -- &rate->rate_min, -- &rate->rate_max); -+ if (!err) - return 0; -- } - - /* try to open with the old protocol version */ - rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION_OLD; - err = open_func(SND_PCM_RATE_PLUGIN_VERSION_OLD, - &rate->obj, &rate->ops); -- if (err) { -- snd_dlobj_cache_put(open_func); -- rate->open_func = NULL; -- } -+ if (!err) -+ return 0; -+ -+ snd_dlobj_cache_put(open_func); -+ rate->open_func = NULL; - return err; - } - #endif -@@ -1417,6 +1485,10 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, - rate->srate = srate; - rate->sformat = sformat; - -+ rate->rate_min = SND_PCM_PLUGIN_RATE_MIN; -+ rate->rate_max = SND_PCM_PLUGIN_RATE_MAX; -+ rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION; -+ - err = snd_pcm_new(&pcm, SND_PCM_TYPE_RATE, name, slave->stream, slave->mode); - if (err < 0) { - free(rate); -@@ -1496,6 +1568,8 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, - return err; - } - -+ rate_initial_setup(rate); -+ - pcm->ops = &snd_pcm_rate_ops; - pcm->fast_ops = &snd_pcm_rate_fast_ops; - pcm->private_data = rate; --- -2.31.1 - - -From 3f737a2a2c8d20e78dea3ea836997f9d74f602a0 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 18 Jun 2021 11:35:30 +0200 -Subject: [PATCH 04/20] pcm: improve docs for snd_pcm_sw_params_get_avail_min() - and snd_pcm_status_get_avail_max() - -Fixes: https://github.com/alsa-project/alsa-lib/issues/44 -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c -index 09df0f12..892abf98 100644 ---- a/src/pcm/pcm.c -+++ b/src/pcm/pcm.c -@@ -6500,6 +6500,9 @@ int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, - * \param params Software configuration container - * \param val returned minimum available frames to consider PCM ready - * \return 0 otherwise a negative error code -+ * -+ * This is a threshold value when the PCM stream is considered as ready for -+ * another read/write operation or poll event. - */ - #ifndef DOXYGEN - EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_avail_min)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val) -@@ -6960,6 +6963,8 @@ snd_pcm_uframes_t snd_pcm_status_get_avail(const snd_pcm_status_t *obj) - /** - * \brief Get maximum number of frames available from a PCM status container after last #snd_pcm_status call - * \return Maximum number of frames ready to be read/written -+ * -+ * This value returns the peak for the available frames between #snd_pcm_status calls. - */ - snd_pcm_uframes_t snd_pcm_status_get_avail_max(const snd_pcm_status_t *obj) - { --- -2.31.1 - - -From 212c6c18c4317af48c007a0866efc029b9c3a593 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Mon, 21 Jun 2021 09:23:02 +0200 -Subject: [PATCH 05/20] pcm: dmix - use pcm_frame_diff() in - snd_pcm_dmix_sync_ptr0() - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dmix.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index 608593f1..0d0d0bff 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -393,17 +393,13 @@ static int snd_pcm_dmix_sync_ptr0(snd_pcm_t *pcm, snd_pcm_uframes_t slave_hw_ptr - - old_slave_hw_ptr = dmix->slave_hw_ptr; - dmix->slave_hw_ptr = slave_hw_ptr; -- diff = slave_hw_ptr - old_slave_hw_ptr; -+ diff = pcm_frame_diff(slave_hw_ptr, old_slave_hw_ptr, dmix->slave_boundary); - if (diff == 0) /* fast path */ - return 0; - if (dmix->state != SND_PCM_STATE_RUNNING && - dmix->state != SND_PCM_STATE_DRAINING) - /* not really started yet - don't update hw_ptr */ - return 0; -- if (diff < 0) { -- slave_hw_ptr += dmix->slave_boundary; -- diff = slave_hw_ptr - old_slave_hw_ptr; -- } - dmix->hw_ptr += diff; - dmix->hw_ptr %= pcm->boundary; - if (pcm->stop_threshold >= pcm->boundary) /* don't care */ --- -2.31.1 - - -From dd609ef9684987d3ca61d5c5cc3c77589ff9c29f Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Mon, 21 Jun 2021 09:28:41 +0200 -Subject: [PATCH 06/20] pcm: direct plugins - fix hw_ptr in the status callback - -The parent hw_ptr may be in another range (boundary limit). -Set the correct value for the caller. - -BugLink: https://github.com/alsa-project/alsa-lib/issues/155 -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_dmix.c | 1 + - src/pcm/pcm_dshare.c | 1 + - src/pcm/pcm_dsnoop.c | 1 + - 3 files changed, 3 insertions(+) - -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index 0d0d0bff..94dbb1e0 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -491,6 +491,7 @@ static int snd_pcm_dmix_status(snd_pcm_t *pcm, snd_pcm_status_t * status) - } - - status->state = snd_pcm_dmix_state(pcm); -+ status->hw_ptr = *pcm->hw.ptr; /* boundary may be different */ - status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */ - status->trigger_tstamp = dmix->trigger_tstamp; - status->avail = snd_pcm_mmap_playback_avail(pcm); -diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c -index a918512b..01814dc8 100644 ---- a/src/pcm/pcm_dshare.c -+++ b/src/pcm/pcm_dshare.c -@@ -243,6 +243,7 @@ static int snd_pcm_dshare_status(snd_pcm_t *pcm, snd_pcm_status_t * status) - break; - } - status->state = snd_pcm_dshare_state(pcm); -+ status->hw_ptr = *pcm->hw.ptr; /* boundary may be different */ - status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */ - status->trigger_tstamp = dshare->trigger_tstamp; - status->avail = snd_pcm_mmap_playback_avail(pcm); -diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c -index 2c3b9f43..3f28df99 100644 ---- a/src/pcm/pcm_dsnoop.c -+++ b/src/pcm/pcm_dsnoop.c -@@ -193,6 +193,7 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status) - snd_pcm_status(dsnoop->spcm, status); - state = snd_pcm_state(dsnoop->spcm); - status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state; -+ status->hw_ptr = *pcm->hw.ptr; /* boundary may be different */ - status->appl_ptr = *pcm->appl.ptr; /* slave PCM doesn't set appl_ptr */ - status->trigger_tstamp = dsnoop->trigger_tstamp; - status->avail = snd_pcm_mmap_capture_avail(pcm); --- -2.31.1 - - -From a5e11f9a810391777ea7750f04ba66f9c9e624de Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Mon, 21 Jun 2021 14:21:26 +0200 -Subject: [PATCH 07/20] pcm: Move snd_pcm_channel_area_addr() and _step() to - public header - -Used in the rate plugins commonly. - -Signed-off-by: Takashi Iwai ---- - include/pcm.h | 23 +++++++++++++++++++++++ - src/pcm/pcm_local.h | 13 ------------- - 2 files changed, 23 insertions(+), 13 deletions(-) - -diff --git a/include/pcm.h b/include/pcm.h -index e300b951..b5a514fa 100644 ---- a/include/pcm.h -+++ b/include/pcm.h -@@ -1173,6 +1173,29 @@ int snd_pcm_areas_copy_wrap(const snd_pcm_channel_area_t *dst_channels, - snd_pcm_uframes_t frames, - const snd_pcm_format_t format); - -+/** -+ * \brief get the address of the given PCM channel area -+ * \param area PCM channel area -+ * \param offset Offset in frames -+ * -+ * Returns the pointer corresponding to the given offset on the channel area. -+ */ -+static inline void *snd_pcm_channel_area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset) -+{ -+ return (char *)area->addr + (area->first + area->step * offset) / 8; -+} -+ -+/** -+ * \brief get the step size of the given PCM channel area in bytes -+ * \param area PCM channel area -+ * -+ * Returns the step size in bytes from the given channel area. -+ */ -+static inline unsigned int snd_pcm_channel_area_step(const snd_pcm_channel_area_t *area) -+{ -+ return area->step / 8; -+} -+ - /** \} */ - - /** -diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h -index a63f4be0..6f03365c 100644 ---- a/src/pcm/pcm_local.h -+++ b/src/pcm/pcm_local.h -@@ -632,19 +632,6 @@ static inline snd_pcm_sframes_t snd_pcm_mmap_delay(snd_pcm_t *pcm) - return snd_pcm_mmap_capture_delay(pcm); - } - --static inline void *snd_pcm_channel_area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset) --{ -- unsigned int bitofs = area->first + area->step * offset; -- assert(bitofs % 8 == 0); -- return (char *) area->addr + bitofs / 8; --} -- --static inline unsigned int snd_pcm_channel_area_step(const snd_pcm_channel_area_t *area) --{ -- assert(area->step % 8 == 0); -- return area->step / 8; --} -- - static inline snd_pcm_sframes_t _snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) - { - /* lock handled in the callback */ --- -2.31.1 - - -From e0e084659083c2ab75d5c894f24227ea2f67010f Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Mon, 21 Jun 2021 15:14:18 +0200 -Subject: [PATCH 08/20] pcm: direct plugins - fix bad memory access when - channel bindings do not match hw - -Fix and cleanup snd_pcm_direct_check_interleave() function. -Add requested / hardware channel check and use goto when the interleaved - -Fixes: https://github.com/alsa-project/alsa-lib/issues/117 -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_direct.c | 40 +++++++++++++++++----------------------- - 1 file changed, 17 insertions(+), 23 deletions(-) - -diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c -index d50503e3..90417b2f 100644 ---- a/src/pcm/pcm_direct.c -+++ b/src/pcm/pcm_direct.c -@@ -1627,43 +1627,37 @@ int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix) - int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm) - { - unsigned int chn, channels; -- int bits, interleaved = 1; -+ int bits; - const snd_pcm_channel_area_t *dst_areas; - const snd_pcm_channel_area_t *src_areas; - - bits = snd_pcm_format_physical_width(pcm->format); - if ((bits % 8) != 0) -- interleaved = 0; -+ goto __nointerleaved; - channels = dmix->channels; -+ if (channels != dmix->spcm->channels) -+ goto __nointerleaved; - dst_areas = snd_pcm_mmap_areas(dmix->spcm); - src_areas = snd_pcm_mmap_areas(pcm); - for (chn = 1; chn < channels; chn++) { -- if (dst_areas[chn-1].addr != dst_areas[chn].addr) { -- interleaved = 0; -- break; -- } -- if (src_areas[chn-1].addr != src_areas[chn].addr) { -- interleaved = 0; -- break; -- } -+ if (dst_areas[chn-1].addr != dst_areas[chn].addr) -+ goto __nointerleaved; -+ if (src_areas[chn-1].addr != src_areas[chn].addr) -+ goto __nointerleaved; - } - for (chn = 0; chn < channels; chn++) { -- if (dmix->bindings && dmix->bindings[chn] != chn) { -- interleaved = 0; -- break; -- } -+ if (dmix->bindings && dmix->bindings[chn] != chn) -+ goto __nointerleaved; - if (dst_areas[chn].first != chn * bits || -- dst_areas[chn].step != channels * bits) { -- interleaved = 0; -- break; -- } -+ dst_areas[chn].step != channels * bits) -+ goto __nointerleaved; - if (src_areas[chn].first != chn * bits || -- src_areas[chn].step != channels * bits) { -- interleaved = 0; -- break; -- } -+ src_areas[chn].step != channels * bits) -+ goto __nointerleaved; - } -- return dmix->interleaved = interleaved; -+ return dmix->interleaved = 1; -+__nointerleaved: -+ return dmix->interleaved = 0; - } - - /* --- -2.31.1 - - -From ccc14ae897d170156f1c2905ea5d18a3295e7b36 Mon Sep 17 00:00:00 2001 -From: "Tanjeff-N. Moos" -Date: Thu, 17 Jun 2021 10:36:38 +0200 -Subject: [PATCH 09/20] control: Add documentation for snd_ctl_card_* and - friends. - -In this patch series, I added a description about control interface -handling and how control interfaces are identified. - -In addition, I added/improved Doxygen documentation for the -snd_ctl_card_info_t type and related corresponding functions, -e.g. snd_ctl_card_info(). I also documented other card-related like -snd_card_next(). - -Along the way I did minor documentation improvements. - -Signed-off-by: Tanjeff-N. Moos -Signed-off-by: Takashi Iwai ---- - include/control.h | 40 +++++++++- - src/control/cards.c | 56 +++++++++----- - src/control/control.c | 175 +++++++++++++++++++++++++++++++----------- - 3 files changed, 202 insertions(+), 69 deletions(-) - -diff --git a/include/control.h b/include/control.h -index ccf906e2..9ebb4905 100644 ---- a/include/control.h -+++ b/include/control.h -@@ -50,7 +50,32 @@ typedef struct snd_aes_iec958 { - unsigned char dig_subframe[4]; /**< AES/IEC958 subframe bits */ - } snd_aes_iec958_t; - --/** CTL card info container */ -+/** \brief CTL card info container. -+ * -+ * This type contains meta information about a sound card, such as the index, -+ * name, longname, etc. -+ * -+ * \par Memory management -+ * -+ * Before using a snd_ctl_card_info_t object, it must be allocated using -+ * snd_ctl_card_info_alloca() or snd_ctl_card_info_malloc(). When using the -+ * latter, it must be freed again using snd_ctl_card_info_free(). -+ * -+ * A card info object can be zeroed out using snd_ctl_card_info_clear(). -+ * -+ * A card info object can be copied to another one using -+ * snd_ctl_card_info_copy(). -+ * -+ * \par Obtaining the Information -+ * -+ * To obtain the card information, it must first be opened using -+ * snd_ctl_open(), and a snd_ctl_card_info_t container must be -+ * allocated. Then, the information can be read using -+ * snd_ctl_card_info_get_card(). -+ * -+ * Thereafter, the card properties can be read using the -+ * snd_ctl_card_info_get_*() functions. -+ */ - typedef struct _snd_ctl_card_info snd_ctl_card_info_t; - - /** CTL element identifier container */ -@@ -442,11 +467,20 @@ void snd_ctl_elem_id_set_name(snd_ctl_elem_id_t *obj, const char *val); - void snd_ctl_elem_id_set_index(snd_ctl_elem_id_t *obj, unsigned int val); - - size_t snd_ctl_card_info_sizeof(void); -+ - /** \hideinitializer -- * \brief allocate an invalid #snd_ctl_card_info_t using standard alloca -- * \param ptr returned pointer -+ * \brief Allocate an invalid #snd_ctl_card_info_t on the stack. -+ * -+ * Allocate space for a card info object on the stack. The allocated -+ * memory need not be freed, because it is on the stack. -+ * -+ * See snd_ctl_card_info_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_card_info_alloca(ptr) __snd_alloca(ptr, snd_ctl_card_info) -+ - int snd_ctl_card_info_malloc(snd_ctl_card_info_t **ptr); - void snd_ctl_card_info_free(snd_ctl_card_info_t *obj); - void snd_ctl_card_info_clear(snd_ctl_card_info_t *obj); -diff --git a/src/control/cards.c b/src/control/cards.c -index e57457c2..8226c42d 100644 ---- a/src/control/cards.c -+++ b/src/control/cards.c -@@ -77,8 +77,8 @@ static int snd_card_load1(int card) - - /** - * \brief Try to load the driver for a card. -- * \param card Card number. -- * \return 1 if driver is present, zero if driver is not present -+ * \param card Card index. -+ * \return 1 if driver is present, zero if driver is not present. - */ - int snd_card_load(int card) - { -@@ -86,14 +86,24 @@ int snd_card_load(int card) - } - - /** -- * \brief Try to determine the next card. -- * \param rcard pointer to card number -- * \result zero if success, otherwise a negative error code -+ * \brief Iterate over physical sound cards. -+ * -+ * This function takes the index of a physical sound card and sets it to the -+ * index of the next card. If index is -1, it is set to the index of the first -+ * card. After the last card, the index is set to -1. -+ * -+ * For example, if you have 2 sound cards (with index 0 and 1), the index will -+ * be modified as follows: -+ * -+ * - -1 --> 0 -+ * - 0 --> 1 -+ * - 1 --> -1 -+ * -+ * This does not work for virtual sound cards. - * -- * Tries to determine the next card from given card number. -- * If card number is -1, then the first available card is -- * returned. If the result card number is -1, no more cards -- * are available. -+ * \param rcard Index of current card. The index of the next card is stored -+ * here. -+ * \result zero if success, otherwise a negative error code. - */ - int snd_card_next(int *rcard) - { -@@ -114,13 +124,18 @@ int snd_card_next(int *rcard) - } - - /** -- * \brief Convert card string to an integer value. -- * \param string String containing card identifier -- * \return zero if success, otherwise a negative error code -+ * \brief Convert a card string to the card index. - * -- * The accepted format is an integer value in ASCII representation -- * or the card identifier (the id parameter for sound-card drivers). -- * The control device name like /dev/snd/controlC0 is accepted, too. -+ * This works only for physical sound cards, not for virtual cards. -+ * -+ * \param string A string identifying the card. -+ * \return The index of the card. On error, a a negative error code -+ * is returned. -+ * -+ * The accepted formats for "string" are: -+ * - The index of the card (as listed in /proc/asound/cards), given as string -+ * - The ID of the card (as listed in /proc/asound/cards) -+ * - The control device name (like /dev/snd/controlC0) - */ - int snd_card_get_index(const char *string) - { -@@ -163,8 +178,9 @@ int snd_card_get_index(const char *string) - - /** - * \brief Obtain the card name. -- * \param card Card number -- * \param name Result - card name corresponding to card number -+ * -+ * \param card The index of the card. -+ * \param name Result - card name corresponding to card index. - * \result zero if success, otherwise a negative error code - * - * The value returned in name is allocated with strdup and should be -@@ -193,9 +209,9 @@ int snd_card_get_name(int card, char **name) - - /** - * \brief Obtain the card long name. -- * \param card Card number -- * \param name Result - card long name corresponding to card number -- * \result zero if success, otherwise a negative error code -+ * \param card Index of the card. -+ * \param name Result - card long name corresponding to card index. -+ * \result Zero if success, otherwise a negative error code. - * - * The value returned in name is allocated with strdup and should be - * freed when no longer used. -diff --git a/src/control/control.c b/src/control/control.c -index ed986e54..7cf4decb 100644 ---- a/src/control/control.c -+++ b/src/control/control.c -@@ -33,8 +33,50 @@ -

Control interface is designed to access primitive controls. There is - also an interface for notifying about control and structure changes. - -+ - \section control_general_overview General overview - -+In Alsa, there are physical sound cards, such as USB headsets, and -+virtual sound cards, such as "pulse", which represents the PulseAudio -+Sound system. Each sound card offers a control interface, making its -+settings (e.g. volume knobs) available. The complete list of available -+control interfaces can be obtained using snd_device_name_hint(), -+giving -1 as card index and "ctl" as interface type. Each returned -+NAME hint identifies a control interface. -+ -+Sound cards have an ID (a string), an index (an int, sometimes called -+the "card number"), a name, a longname, a mixername and a "components" -+property. The file /proc/asound/cards lists most of these properties -+for physical sound cards. Virtual sound cards are not listed in that -+file. The format is: -+ -+\verbatim -+index [ID ] Driver - name -+ longname -+\endverbatim -+ -+Note that the mixername and components are not listed. -+ -+ -+\subsection control_cards_id Identifying and Opening Control Interfaces -+ -+To work with a control interface, is must be opened first, using -+snd_ctl_open(). This function takes the interface name. -+ -+For physical sound cards, the control interface can be identified -+using the string "hw:" (e.g. `hw:2`). The NAME hint - which is -+"hw:CARD=" - can also be used. Further, its device file (something -+like `/dev/snd/controlC0`) is also acceptable. Either of them can be -+given to snd_ctl_open(). -+ -+For virtual sound cards, the NAME hint is given to snd_ctl_open(). -+ -+The functions snd_card_get_index(), snd_card_get_name() and -+snd_card_get_longname() can be used to find an identifying property -+when another one is already known. -+ -+\section control_elements Elements -+ - In ALSA control feature, each sound card can have control elements. The elements - are managed according to below model. - -@@ -65,7 +107,7 @@ are managed according to below model. - of userspace applications and drivers in kernel. - - --\section identifying_elements Identifying Elements -+\subsection identifying_elements Identifying Elements - - Each element has the following identifying properties: - -@@ -84,7 +126,7 @@ 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. The short numid is used to reduce the lookup time. - --\section element_lists Element Lists -+\subsection 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 -@@ -93,7 +135,7 @@ elements the card has), and the identifying properties of the elements - element lists. - - --\section working_with_elements Working with Elements -+\subsection 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 -@@ -108,7 +150,7 @@ 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 -+\subsection 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 -@@ -329,10 +371,15 @@ int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe) - - - /** -- * \brief Get card related information -- * \param ctl CTL handle -- * \param info Card info pointer -- * \return 0 on success otherwise a negative error code -+ * \brief Get information about the sound card. -+ * -+ * Obtain information about the sound card previously opened using -+ * snd_ctl_open(). The object "info" must be allocated prior to calling this -+ * function. See snd_ctl_card_info_t for details. -+ * -+ * \param ctl The CTL handle. -+ * \param info The card information is stored here. -+ * \return 0 on success, otherwise a negative error code. - */ - int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info) - { -@@ -1508,11 +1555,13 @@ int _snd_ctl_open_named_child(snd_ctl_t **pctl, const char *name, - #endif - - /** -- * \brief Opens a CTL -- * \param ctlp Returned CTL handle -- * \param name ASCII identifier of the CTL handle -- * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC) -- * \return 0 on success otherwise a negative error code -+ * \brief Opens a sound card. -+ * -+ * \param ctlp Returned CTL handle. -+ * \param name A string identifying the card (See \ref control_cards_id). -+ * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC). -+ * -+ * \return 0 on success otherwise a negative error code. - */ - int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode) - { -@@ -2027,8 +2076,8 @@ void snd_ctl_elem_id_set_index(snd_ctl_elem_id_t *obj, unsigned int val) - } - - /** -- * \brief get size of #snd_ctl_card_info_t -- * \return size in bytes -+ * \brief get size of #snd_ctl_card_info_t. -+ * \return Size in bytes. - */ - size_t snd_ctl_card_info_sizeof() - { -@@ -2036,9 +2085,16 @@ size_t snd_ctl_card_info_sizeof() - } - - /** -- * \brief allocate an invalid #snd_ctl_card_info_t using standard malloc -- * \param ptr returned pointer -- * \return 0 on success otherwise negative error code -+ * \brief Allocate an invalid #snd_ctl_card_info_t on the heap. -+ * -+ * Allocate space for a card info object on the heap. The allocated memory -+ * must be freed using snd_ctl_card_info_free(). -+ * -+ * See snd_ctl_card_info_t for details. -+ * -+ * \param ptr Pointer to a snd_ctl_card_info_t pointer. The address -+ * of the allocated space will be returned here. -+ * \return 0 on success, otherwise a negative error code. - */ - int snd_ctl_card_info_malloc(snd_ctl_card_info_t **ptr) - { -@@ -2050,8 +2106,10 @@ int snd_ctl_card_info_malloc(snd_ctl_card_info_t **ptr) - } - - /** -- * \brief frees a previously allocated #snd_ctl_card_info_t -- * \param obj pointer to object to free -+ * \brief Free an #snd_ctl_card_info_t previously allocated using -+ * snd_ctl_card_info_malloc(). -+ * -+ * \param obj Pointer to the snd_ctl_card_info_t. - */ - void snd_ctl_card_info_free(snd_ctl_card_info_t *obj) - { -@@ -2059,8 +2117,11 @@ void snd_ctl_card_info_free(snd_ctl_card_info_t *obj) - } - - /** -- * \brief clear given #snd_ctl_card_info_t object -- * \param obj pointer to object to clear -+ * \brief Clear given card info object. -+ * -+ * See snd_ctl_elem_value_t for details. -+ * -+ * \param obj Card info object. - */ - void snd_ctl_card_info_clear(snd_ctl_card_info_t *obj) - { -@@ -2068,9 +2129,10 @@ void snd_ctl_card_info_clear(snd_ctl_card_info_t *obj) - } - - /** -- * \brief copy one #snd_ctl_card_info_t to another -- * \param dst pointer to destination -- * \param src pointer to source -+ * \brief Bitwise copy of a #snd_ctl_card_info_t object. -+ * -+ * \param dst Pointer to destination. -+ * \param src Pointer to source. - */ - void snd_ctl_card_info_copy(snd_ctl_card_info_t *dst, const snd_ctl_card_info_t *src) - { -@@ -2079,9 +2141,12 @@ void snd_ctl_card_info_copy(snd_ctl_card_info_t *dst, const snd_ctl_card_info_t - } - - /** -- * \brief Get card number from a CTL card info -- * \param obj CTL card info -- * \return card number -+ * \brief Get the sound card index from the given info object. -+ * -+ * See snd_ctl_card_info_t for more details. -+ * -+ * \param obj The card info object. -+ * \return Sound card index. - */ - int snd_ctl_card_info_get_card(const snd_ctl_card_info_t *obj) - { -@@ -2090,9 +2155,12 @@ int snd_ctl_card_info_get_card(const snd_ctl_card_info_t *obj) - } - - /** -- * \brief Get card identifier from a CTL card info -- * \param obj CTL card info -- * \return card identifier -+ * \brief Get the sound card ID from the given info object. -+ * -+ * See snd_ctl_card_info_t for more details. -+ * -+ * \param obj The card info object. -+ * \return Sound card ID. - */ - const char *snd_ctl_card_info_get_id(const snd_ctl_card_info_t *obj) - { -@@ -2101,9 +2169,12 @@ const char *snd_ctl_card_info_get_id(const snd_ctl_card_info_t *obj) - } - - /** -- * \brief Get card driver name from a CTL card info -- * \param obj CTL card info -- * \return card driver name -+ * \brief Get the sound card driver from the given info object. -+ * -+ * See snd_ctl_card_info_t for more details. -+ * -+ * \param obj The card info object. -+ * \return The sound card driver. - */ - const char *snd_ctl_card_info_get_driver(const snd_ctl_card_info_t *obj) - { -@@ -2112,9 +2183,12 @@ const char *snd_ctl_card_info_get_driver(const snd_ctl_card_info_t *obj) - } - - /** -- * \brief Get card name from a CTL card info -- * \param obj CTL card info -- * \return card name -+ * \brief Get the sound card name from the given info object. -+ * -+ * See snd_ctl_card_info_t for more details. -+ * -+ * \param obj The card info object. -+ * \return Sound card name. - */ - const char *snd_ctl_card_info_get_name(const snd_ctl_card_info_t *obj) - { -@@ -2123,9 +2197,12 @@ const char *snd_ctl_card_info_get_name(const snd_ctl_card_info_t *obj) - } - - /** -- * \brief Get card long name from a CTL card info -- * \param obj CTL card info -- * \return card long name -+ * \brief Get the sound cards long name from the given info object. -+ * -+ * See snd_ctl_card_info_t for more details. -+ * -+ * \param obj The card info object. -+ * \return Sound cards long name. - */ - const char *snd_ctl_card_info_get_longname(const snd_ctl_card_info_t *obj) - { -@@ -2134,9 +2211,12 @@ const char *snd_ctl_card_info_get_longname(const snd_ctl_card_info_t *obj) - } - - /** -- * \brief Get card mixer name from a CTL card info -- * \param obj CTL card info -- * \return card mixer name -+ * \brief Get the sound card mixer name from the given info object. -+ * -+ * See snd_ctl_card_info_t for more details. -+ * -+ * \param obj The card info object. -+ * \return Sound card mixer name. - */ - const char *snd_ctl_card_info_get_mixername(const snd_ctl_card_info_t *obj) - { -@@ -2145,9 +2225,12 @@ const char *snd_ctl_card_info_get_mixername(const snd_ctl_card_info_t *obj) - } - - /** -- * \brief Get card component list from a CTL card info -- * \param obj CTL card info -- * \return card mixer identifier -+ * \brief Get the sound cards "components" property from the given info object. -+ * -+ * See snd_ctl_card_info_t for more details. -+ * -+ * \param obj The card info object. -+ * \return Sound cards "components" property. - */ - const char *snd_ctl_card_info_get_components(const snd_ctl_card_info_t *obj) - { --- -2.31.1 - - -From 7ba3f888d07cafbad04391b915db23408c663dad Mon Sep 17 00:00:00 2001 -From: "Tanjeff-N. Moos" -Date: Thu, 17 Jun 2021 10:36:39 +0200 -Subject: [PATCH 10/20] control: Minor documentation fixes. - -Signed-off-by: Tanjeff-N. Moos -Signed-off-by: Takashi Iwai ---- - include/control.h | 9 +++++++-- - src/control/cards.c | 5 ++++- - src/control/control.c | 2 +- - 3 files changed, 12 insertions(+), 4 deletions(-) - -diff --git a/include/control.h b/include/control.h -index 9ebb4905..e386ecec 100644 ---- a/include/control.h -+++ b/include/control.h -@@ -155,7 +155,7 @@ 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. -@@ -167,6 +167,11 @@ typedef struct _snd_ctl_elem_info snd_ctl_elem_info_t; - * using the latter, it must be freed again using - * snd_ctl_elem_value_free(). - * -+ * A value object can be zeroed out using snd_ctl_elem_value_clear(). -+ * -+ * A value object can be copied to another one using -+ * snd_ctl_elem_value_copy(). -+ * - * \par Identifier - * - * Then, the ID must be filled. It is sufficient to fill only the -@@ -621,7 +626,7 @@ size_t snd_ctl_elem_value_sizeof(void); - * \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. -+ * memory need not be freed, because it is on the stack. - * - * See snd_ctl_elem_value_t for details. - * -diff --git a/src/control/cards.c b/src/control/cards.c -index 8226c42d..6145ebcd 100644 ---- a/src/control/cards.c -+++ b/src/control/cards.c -@@ -147,6 +147,7 @@ int snd_card_get_index(const char *string) - return -EINVAL; - if ((isdigit(*string) && *(string + 1) == 0) || - (isdigit(*string) && isdigit(*(string + 1)) && *(string + 2) == 0)) { -+ /* We got an index */ - if (sscanf(string, "%i", &card) != 1) - return -EINVAL; - if (card < 0 || card >= SND_MAX_CARDS) -@@ -156,8 +157,10 @@ int snd_card_get_index(const char *string) - return card; - return err; - } -- if (string[0] == '/') /* device name */ -+ if (string[0] == '/') -+ /* We got a device name */ - return snd_card_load2(string); -+ /* We got in ID */ - for (card = 0; card < SND_MAX_CARDS; card++) { - #ifdef SUPPORT_ALOAD - if (! snd_card_load(card)) -diff --git a/src/control/control.c b/src/control/control.c -index 7cf4decb..91415b51 100644 ---- a/src/control/control.c -+++ b/src/control/control.c -@@ -3127,7 +3127,7 @@ size_t snd_ctl_elem_value_sizeof() - /** - * \brief Allocate an invalid #snd_ctl_elem_value_t on the heap. - * -- * Allocate space for a value object on the head. The allocated memory -+ * Allocate space for a value object on the heap. The allocated memory - * must be freed using snd_ctl_elem_value_free(). - * - * See snd_ctl_elem_value_t for details. --- -2.31.1 - - -From f4f29d42be8b8ad60ea4c5697374adad4bfe6868 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Mon, 28 Jun 2021 12:08:53 +0200 -Subject: [PATCH 11/20] fix build with --disable-ucm - -Link: https://mailman.alsa-project.org/pipermail/alsa-devel/2021-June/186729.html -Reported-by: Michael Forney -Signed-off-by: Jaroslav Kysela ---- - include/local.h | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/include/local.h b/include/local.h -index 4e7d88a0..7cfcec53 100644 ---- a/include/local.h -+++ b/include/local.h -@@ -374,6 +374,8 @@ int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in, - void *INTERNAL(snd_dlopen)(const char *name, int mode, char *errbuf, size_t errbuflen); - #endif - -+#ifdef BUILD_UCM -+ - const char *uc_mgr_alibcfg_by_device(snd_config_t **config, const char *name); - - static inline int _snd_is_ucm_device(const char *name) -@@ -381,4 +383,12 @@ static inline int _snd_is_ucm_device(const char *name) - return name && name[0] == '_' && name[1] == 'u' && name[2] == 'c' && name[3] == 'm'; - } - -+#else -+ -+static inline const char *uc_mgr_alibcfg_by_device(snd_config_t **config, const char *name) { return NULL; } -+static inline int _snd_is_ucm_device(const char *name) { return 0; } -+ -+ -+#endif -+ - #endif --- -2.31.1 - - -From 1a1f0fb244c477c430e156da878475ef57d198f9 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Mon, 28 Jun 2021 12:11:54 +0200 -Subject: [PATCH 12/20] pcm: rate - fix some gcc warnings - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_rate.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c -index 13111d29..c45895a9 100644 ---- a/src/pcm/pcm_rate.c -+++ b/src/pcm/pcm_rate.c -@@ -82,12 +82,12 @@ struct _snd_pcm_rate { - - /* allocate a channel area and a temporary buffer for the given size */ - static snd_pcm_channel_area_t * --rate_alloc_tmp_buf(snd_pcm_rate_t *rate, snd_pcm_format_t format, -+rate_alloc_tmp_buf(snd_pcm_format_t format, - unsigned int channels, unsigned int frames) - { - snd_pcm_channel_area_t *ap; - int width = snd_pcm_format_physical_width(format); -- int i; -+ unsigned int i; - - ap = malloc(sizeof(*ap) * channels); - if (!ap) -@@ -354,7 +354,7 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - snd_pcm_rate_t *rate = pcm->private_data; - snd_pcm_t *slave = rate->gen.slave; - snd_pcm_rate_side_info_t *sinfo, *cinfo; -- unsigned int channels, cwidth, swidth, chn, acc; -+ unsigned int channels, acc; - int need_src_buf, need_dst_buf; - int err = snd_pcm_hw_params_slave(pcm, params, - snd_pcm_rate_hw_refine_cchange, -@@ -401,9 +401,9 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - return -EBUSY; - } - -- rate->pareas = rate_alloc_tmp_buf(rate, cinfo->format, channels, -+ rate->pareas = rate_alloc_tmp_buf(cinfo->format, channels, - cinfo->period_size); -- rate->sareas = rate_alloc_tmp_buf(rate, sinfo->format, channels, -+ rate->sareas = rate_alloc_tmp_buf(sinfo->format, channels, - sinfo->period_size); - if (!rate->pareas || !rate->sareas) { - err = -ENOMEM; -@@ -442,7 +442,7 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - rate->src_conv_idx = - snd_pcm_linear_convert_index(rate->orig_in_format, - rate->info.in.format); -- rate->src_buf = rate_alloc_tmp_buf(rate, rate->info.in.format, -+ rate->src_buf = rate_alloc_tmp_buf(rate->info.in.format, - channels, rate->info.in.period_size); - if (!rate->src_buf) { - err = -ENOMEM; -@@ -454,7 +454,7 @@ static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - rate->dst_conv_idx = - snd_pcm_linear_convert_index(rate->info.out.format, - rate->orig_out_format); -- rate->dst_buf = rate_alloc_tmp_buf(rate, rate->info.out.format, -+ rate->dst_buf = rate_alloc_tmp_buf(rate->info.out.format, - channels, rate->info.out.period_size); - if (!rate->dst_buf) { - err = -ENOMEM; --- -2.31.1 - - -From e47c11822d6b459a9b3704b3ee6a4a5c9a1b85be Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Tue, 29 Jun 2021 18:02:27 +0200 -Subject: [PATCH 13/20] control: remap - assign right name to the child handle - for no-op - -Fixes: https://github.com/alsa-project/alsa-utils/issues/100 -Signed-off-by: Jaroslav Kysela ---- - src/control/control_remap.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/control/control_remap.c b/src/control/control_remap.c -index a85c1725..81524014 100644 ---- a/src/control/control_remap.c -+++ b/src/control/control_remap.c -@@ -1173,6 +1173,10 @@ int snd_ctl_remap_open(snd_ctl_t **handlep, const char *name, snd_config_t *rema - /* no-op check, remove the plugin */ - if (priv->map_items == 0 && priv->remap_items == 0) { - remap_free(priv); -+ free(child->name); -+ child->name = name ? strdup(name) : NULL; -+ if (name && !child->name) -+ return -ENOMEM; - *handlep = child; - return 0; - } --- -2.31.1 - - -From 23a191a82c693456e61431ab699cddc1e5782a26 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Tue, 29 Jun 2021 19:31:28 +0200 -Subject: [PATCH 14/20] control: remap - assign right name to the child handle - for no-op (2nd case) - -Fixes: https://github.com/alsa-project/alsa-utils/issues/100 -Signed-off-by: Jaroslav Kysela ---- - src/control/control_remap.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/control/control_remap.c b/src/control/control_remap.c -index 81524014..4914f960 100644 ---- a/src/control/control_remap.c -+++ b/src/control/control_remap.c -@@ -1154,6 +1154,10 @@ int snd_ctl_remap_open(snd_ctl_t **handlep, const char *name, snd_config_t *rema - snd_ctl_t *ctl; - int result, err; - -+ /* no-op, remove the plugin */ -+ if (!remap && !map) -+ goto _noop; -+ - priv = calloc(1, sizeof(*priv)); - if (priv == NULL) - return -ENOMEM; -@@ -1173,6 +1177,7 @@ int snd_ctl_remap_open(snd_ctl_t **handlep, const char *name, snd_config_t *rema - /* no-op check, remove the plugin */ - if (priv->map_items == 0 && priv->remap_items == 0) { - remap_free(priv); -+ _noop: - free(child->name); - child->name = name ? strdup(name) : NULL; - if (name && !child->name) -@@ -1316,11 +1321,6 @@ int _snd_ctl_remap_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd - err = _snd_ctl_open_child(&cctl, root, child, mode, conf); - if (err < 0) - return err; -- /* no-op, remove the plugin */ -- if (!remap && !map) { -- *handlep = cctl; -- return 0; -- } - err = snd_ctl_remap_open(handlep, name, remap, map, cctl, mode); - if (err < 0) - snd_ctl_close(cctl); --- -2.31.1 - - -From 7d40a76ef5494e08af00fa4e7bfefbd43aba4827 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Tue, 31 Aug 2021 09:25:12 +0200 -Subject: [PATCH 19/20] ucm: avoid zero card instance number - -Signed-off-by: Jaroslav Kysela ---- - src/ucm/utils.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/ucm/utils.c b/src/ucm/utils.c -index f3a8c9ba..10b21c34 100644 ---- a/src/ucm/utils.c -+++ b/src/ucm/utils.c -@@ -780,6 +780,9 @@ int uc_mgr_card_open(snd_use_case_mgr_t *uc_mgr) - while (uc_mgr_card_find(ucm_card_assign)) { - ucm_card_assign++; - ucm_card_assign &= 0xffff; -+ /* avoid zero card instance number */ -+ if (ucm_card_assign == 0) -+ ucm_card_assign++; - if (ucm_card_assign == prev) { - pthread_mutex_unlock(&ucm_cards_mutex); - return -ENOMEM; --- -2.31.1 - - -From 4a52ae4c329ae17117375a4b85b80f37994a4044 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Tue, 31 Aug 2021 09:40:42 +0200 -Subject: [PATCH 20/20] ucm: fix the parsing of the hexadecimal prefix - -The safe_strtol() function use strtol() which expects -to have the '0x' prefix for the hexadecimal number (when -base argument is zero). - -BugLink: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1553 -Signed-off-by: Jaroslav Kysela ---- - src/ucm/utils.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/src/ucm/utils.c b/src/ucm/utils.c -index 10b21c34..2fbc4c8c 100644 ---- a/src/ucm/utils.c -+++ b/src/ucm/utils.c -@@ -811,7 +811,7 @@ void uc_mgr_card_close(snd_use_case_mgr_t *uc_mgr) - */ - const char *uc_mgr_alibcfg_by_device(snd_config_t **top, const char *name) - { -- char buf[5]; -+ char buf[7]; - long card_num; - snd_config_t *config; - snd_use_case_mgr_t *uc_mgr; -@@ -819,8 +819,10 @@ const char *uc_mgr_alibcfg_by_device(snd_config_t **top, const char *name) - - if (strncmp(name, "_ucm", 4) || strlen(name) < 12 || name[8] != '.') - return NULL; -- strncpy(buf, name + 4, 4); -- buf[4] = '\0'; -+ buf[0] = '0'; -+ buf[1] = 'x'; -+ strncpy(buf + 2, name + 4, 4); -+ buf[6] = '\0'; - err = safe_strtol(buf, &card_num); - if (err < 0 || card_num < 0 || card_num > 0xffff) - return NULL; --- -2.31.1 - diff --git a/alsa-lib.spec b/alsa-lib.spec index 8ff5b53..50c4eff 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -2,14 +2,14 @@ #define prever_dot .rc3 #define postver a -%define version_alsa_lib 1.2.5.1 -%define version_alsa_ucm 1.2.5.1 +%define version_alsa_lib 1.2.6 +%define version_alsa_ucm 1.2.6 %define version_alsa_tplg 1.2.5 Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 2%{?prever_dot}%{?dist} +Release: 1%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,6 +167,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Mon Dec 6 2021 Jaroslav Kysela - 1.2.6-1 +- update to 1.2.6 + * Tue Aug 31 2021 Jaroslav Kysela - 1.2.5.1-2 - add UCM related fixes diff --git a/sources b/sources index ddf88ed..07eab63 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (alsa-lib-1.2.5.1.tar.bz2) = 01998ffa449e925ff552c13aea47f9540903afdc533086067c78dcaba4d239c347180d3d28bb0000e6d19b7779c7249fcc77a30057930ca22d18ba55e163fa1c +SHA512 (alsa-lib-1.2.6.tar.bz2) = ae95718813abf62811fe44c6df2a8de5a1227da4b022c4dd97dd8e7c1001f48307ba36bf04208bdbe24e8a8eebf4ed5a59f40ee6750dcbe976678071c3f2f5b7 +SHA512 (alsa-ucm-conf-1.2.6.tar.bz2) = 5fe85643b60c8defeafcdfcf97e61b5d05e6db28cef2466a70f63b8fffba22bdd50b83a5ca88806a6350de6e9d802dd3c2240b293190b9d05daea515c03d4397 SHA512 (alsa-topology-conf-1.2.5.tar.bz2) = 2eb4d8baf2dcbf0b631dd11dbf15bffc51694d9cc6931619e51787f3ba58d1a091d266e6721a3b737c040ec74a28270b93f39fb97f30a3227cf340dd646e5d51 -SHA512 (alsa-ucm-conf-1.2.5.1.tar.bz2) = 774d6da1a0ee6fb1fcd764c1d4b3eb5812a35508cf27db71f6c82784f125eca207992da9081d25783fecb31e548d8b34124d4b3b3d506e33215b76ea48f71012 From 6792944e7f82d082d031f08af67e96c748d6bf2c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 9 Dec 2021 10:26:39 +0100 Subject: [PATCH 06/10] device open fixes from upstream --- alsa-git.patch | 97 +++++++++++++++++++++++++++++++++++++++++++++ alsa-lib.spec | 5 ++- alsa-ucm-conf.patch | 28 +++++++++++++ 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/alsa-git.patch b/alsa-git.patch index e69de29..4082c0c 100644 --- a/alsa-git.patch +++ b/alsa-git.patch @@ -0,0 +1,97 @@ +From f44c94f24c2422c5ee1c4c58253ec17412b248a9 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 7 Dec 2021 09:21:24 +0100 +Subject: [PATCH 1/2] conf: accept '_' character in the variable name + +Fixes: https://github.com/alsa-project/alsa-lib/issues/197 +Signed-off-by: Jaroslav Kysela +--- + src/confeval.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/confeval.c b/src/confeval.c +index a971bf38..be9ac874 100644 +--- a/src/confeval.c ++++ b/src/confeval.c +@@ -190,7 +190,7 @@ int _snd_eval_string(snd_config_t **dst, const char *s, + } else { + e = s + 1; + while (*e) { +- if (!isalnum(*e)) ++ if (!isalnum(*e) && *e != '_') + break; + e++; + } +-- +2.31.1 + + +From 4b22871ee5a3bbc8eef7039bfc8db5e65ff3895f Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 9 Dec 2021 10:15:29 +0100 +Subject: [PATCH 2/2] conf: fix the device parsing when arguments has no + defaults + +The commit bf528b90 sets the value to an empty string which causes +these errors: + + pcm_hw.c: Invalid type for device + pcm_hw.c: Invalid type for subdevice + +When device arguments (@args) have no default values set, +the field must be skipped to keep the compatibility. + +BugLink: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1246 +Fixes: https://github.com/alsa-project/alsa-lib/issues/199 +Fixes: bf528b90 ("conf: add possibility to evaluate simple integer math expressions") +Signed-off-by: Jaroslav Kysela +--- + src/conf.c | 8 ++++++-- + src/confeval.c | 5 +++++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/conf.c b/src/conf.c +index 0f6d2ba8..d3597cbc 100644 +--- a/src/conf.c ++++ b/src/conf.c +@@ -4994,8 +4994,10 @@ int snd_config_copy(snd_config_t **dst, + static int _snd_config_expand_vars(snd_config_t **dst, const char *s, void *private_data) + { + snd_config_t *val, *vars = private_data; +- if (snd_config_search(vars, s, &val) < 0) +- return snd_config_make_string(dst, ""); ++ if (snd_config_search(vars, s, &val) < 0) { ++ *dst = NULL; ++ return 0; ++ } + return snd_config_copy(dst, val); + } + +@@ -5060,6 +5062,8 @@ static int _snd_config_expand(snd_config_t *src, + err = snd_config_evaluate_string(dst, s, fcn, vars); + if (err < 0) + return err; ++ if (*dst == NULL) ++ return 0; + err = snd_config_set_id(*dst, id); + if (err < 0) { + snd_config_delete(*dst); +diff --git a/src/confeval.c b/src/confeval.c +index be9ac874..4a6f8c2e 100644 +--- a/src/confeval.c ++++ b/src/confeval.c +@@ -203,6 +203,11 @@ int _snd_eval_string(snd_config_t **dst, const char *s, + free(m); + if (err < 0) + return err; ++ if (tmp == NULL) { ++ err = snd_config_imake_integer(&tmp, NULL, 0); ++ if (err < 0) ++ return err; ++ } + s = e; + } + err = _to_integer(op == LEFT ? &left : &right, tmp); +-- +2.31.1 + diff --git a/alsa-lib.spec b/alsa-lib.spec index 50c4eff..41bce0c 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -9,7 +9,7 @@ Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 1%{?prever_dot}%{?dist} +Release: 2%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,6 +167,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Thu Dec 9 2021 Jaroslav Kysela - 1.2.6-2 +- device open fixes from upstream + * Mon Dec 6 2021 Jaroslav Kysela - 1.2.6-1 - update to 1.2.6 diff --git a/alsa-ucm-conf.patch b/alsa-ucm-conf.patch index e69de29..b04faba 100644 --- a/alsa-ucm-conf.patch +++ b/alsa-ucm-conf.patch @@ -0,0 +1,28 @@ +From 244fc744e90c85f2816c5baba9fee08a85fec58e Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 9 Dec 2021 09:00:12 +0100 +Subject: [PATCH] USB-Audio: fix the wrong condition type for + If.realtek-alc1220-vb + +BugLink: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1246 +Signed-off-by: Jaroslav Kysela +--- + ucm2/USB-Audio/USB-Audio.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ucm2/USB-Audio/USB-Audio.conf b/ucm2/USB-Audio/USB-Audio.conf +index 878d16d..d9d740e 100644 +--- a/ucm2/USB-Audio/USB-Audio.conf ++++ b/ucm2/USB-Audio/USB-Audio.conf +@@ -15,7 +15,7 @@ If.linked { + If.realtek-alc1220-vb { + + Condition { +- Type Regex ++ Type RegexMatch + String "${CardComponents}" + # 0414:a002 Gigabyte TRX40 Aorus Pro WiFi + # 0b05:1917 ASUS ROG Strix +-- +2.31.1 + From c24c1753bcb7d09e5b6c7b892706a5de3954429a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 9 Dec 2021 12:24:17 +0100 Subject: [PATCH 07/10] AMD acp UCM fix --- alsa-lib.spec | 4 +- alsa-ucm-conf.patch | 228 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 229 insertions(+), 3 deletions(-) diff --git a/alsa-lib.spec b/alsa-lib.spec index 41bce0c..cef2f8f 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -9,7 +9,7 @@ Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 2%{?prever_dot}%{?dist} +Release: 3%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,7 +167,7 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog -* Thu Dec 9 2021 Jaroslav Kysela - 1.2.6-2 +* Thu Dec 9 2021 Jaroslav Kysela - 1.2.6-3 - device open fixes from upstream * Mon Dec 6 2021 Jaroslav Kysela - 1.2.6-1 diff --git a/alsa-ucm-conf.patch b/alsa-ucm-conf.patch index b04faba..f7e2ff1 100644 --- a/alsa-ucm-conf.patch +++ b/alsa-ucm-conf.patch @@ -1,7 +1,7 @@ From 244fc744e90c85f2816c5baba9fee08a85fec58e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 9 Dec 2021 09:00:12 +0100 -Subject: [PATCH] USB-Audio: fix the wrong condition type for +Subject: [PATCH 1/3] USB-Audio: fix the wrong condition type for If.realtek-alc1220-vb BugLink: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1246 @@ -26,3 +26,229 @@ index 878d16d..d9d740e 100644 -- 2.31.1 + +From cefbdeb9f763ab4cbba1c338716d40acb6a4e43a Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Wed, 10 Nov 2021 14:12:39 +0100 +Subject: [PATCH 2/3] ucm2: Add support for SC7180 Trogdor Lazor Chromebooks + +Almost all Trogdor Chromebooks are using RT5682 for headphones/headset +on 3.5mm jack, internal microphone and headset microphone, and MAX98357A +for the internal speakers (Lazor and Limozeen). + +This adds support for the sc7180-rt5682-max98357a-1mic sound card found +on the aforementioned Chromebooks. + +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Jaroslav Kysela +--- + .../sc7180/rt5682-max98357a/HiFi.conf | 101 ++++++++++++++++++ + .../sc7180/rt5682-max98357a/init.conf | 24 +++++ + .../sc7180-rt5682-max98357a-1mic.conf | 11 ++ + .../SC7180/sc7180-rt5682-max98357a-1mic.conf | 1 + + 4 files changed, 137 insertions(+) + create mode 100644 ucm2/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf + create mode 100644 ucm2/Qualcomm/sc7180/rt5682-max98357a/init.conf + create mode 100644 ucm2/Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf + create mode 120000 ucm2/conf.d/SC7180/sc7180-rt5682-max98357a-1mic.conf + +diff --git a/ucm2/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf b/ucm2/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf +new file mode 100644 +index 0000000..c93b4f7 +--- /dev/null ++++ b/ucm2/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf +@@ -0,0 +1,101 @@ ++# Use case configuration for ALC5682+MAX98357A on SC7180 ++ ++SectionVerb { ++ Value { ++ TQ "HiFi" ++ } ++} ++ ++SectionDevice."Speaker" { ++ Comment "Speaker" ++ ++ Value { ++ PlaybackChannels 2 ++ PlaybackPCM "hw:${CardId},1" ++ PlaybackPriority 100 ++ PlaybackMixerElem "Speaker" ++ PlaybackVolume "Speaker Playback Volume" ++ } ++} ++ ++SectionDevice."Headphones" { ++ Comment "Headphones" ++ ++ EnableSequence [ ++ cset "name='HPOL Playback Switch' 1" ++ cset "name='HPOR Playback Switch' 1" ++ cset "name='Stereo1 DAC MIXL DAC L1 Switch' 1" ++ cset "name='Stereo1 DAC MIXR DAC R1 Switch' 1" ++ ] ++ ++ DisableSequence [ ++ cset "name='HPOL Playback Switch' 0" ++ cset "name='HPOR Playback Switch' 0" ++ cset "name='Stereo1 DAC MIXL DAC L1 Switch' 0" ++ cset "name='Stereo1 DAC MIXR DAC R1 Switch' 0" ++ ] ++ ++ Value { ++ PlaybackPCM "hw:${CardId},0" ++ PlaybackPriority 200 ++ PlaybackMasterElem "DAC1" ++ PlaybackMixerElem "Headphone" ++ PlaybackVolume "Headphone Playback Volume" ++ } ++} ++ ++SectionDevice."Mic" { ++ Comment "Internal Microphone" ++ ++ ConflictingDevice [ ++ "Headset" ++ ] ++ ++ EnableSequence [ ++ cset "name='IF1 01 ADC Swap Mux' 1" ++ cset "name='Stereo1 ADC L2 Mux' 1" ++ cset "name='Stereo1 ADC R2 Mux' 1" ++ cset "name='Stereo1 ADC MIXL ADC2 Switch' 1" ++ cset "name='Stereo1 ADC MIXR ADC2 Switch' 1" ++ ] ++ ++ DisableSequence [ ++ cset "name='Stereo1 ADC L2 Mux' 0" ++ cset "name='Stereo1 ADC R2 Mux' 0" ++ cset "name='Stereo1 ADC MIXL ADC2 Switch' 0" ++ cset "name='Stereo1 ADC MIXR ADC2 Switch' 0" ++ ] ++ ++ Value { ++ CapturePCM "hw:${CardId},0" ++ CapturePriority 100 ++ CaptureMixerElem "STO1 ADC" ++ CaptureVolume "STO1 ADC Capture Volume" ++ } ++} ++ ++SectionDevice."Headset" { ++ Comment "Headset Microphone" ++ ++ EnableSequence [ ++ cset "name='IF1 01 ADC Swap Mux' 2" ++ cset "name='Stereo1 ADC L1 Mux' 1" ++ cset "name='Stereo1 ADC R1 Mux' 1" ++ cset "name='Stereo1 ADC MIXL ADC1 Switch' 1" ++ cset "name='Stereo1 ADC MIXR ADC1 Switch' 1" ++ ] ++ ++ DisableSequence [ ++ cset "name='Stereo1 ADC L1 Mux' 0" ++ cset "name='Stereo1 ADC R1 Mux' 0" ++ cset "name='Stereo1 ADC MIXL ADC1 Switch' 0" ++ cset "name='Stereo1 ADC MIXR ADC1 Switch' 0" ++ ] ++ ++ Value { ++ CapturePCM "hw:${CardId},0" ++ CapturePriority 200 ++ CaptureMixerElem "STO1 ADC" ++ CaptureVolume "STO1 ADC Capture Volume" ++ } ++} +diff --git a/ucm2/Qualcomm/sc7180/rt5682-max98357a/init.conf b/ucm2/Qualcomm/sc7180/rt5682-max98357a/init.conf +new file mode 100644 +index 0000000..5dee38a +--- /dev/null ++++ b/ucm2/Qualcomm/sc7180/rt5682-max98357a/init.conf +@@ -0,0 +1,24 @@ ++BootSequence [ ++ # Headphone ++ cset "name='HPOL Playback Switch' 0" ++ cset "name='HPOR Playback Switch' 0" ++ cset "name='Stereo1 DAC MIXL DAC L1 Switch' 0" ++ cset "name='Stereo1 DAC MIXR DAC R1 Switch' 0" ++ ++ # Headset mic ++ cset "name='Stereo1 ADC L Mux' 0" ++ cset "name='STO1 ADC Capture Switch' on" ++ cset "name='RECMIX1L CBJ Switch' 1" ++ cset "name='CBJ Boost Volume' 3" ++ cset "name='Stereo1 ADC L1 Mux' 0" ++ cset "name='Stereo1 ADC R1 Mux' 0" ++ cset "name='Stereo1 ADC MIXL ADC1 Switch' 0" ++ cset "name='Stereo1 ADC MIXR ADC1 Switch' 0" ++ ++ # Internal mic on ALC5682 ++ cset "name='IF1 01 ADC Swap Mux' 1" ++ cset "name='Stereo1 ADC L2 Mux' 0" ++ cset "name='Stereo1 ADC R2 Mux' 0" ++ cset "name='Stereo1 ADC MIXL ADC2 Switch' 0" ++ cset "name='Stereo1 ADC MIXR ADC2 Switch' 0" ++] +diff --git a/ucm2/Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf b/ucm2/Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf +new file mode 100644 +index 0000000..6a2be7e +--- /dev/null ++++ b/ucm2/Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf +@@ -0,0 +1,11 @@ ++Comment "SC7180 RT5682 MAX98357A single microphone sound card" ++Syntax 4 ++ ++SectionUseCase."HiFi" { ++ File "/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf" ++ Comment "Default" ++} ++ ++Include.card-init.File "/lib/card-init.conf" ++Include.ctl-remap.File "/lib/ctl-remap.conf" ++Include.init.File "/Qualcomm/sc7180/rt5682-max98357a/init.conf" +diff --git a/ucm2/conf.d/SC7180/sc7180-rt5682-max98357a-1mic.conf b/ucm2/conf.d/SC7180/sc7180-rt5682-max98357a-1mic.conf +new file mode 120000 +index 0000000..00f3e9e +--- /dev/null ++++ b/ucm2/conf.d/SC7180/sc7180-rt5682-max98357a-1mic.conf +@@ -0,0 +1 @@ ++../../Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf +\ No newline at end of file +-- +2.31.1 + + +From 60ea26507390bad3742af2272ba08b21f009d0ef Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 9 Dec 2021 11:24:14 +0100 +Subject: [PATCH 3/3] acp: fix linked configuration + +Fixes: https://github.com/alsa-project/alsa-lib/issues/199 +Signed-off-by: Jaroslav Kysela +--- + ucm2/common/linked-card.conf | 3 +++ + ucm2/conf.d/acp/acp.conf | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + create mode 100644 ucm2/common/linked-card.conf + +diff --git a/ucm2/common/linked-card.conf b/ucm2/common/linked-card.conf +new file mode 100644 +index 0000000..a90f20e +--- /dev/null ++++ b/ucm2/common/linked-card.conf +@@ -0,0 +1,3 @@ ++Syntax 3 ++ ++Include.linked.File "/common/linked.conf" +diff --git a/ucm2/conf.d/acp/acp.conf b/ucm2/conf.d/acp/acp.conf +index 5f056c7..7298c24 120000 +--- a/ucm2/conf.d/acp/acp.conf ++++ b/ucm2/conf.d/acp/acp.conf +@@ -1 +1 @@ +-../../common/linked.conf +\ No newline at end of file ++../../common/linked-card.conf +\ No newline at end of file +-- +2.31.1 + From 1157897630780be354080c623cc1287a21a1560d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 10 Dec 2021 10:11:53 +0100 Subject: [PATCH 08/10] updated alsa-lib to 1.2.6.1 and alsa-ucm-conf to 1.2.6.2 --- alsa-git.patch | 97 ----------------- alsa-lib.spec | 9 +- alsa-ucm-conf.patch | 254 -------------------------------------------- sources | 5 +- 4 files changed, 9 insertions(+), 356 deletions(-) diff --git a/alsa-git.patch b/alsa-git.patch index 4082c0c..e69de29 100644 --- a/alsa-git.patch +++ b/alsa-git.patch @@ -1,97 +0,0 @@ -From f44c94f24c2422c5ee1c4c58253ec17412b248a9 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Tue, 7 Dec 2021 09:21:24 +0100 -Subject: [PATCH 1/2] conf: accept '_' character in the variable name - -Fixes: https://github.com/alsa-project/alsa-lib/issues/197 -Signed-off-by: Jaroslav Kysela ---- - src/confeval.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/confeval.c b/src/confeval.c -index a971bf38..be9ac874 100644 ---- a/src/confeval.c -+++ b/src/confeval.c -@@ -190,7 +190,7 @@ int _snd_eval_string(snd_config_t **dst, const char *s, - } else { - e = s + 1; - while (*e) { -- if (!isalnum(*e)) -+ if (!isalnum(*e) && *e != '_') - break; - e++; - } --- -2.31.1 - - -From 4b22871ee5a3bbc8eef7039bfc8db5e65ff3895f Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Thu, 9 Dec 2021 10:15:29 +0100 -Subject: [PATCH 2/2] conf: fix the device parsing when arguments has no - defaults - -The commit bf528b90 sets the value to an empty string which causes -these errors: - - pcm_hw.c: Invalid type for device - pcm_hw.c: Invalid type for subdevice - -When device arguments (@args) have no default values set, -the field must be skipped to keep the compatibility. - -BugLink: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1246 -Fixes: https://github.com/alsa-project/alsa-lib/issues/199 -Fixes: bf528b90 ("conf: add possibility to evaluate simple integer math expressions") -Signed-off-by: Jaroslav Kysela ---- - src/conf.c | 8 ++++++-- - src/confeval.c | 5 +++++ - 2 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/src/conf.c b/src/conf.c -index 0f6d2ba8..d3597cbc 100644 ---- a/src/conf.c -+++ b/src/conf.c -@@ -4994,8 +4994,10 @@ int snd_config_copy(snd_config_t **dst, - static int _snd_config_expand_vars(snd_config_t **dst, const char *s, void *private_data) - { - snd_config_t *val, *vars = private_data; -- if (snd_config_search(vars, s, &val) < 0) -- return snd_config_make_string(dst, ""); -+ if (snd_config_search(vars, s, &val) < 0) { -+ *dst = NULL; -+ return 0; -+ } - return snd_config_copy(dst, val); - } - -@@ -5060,6 +5062,8 @@ static int _snd_config_expand(snd_config_t *src, - err = snd_config_evaluate_string(dst, s, fcn, vars); - if (err < 0) - return err; -+ if (*dst == NULL) -+ return 0; - err = snd_config_set_id(*dst, id); - if (err < 0) { - snd_config_delete(*dst); -diff --git a/src/confeval.c b/src/confeval.c -index be9ac874..4a6f8c2e 100644 ---- a/src/confeval.c -+++ b/src/confeval.c -@@ -203,6 +203,11 @@ int _snd_eval_string(snd_config_t **dst, const char *s, - free(m); - if (err < 0) - return err; -+ if (tmp == NULL) { -+ err = snd_config_imake_integer(&tmp, NULL, 0); -+ if (err < 0) -+ return err; -+ } - s = e; - } - err = _to_integer(op == LEFT ? &left : &right, tmp); --- -2.31.1 - diff --git a/alsa-lib.spec b/alsa-lib.spec index cef2f8f..9f3dcbf 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -2,14 +2,14 @@ #define prever_dot .rc3 #define postver a -%define version_alsa_lib 1.2.6 -%define version_alsa_ucm 1.2.6 +%define version_alsa_lib 1.2.6.1 +%define version_alsa_ucm 1.2.6.2 %define version_alsa_tplg 1.2.5 Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 3%{?prever_dot}%{?dist} +Release: 1%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,6 +167,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Fri Dec 10 2021 Jaroslav Kysela - 1.2.6.1-1 +- updated alsa-lib to 1.2.6.1 and alsa-ucm-conf to 1.2.6.2 + * Thu Dec 9 2021 Jaroslav Kysela - 1.2.6-3 - device open fixes from upstream diff --git a/alsa-ucm-conf.patch b/alsa-ucm-conf.patch index f7e2ff1..e69de29 100644 --- a/alsa-ucm-conf.patch +++ b/alsa-ucm-conf.patch @@ -1,254 +0,0 @@ -From 244fc744e90c85f2816c5baba9fee08a85fec58e Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Thu, 9 Dec 2021 09:00:12 +0100 -Subject: [PATCH 1/3] USB-Audio: fix the wrong condition type for - If.realtek-alc1220-vb - -BugLink: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1246 -Signed-off-by: Jaroslav Kysela ---- - ucm2/USB-Audio/USB-Audio.conf | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ucm2/USB-Audio/USB-Audio.conf b/ucm2/USB-Audio/USB-Audio.conf -index 878d16d..d9d740e 100644 ---- a/ucm2/USB-Audio/USB-Audio.conf -+++ b/ucm2/USB-Audio/USB-Audio.conf -@@ -15,7 +15,7 @@ If.linked { - If.realtek-alc1220-vb { - - Condition { -- Type Regex -+ Type RegexMatch - String "${CardComponents}" - # 0414:a002 Gigabyte TRX40 Aorus Pro WiFi - # 0b05:1917 ASUS ROG Strix --- -2.31.1 - - -From cefbdeb9f763ab4cbba1c338716d40acb6a4e43a Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Wed, 10 Nov 2021 14:12:39 +0100 -Subject: [PATCH 2/3] ucm2: Add support for SC7180 Trogdor Lazor Chromebooks - -Almost all Trogdor Chromebooks are using RT5682 for headphones/headset -on 3.5mm jack, internal microphone and headset microphone, and MAX98357A -for the internal speakers (Lazor and Limozeen). - -This adds support for the sc7180-rt5682-max98357a-1mic sound card found -on the aforementioned Chromebooks. - -Signed-off-by: AngeloGioacchino Del Regno -Signed-off-by: Jaroslav Kysela ---- - .../sc7180/rt5682-max98357a/HiFi.conf | 101 ++++++++++++++++++ - .../sc7180/rt5682-max98357a/init.conf | 24 +++++ - .../sc7180-rt5682-max98357a-1mic.conf | 11 ++ - .../SC7180/sc7180-rt5682-max98357a-1mic.conf | 1 + - 4 files changed, 137 insertions(+) - create mode 100644 ucm2/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf - create mode 100644 ucm2/Qualcomm/sc7180/rt5682-max98357a/init.conf - create mode 100644 ucm2/Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf - create mode 120000 ucm2/conf.d/SC7180/sc7180-rt5682-max98357a-1mic.conf - -diff --git a/ucm2/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf b/ucm2/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf -new file mode 100644 -index 0000000..c93b4f7 ---- /dev/null -+++ b/ucm2/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf -@@ -0,0 +1,101 @@ -+# Use case configuration for ALC5682+MAX98357A on SC7180 -+ -+SectionVerb { -+ Value { -+ TQ "HiFi" -+ } -+} -+ -+SectionDevice."Speaker" { -+ Comment "Speaker" -+ -+ Value { -+ PlaybackChannels 2 -+ PlaybackPCM "hw:${CardId},1" -+ PlaybackPriority 100 -+ PlaybackMixerElem "Speaker" -+ PlaybackVolume "Speaker Playback Volume" -+ } -+} -+ -+SectionDevice."Headphones" { -+ Comment "Headphones" -+ -+ EnableSequence [ -+ cset "name='HPOL Playback Switch' 1" -+ cset "name='HPOR Playback Switch' 1" -+ cset "name='Stereo1 DAC MIXL DAC L1 Switch' 1" -+ cset "name='Stereo1 DAC MIXR DAC R1 Switch' 1" -+ ] -+ -+ DisableSequence [ -+ cset "name='HPOL Playback Switch' 0" -+ cset "name='HPOR Playback Switch' 0" -+ cset "name='Stereo1 DAC MIXL DAC L1 Switch' 0" -+ cset "name='Stereo1 DAC MIXR DAC R1 Switch' 0" -+ ] -+ -+ Value { -+ PlaybackPCM "hw:${CardId},0" -+ PlaybackPriority 200 -+ PlaybackMasterElem "DAC1" -+ PlaybackMixerElem "Headphone" -+ PlaybackVolume "Headphone Playback Volume" -+ } -+} -+ -+SectionDevice."Mic" { -+ Comment "Internal Microphone" -+ -+ ConflictingDevice [ -+ "Headset" -+ ] -+ -+ EnableSequence [ -+ cset "name='IF1 01 ADC Swap Mux' 1" -+ cset "name='Stereo1 ADC L2 Mux' 1" -+ cset "name='Stereo1 ADC R2 Mux' 1" -+ cset "name='Stereo1 ADC MIXL ADC2 Switch' 1" -+ cset "name='Stereo1 ADC MIXR ADC2 Switch' 1" -+ ] -+ -+ DisableSequence [ -+ cset "name='Stereo1 ADC L2 Mux' 0" -+ cset "name='Stereo1 ADC R2 Mux' 0" -+ cset "name='Stereo1 ADC MIXL ADC2 Switch' 0" -+ cset "name='Stereo1 ADC MIXR ADC2 Switch' 0" -+ ] -+ -+ Value { -+ CapturePCM "hw:${CardId},0" -+ CapturePriority 100 -+ CaptureMixerElem "STO1 ADC" -+ CaptureVolume "STO1 ADC Capture Volume" -+ } -+} -+ -+SectionDevice."Headset" { -+ Comment "Headset Microphone" -+ -+ EnableSequence [ -+ cset "name='IF1 01 ADC Swap Mux' 2" -+ cset "name='Stereo1 ADC L1 Mux' 1" -+ cset "name='Stereo1 ADC R1 Mux' 1" -+ cset "name='Stereo1 ADC MIXL ADC1 Switch' 1" -+ cset "name='Stereo1 ADC MIXR ADC1 Switch' 1" -+ ] -+ -+ DisableSequence [ -+ cset "name='Stereo1 ADC L1 Mux' 0" -+ cset "name='Stereo1 ADC R1 Mux' 0" -+ cset "name='Stereo1 ADC MIXL ADC1 Switch' 0" -+ cset "name='Stereo1 ADC MIXR ADC1 Switch' 0" -+ ] -+ -+ Value { -+ CapturePCM "hw:${CardId},0" -+ CapturePriority 200 -+ CaptureMixerElem "STO1 ADC" -+ CaptureVolume "STO1 ADC Capture Volume" -+ } -+} -diff --git a/ucm2/Qualcomm/sc7180/rt5682-max98357a/init.conf b/ucm2/Qualcomm/sc7180/rt5682-max98357a/init.conf -new file mode 100644 -index 0000000..5dee38a ---- /dev/null -+++ b/ucm2/Qualcomm/sc7180/rt5682-max98357a/init.conf -@@ -0,0 +1,24 @@ -+BootSequence [ -+ # Headphone -+ cset "name='HPOL Playback Switch' 0" -+ cset "name='HPOR Playback Switch' 0" -+ cset "name='Stereo1 DAC MIXL DAC L1 Switch' 0" -+ cset "name='Stereo1 DAC MIXR DAC R1 Switch' 0" -+ -+ # Headset mic -+ cset "name='Stereo1 ADC L Mux' 0" -+ cset "name='STO1 ADC Capture Switch' on" -+ cset "name='RECMIX1L CBJ Switch' 1" -+ cset "name='CBJ Boost Volume' 3" -+ cset "name='Stereo1 ADC L1 Mux' 0" -+ cset "name='Stereo1 ADC R1 Mux' 0" -+ cset "name='Stereo1 ADC MIXL ADC1 Switch' 0" -+ cset "name='Stereo1 ADC MIXR ADC1 Switch' 0" -+ -+ # Internal mic on ALC5682 -+ cset "name='IF1 01 ADC Swap Mux' 1" -+ cset "name='Stereo1 ADC L2 Mux' 0" -+ cset "name='Stereo1 ADC R2 Mux' 0" -+ cset "name='Stereo1 ADC MIXL ADC2 Switch' 0" -+ cset "name='Stereo1 ADC MIXR ADC2 Switch' 0" -+] -diff --git a/ucm2/Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf b/ucm2/Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf -new file mode 100644 -index 0000000..6a2be7e ---- /dev/null -+++ b/ucm2/Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf -@@ -0,0 +1,11 @@ -+Comment "SC7180 RT5682 MAX98357A single microphone sound card" -+Syntax 4 -+ -+SectionUseCase."HiFi" { -+ File "/Qualcomm/sc7180/rt5682-max98357a/HiFi.conf" -+ Comment "Default" -+} -+ -+Include.card-init.File "/lib/card-init.conf" -+Include.ctl-remap.File "/lib/ctl-remap.conf" -+Include.init.File "/Qualcomm/sc7180/rt5682-max98357a/init.conf" -diff --git a/ucm2/conf.d/SC7180/sc7180-rt5682-max98357a-1mic.conf b/ucm2/conf.d/SC7180/sc7180-rt5682-max98357a-1mic.conf -new file mode 120000 -index 0000000..00f3e9e ---- /dev/null -+++ b/ucm2/conf.d/SC7180/sc7180-rt5682-max98357a-1mic.conf -@@ -0,0 +1 @@ -+../../Qualcomm/sc7180/rt5682-max98357a/sc7180-rt5682-max98357a-1mic.conf -\ No newline at end of file --- -2.31.1 - - -From 60ea26507390bad3742af2272ba08b21f009d0ef Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Thu, 9 Dec 2021 11:24:14 +0100 -Subject: [PATCH 3/3] acp: fix linked configuration - -Fixes: https://github.com/alsa-project/alsa-lib/issues/199 -Signed-off-by: Jaroslav Kysela ---- - ucm2/common/linked-card.conf | 3 +++ - ucm2/conf.d/acp/acp.conf | 2 +- - 2 files changed, 4 insertions(+), 1 deletion(-) - create mode 100644 ucm2/common/linked-card.conf - -diff --git a/ucm2/common/linked-card.conf b/ucm2/common/linked-card.conf -new file mode 100644 -index 0000000..a90f20e ---- /dev/null -+++ b/ucm2/common/linked-card.conf -@@ -0,0 +1,3 @@ -+Syntax 3 -+ -+Include.linked.File "/common/linked.conf" -diff --git a/ucm2/conf.d/acp/acp.conf b/ucm2/conf.d/acp/acp.conf -index 5f056c7..7298c24 120000 ---- a/ucm2/conf.d/acp/acp.conf -+++ b/ucm2/conf.d/acp/acp.conf -@@ -1 +1 @@ --../../common/linked.conf -\ No newline at end of file -+../../common/linked-card.conf -\ No newline at end of file --- -2.31.1 - diff --git a/sources b/sources index 07eab63..1544afe 100644 --- a/sources +++ b/sources @@ -1,3 +1,4 @@ -SHA512 (alsa-lib-1.2.6.tar.bz2) = ae95718813abf62811fe44c6df2a8de5a1227da4b022c4dd97dd8e7c1001f48307ba36bf04208bdbe24e8a8eebf4ed5a59f40ee6750dcbe976678071c3f2f5b7 -SHA512 (alsa-ucm-conf-1.2.6.tar.bz2) = 5fe85643b60c8defeafcdfcf97e61b5d05e6db28cef2466a70f63b8fffba22bdd50b83a5ca88806a6350de6e9d802dd3c2240b293190b9d05daea515c03d4397 +SHA512 (alsa-lib-1.2.6.1.tar.bz2) = 70e539cf092b5d43e00e4134d8a3e184f0dc34312823e4b58a574320cbf06cb7369bc3251ecb1858033756a7a8c35d36faa8da48d49f6efe0cec905784adbd45 +SHA512 (alsa-ucm-conf-1.2.6.2.tar.bz2) = d7122279bc36ab16dfe1a5f2e24b9dda57e1b59b7c7aeac3c8755af62b464053ed038aa56ebb52d7707ecae01674cac920ea784bb7493d978276a98cbf78d873 SHA512 (alsa-topology-conf-1.2.5.tar.bz2) = 2eb4d8baf2dcbf0b631dd11dbf15bffc51694d9cc6931619e51787f3ba58d1a091d266e6721a3b737c040ec74a28270b93f39fb97f30a3227cf340dd646e5d51 + From 9d835416330d9bff9b81f2ae5d8b4a3f366bda12 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 10 Dec 2021 11:38:41 +0100 Subject: [PATCH 09/10] correct Requires --- alsa-lib.spec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/alsa-lib.spec b/alsa-lib.spec index 9f3dcbf..06eaef3 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -9,7 +9,7 @@ Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 1%{?prever_dot}%{?dist} +Release: 2%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -52,7 +52,7 @@ against the ALSA libraries and interfaces. Summary: ALSA Use Case Manager configuration BuildArch: noarch License: BSD -Requires: %{name} >= %{version_alsa_ucm} +Requires: %{name} >= %{version_alsa_lib} %description -n alsa-ucm The Advanced Linux Sound Architecture (ALSA) Use Case Manager configuration @@ -62,7 +62,7 @@ contains alsa-lib configuration of Audio input/output names and routing Summary: ALSA Topology configuration BuildArch: noarch License: BSD -Requires: %{name} >= %{version_alsa_tplg} +Requires: %{name} >= %{version_alsa_lib} %description -n alsa-topology The Advanced Linux Sound Architecture (ALSA) topology configuration @@ -167,7 +167,7 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog -* Fri Dec 10 2021 Jaroslav Kysela - 1.2.6.1-1 +* Fri Dec 10 2021 Jaroslav Kysela - 1.2.6.1-2 - updated alsa-lib to 1.2.6.1 and alsa-ucm-conf to 1.2.6.2 * Thu Dec 9 2021 Jaroslav Kysela - 1.2.6-3 From 16a6715ed0d0d87a9c9b3f5e3c04363bac4fb421 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 17 Dec 2021 17:57:34 +0100 Subject: [PATCH 10/10] updated alsa-ucm-conf to 1.2.6.3 Signed-off-by: Jaroslav Kysela --- alsa-lib.spec | 7 +++++-- sources | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/alsa-lib.spec b/alsa-lib.spec index 06eaef3..49316cb 100644 --- a/alsa-lib.spec +++ b/alsa-lib.spec @@ -3,13 +3,13 @@ #define postver a %define version_alsa_lib 1.2.6.1 -%define version_alsa_ucm 1.2.6.2 +%define version_alsa_ucm 1.2.6.3 %define version_alsa_tplg 1.2.5 Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib Version: %{version_alsa_lib} -Release: 2%{?prever_dot}%{?dist} +Release: 3%{?prever_dot}%{?dist} License: LGPLv2+ URL: http://www.alsa-project.org/ @@ -167,6 +167,9 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_datadir}/alsa/topology %changelog +* Fri Dec 17 2021 Jaroslav Kysela - 1.2.6.1-3 +- updated alsa-ucm-conf to 1.2.6.3 + * Fri Dec 10 2021 Jaroslav Kysela - 1.2.6.1-2 - updated alsa-lib to 1.2.6.1 and alsa-ucm-conf to 1.2.6.2 diff --git a/sources b/sources index 1544afe..b6ee355 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ SHA512 (alsa-lib-1.2.6.1.tar.bz2) = 70e539cf092b5d43e00e4134d8a3e184f0dc34312823e4b58a574320cbf06cb7369bc3251ecb1858033756a7a8c35d36faa8da48d49f6efe0cec905784adbd45 -SHA512 (alsa-ucm-conf-1.2.6.2.tar.bz2) = d7122279bc36ab16dfe1a5f2e24b9dda57e1b59b7c7aeac3c8755af62b464053ed038aa56ebb52d7707ecae01674cac920ea784bb7493d978276a98cbf78d873 +SHA512 (alsa-ucm-conf-1.2.6.3.tar.bz2) = 14031173dd9b44c506f13172fcf89d1119e4b2d409a749ec8ef4948e75231a5e5091206e826dff9e70f1f803de8cfb9fd94886ef70764c705f65c1c7ebdf649f SHA512 (alsa-topology-conf-1.2.5.tar.bz2) = 2eb4d8baf2dcbf0b631dd11dbf15bffc51694d9cc6931619e51787f3ba58d1a091d266e6721a3b737c040ec74a28270b93f39fb97f30a3227cf340dd646e5d51 -