diff --git a/.alsa-lib.metadata b/.alsa-lib.metadata index c9df5ae..63d5f76 100644 --- a/.alsa-lib.metadata +++ b/.alsa-lib.metadata @@ -1 +1,3 @@ -2404e1c377428908c5188076d5652a2a1ecd028e SOURCES/alsa-lib-1.1.9.tar.bz2 +b58599c1237b2525962ed190ef501d3b9aa6edf5 SOURCES/alsa-lib-1.2.1.2.tar.bz2 +93fbe39ec099778e67e8ab2ef3780e08893f0176 SOURCES/alsa-topology-conf-1.2.1.tar.bz2 +b4b6070fb3335dcd750718da664b7cba47a3f285 SOURCES/alsa-ucm-conf-1.2.1.2.tar.bz2 diff --git a/.gitignore b/.gitignore index 7200175..bfc63ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -SOURCES/alsa-lib-1.1.9.tar.bz2 +SOURCES/alsa-lib-1.2.1.2.tar.bz2 +SOURCES/alsa-topology-conf-1.2.1.tar.bz2 +SOURCES/alsa-ucm-conf-1.2.1.2.tar.bz2 diff --git a/SOURCES/alsa-git.patch b/SOURCES/alsa-git.patch index 2662484..32f91f4 100644 --- a/SOURCES/alsa-git.patch +++ b/SOURCES/alsa-git.patch @@ -1,2202 +1,1022 @@ -From 63ba5243ab7a33b77be5b65c0a8a2a0d5e26983f Mon Sep 17 00:00:00 2001 -From: Vanitha Channaiah -Date: Wed, 15 May 2019 11:56:32 +0530 -Subject: [PATCH 01/25] pcm: direct: Add generic hw_ptr_alignment function for - dmix, dshare and dsnoop +From c79f09e1f5e8b559b58dacdb00708d995b2e3aa5 Mon Sep 17 00:00:00 2001 +From: paulhsia +Date: Sat, 30 Nov 2019 03:35:30 +0800 +Subject: [PATCH 01/16] ucm: Use strncmp to avoid access-out-of-boundary -Move the code snd_pcm_direct_reset_slave_ptr() from pcm_dmix.c -to pcm_direct.c and its header so that the helper function can be -re-used by other direct-pcm plugins. -There is no change in the behavior or the functionality. +If the length of the identifier is less than the length of the prefix, +access-out-of-boundary will occur in memcmp(). -Signed-off-by: Vanitha Channaiah -Signed-off-by: Takashi Iwai +Signed-off-by: paulhsia +Signed-off-by: Jaroslav Kysela --- - src/pcm/pcm_direct.c | 19 +++++++++++++++++++ - src/pcm/pcm_direct.h | 8 ++++++++ - src/pcm/pcm_dmix.c | 25 ++----------------------- - 3 files changed, 29 insertions(+), 23 deletions(-) + src/ucm/main.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) -diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c -index 666a8ce5..411a035b 100644 ---- a/src/pcm/pcm_direct.c -+++ b/src/pcm/pcm_direct.c -@@ -2040,3 +2040,22 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf, - - return 0; - } -+ -+void snd_pcm_direct_reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix) -+{ -+ dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr; -+ -+ if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDUP || -+ (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO && -+ pcm->buffer_size <= pcm->period_size * 2)) -+ dmix->slave_appl_ptr = -+ ((dmix->slave_appl_ptr + dmix->slave_period_size - 1) / -+ dmix->slave_period_size) * dmix->slave_period_size; -+ else if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDDOWN || -+ (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO && -+ (dmix->slave_period_size * SEC_TO_MS) / -+ pcm->rate < LOW_LATENCY_PERIOD_TIME)) -+ dmix->slave_appl_ptr = dmix->slave_hw_ptr = -+ ((dmix->slave_hw_ptr / dmix->slave_period_size) * -+ dmix->slave_period_size); -+} -diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h -index da5e280e..a71aab13 100644 ---- a/src/pcm/pcm_direct.h -+++ b/src/pcm/pcm_direct.h -@@ -24,6 +24,11 @@ - - #define DIRECT_IPC_SEMS 1 - #define DIRECT_IPC_SEM_CLIENT 0 -+/* Seconds representing in Milli seconds */ -+#define SEC_TO_MS 1000 -+/* slave_period time for low latency requirements in ms */ -+#define LOW_LATENCY_PERIOD_TIME 10 -+ - - typedef void (mix_areas_t)(unsigned int size, - volatile void *dst, void *src, -@@ -257,6 +262,8 @@ struct snd_pcm_direct { - snd1_pcm_direct_get_chmap - #define snd_pcm_direct_set_chmap \ - snd1_pcm_direct_set_chmap -+#define snd_pcm_direct_reset_slave_ptr \ -+ snd1_pcm_direct_reset_slave_ptr - - int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix); - -@@ -341,6 +348,7 @@ int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct); - int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm); - int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid); - struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm); -+void snd_pcm_direct_reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix); - - struct snd_pcm_direct_open_conf { - key_t ipc_key; -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index c5592cdb..dcde40d9 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -55,9 +55,6 @@ const char *_snd_module_pcm_dmix = ""; - #define STATE_RUN_PENDING 1024 - #endif - --#define SEC_TO_MS 1000 /* Seconds representing in Milli seconds */ --#define LOW_LATENCY_PERIOD_TIME 10 /* slave_period time for low latency requirements in ms */ -- - /* - * - */ -@@ -560,30 +557,12 @@ static int snd_pcm_dmix_hwsync(snd_pcm_t *pcm) - } - } - --static void reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix) --{ -- dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr; -- -- if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDUP || -- (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO && -- pcm->buffer_size <= pcm->period_size * 2)) -- dmix->slave_appl_ptr = -- ((dmix->slave_appl_ptr + dmix->slave_period_size - 1) -- / dmix->slave_period_size) * dmix->slave_period_size; -- else if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDDOWN || -- (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO && -- (dmix->slave_period_size * SEC_TO_MS) / pcm->rate < LOW_LATENCY_PERIOD_TIME)) -- dmix->slave_appl_ptr = dmix->slave_hw_ptr = -- ((dmix->slave_hw_ptr / dmix->slave_period_size) * -- dmix->slave_period_size); --} -- - static int snd_pcm_dmix_reset(snd_pcm_t *pcm) +diff --git a/src/ucm/main.c b/src/ucm/main.c +index b0b6ffb3..252e50d9 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -61,11 +61,13 @@ static int check_identifier(const char *identifier, const char *prefix) { - snd_pcm_direct_t *dmix = pcm->private_data; - dmix->hw_ptr %= pcm->period_size; - dmix->appl_ptr = dmix->last_appl_ptr = dmix->hw_ptr; -- reset_slave_ptr(pcm, dmix); -+ snd_pcm_direct_reset_slave_ptr(pcm, dmix); + int len; + +- if (strcmp(identifier, prefix) == 0) +- return 1; + len = strlen(prefix); +- if (memcmp(identifier, prefix, len) == 0 && identifier[len] == '/') ++ if (strncmp(identifier, prefix, len) != 0) ++ return 0; ++ ++ if (identifier[len] == 0 || identifier[len] == '/') + return 1; ++ return 0; } -@@ -592,7 +571,7 @@ static int snd_pcm_dmix_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dmix) - int err; - - snd_pcm_hwsync(dmix->spcm); -- reset_slave_ptr(pcm, dmix); -+ snd_pcm_direct_reset_slave_ptr(pcm, dmix); - err = snd_timer_start(dmix->timer); - if (err < 0) - return err; -- 2.20.1 -From 7265e603bf880a9ec2cd01c3cf2afbd7709e5af4 Mon Sep 17 00:00:00 2001 -From: Vanitha Channaiah -Date: Wed, 15 May 2019 11:56:33 +0530 -Subject: [PATCH 02/25] pcm: dshare: Added "hw_ptr_alignment" option in - configuration for alignment of slave pointers +From 9baf64da2f26844434ecea4825052937a3abe06c Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 29 Nov 2019 22:28:26 +0100 +Subject: [PATCH 02/16] ucm: return always at least NULL if no list is + available in snd_use_case_get_list() -This change adapt the fix commit 6b058fda9dce -("pcm: dmix: Add option to allow alignment of slave pointers") -for dshare plugin - -Issue is that snd_pcm_wait() goes back to waiting because the hw_ptr -is not period aligned. Therefore snd_pcm_wait() will block for a longer -time as required. - -With these rcar driver changes the exact position of the dma is returned. -During snd_pcm_start they read hw_ptr as reference, and this hw_ptr -is now not period aligned, and is a little ahead over the period while it -is read. Therefore when the avail is calculated during snd_pcm_wait(), -it is missing the avail_min by a few frames. - -An additional option hw_ptr_alignment is provided to dshare configuration, -to allow the user to configure the slave application and hw pointer -alignment at startup - -Signed-off-by: Vanitha Channaiah -Signed-off-by: Takashi Iwai +Signed-off-by: Jaroslav Kysela --- - src/pcm/pcm_dshare.c | 40 +++++++++++++++++++++++++++++++++++----- - 1 file changed, 35 insertions(+), 5 deletions(-) - -diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c -index f135b5df..cf8a8631 100644 ---- a/src/pcm/pcm_dshare.c -+++ b/src/pcm/pcm_dshare.c -@@ -333,16 +333,16 @@ static int snd_pcm_dshare_reset(snd_pcm_t *pcm) - snd_pcm_direct_t *dshare = pcm->private_data; - dshare->hw_ptr %= pcm->period_size; - dshare->appl_ptr = dshare->last_appl_ptr = dshare->hw_ptr; -- dshare->slave_appl_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr; -+ snd_pcm_direct_reset_slave_ptr(pcm, dshare); - return 0; - } - --static int snd_pcm_dshare_start_timer(snd_pcm_direct_t *dshare) -+static int snd_pcm_dshare_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dshare) - { - int err; - - snd_pcm_hwsync(dshare->spcm); -- dshare->slave_appl_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr; -+ snd_pcm_direct_reset_slave_ptr(pcm, dshare); - err = snd_timer_start(dshare->timer); - if (err < 0) - return err; -@@ -364,7 +364,8 @@ static int snd_pcm_dshare_start(snd_pcm_t *pcm) - else if (avail < 0) - return 0; - else { -- if ((err = snd_pcm_dshare_start_timer(dshare)) < 0) -+ err = snd_pcm_dshare_start_timer(pcm, dshare); -+ if (err < 0) - return err; - snd_pcm_dshare_sync_area(pcm); - } -@@ -547,7 +548,8 @@ static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm, - return 0; - snd_pcm_mmap_appl_forward(pcm, size); - if (dshare->state == STATE_RUN_PENDING) { -- if ((err = snd_pcm_dshare_start_timer(dshare)) < 0) -+ err = snd_pcm_dshare_start_timer(pcm, dshare); -+ if (err < 0) - return err; - } else if (dshare->state == SND_PCM_STATE_RUNNING || - dshare->state == SND_PCM_STATE_DRAINING) { -@@ -755,6 +757,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, - dshare->slowptr = opts->slowptr; - dshare->max_periods = opts->max_periods; - dshare->var_periodsize = opts->var_periodsize; -+ dshare->hw_ptr_alignment = opts->hw_ptr_alignment; - dshare->sync_ptr = snd_pcm_dshare_sync_ptr; - - retry: -@@ -912,6 +915,12 @@ pcm.name { - ipc_key INT # unique IPC key - ipc_key_add_uid BOOL # add current uid to unique IPC key - ipc_perm INT # IPC permissions (octal, default 0600) -+ hw_ptr_alignment STR # Slave application and hw pointer alignment type -+ # STR can be one of the below strings : -+ # no -+ # roundup -+ # rounddown -+ # auto (default) - slave STR - # or - slave { # Slave definition -@@ -936,6 +945,27 @@ pcm.name { - } - \endcode - -+hw_ptr_alignment specifies slave application and hw -+pointer alignment type. By default hw_ptr_alignment is auto. Below are -+the possible configurations: -+- no: minimal latency with minimal frames dropped at startup. But -+ wakeup of application (return from snd_pcm_wait() or poll()) can -+ take up to 2 * period. -+- roundup: It is guaranteed that all frames will be played at -+ startup. But the latency will increase upto period-1 frames. -+- rounddown: It is guaranteed that a wakeup will happen for each -+ period and frames can be written from application. But on startup -+ upto period-1 frames will be dropped. -+- auto: Selects the best approach depending on the used period and -+ buffer size. -+ If the application buffer size is < 2 * application period, -+ "roundup" will be selected to avoid under runs. If the slave_period -+ is < 10ms we could expect that there are low latency -+ requirements. Therefore "rounddown" will be chosen to avoid long -+ wakeup times. Such wakeup delay could otherwise end up with Xruns in -+ case of a dependency to another sound device (e.g. forwarding of -+ microphone to speaker). Else "no" will be chosen. -+ - \subsection pcm_plugins_dshare_funcref Function reference - -
    --- -2.20.1 - - -From 3ab798004733ce65bd5c7a48d650de3465825210 Mon Sep 17 00:00:00 2001 -From: Vanitha Channaiah -Date: Wed, 15 May 2019 11:56:34 +0530 -Subject: [PATCH 03/25] pcm: dsnoop: Added "hw_ptr_alignment" option in - configuration for slave pointer alignment - -This change adapt the fix commit 6b058fda9dce -("pcm: dmix: Add option to allow alignment of slave pointers") -for dsnoop plugin - -Issue is that snd_pcm_wait() goes back to waiting because the hw_ptr -is not period aligned. Therefore snd_pcm_wait() will block for a longer -time as required. - -With these rcar driver changes the exact position of the dma is returned. -During snd_pcm_start they read hw_ptr as reference, and this hw_ptr -is now not period aligned, and is a little ahead over the period while it -is read. Therefore when the avail is calculated during snd_pcm_wait(), -it is missing the avail_min by a few frames. - -An additional option hw_ptr_alignment is provided to dsnoop configuration, -to allow the user to configure the slave application and hw pointer -alignment at startup - -Signed-off-by: Vanitha Channaiah -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_direct.c | 1 - - src/pcm/pcm_dmix.c | 2 ++ - src/pcm/pcm_dshare.c | 2 ++ - src/pcm/pcm_dsnoop.c | 30 +++++++++++++++++++++++++++++- - 4 files changed, 33 insertions(+), 2 deletions(-) - -diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c -index 411a035b..54d99005 100644 ---- a/src/pcm/pcm_direct.c -+++ b/src/pcm/pcm_direct.c -@@ -2043,7 +2043,6 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf, - - void snd_pcm_direct_reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix) - { -- dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr; - - if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDUP || - (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO && -diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c -index dcde40d9..274726e4 100644 ---- a/src/pcm/pcm_dmix.c -+++ b/src/pcm/pcm_dmix.c -@@ -562,6 +562,7 @@ static int snd_pcm_dmix_reset(snd_pcm_t *pcm) - snd_pcm_direct_t *dmix = pcm->private_data; - dmix->hw_ptr %= pcm->period_size; - dmix->appl_ptr = dmix->last_appl_ptr = dmix->hw_ptr; -+ dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr; - snd_pcm_direct_reset_slave_ptr(pcm, dmix); - return 0; - } -@@ -571,6 +572,7 @@ static int snd_pcm_dmix_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dmix) - int err; - - snd_pcm_hwsync(dmix->spcm); -+ dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr; - snd_pcm_direct_reset_slave_ptr(pcm, dmix); - err = snd_timer_start(dmix->timer); - if (err < 0) -diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c -index cf8a8631..b75809c8 100644 ---- a/src/pcm/pcm_dshare.c -+++ b/src/pcm/pcm_dshare.c -@@ -333,6 +333,7 @@ static int snd_pcm_dshare_reset(snd_pcm_t *pcm) - snd_pcm_direct_t *dshare = pcm->private_data; - dshare->hw_ptr %= pcm->period_size; - dshare->appl_ptr = dshare->last_appl_ptr = dshare->hw_ptr; -+ dshare->slave_appl_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr; - snd_pcm_direct_reset_slave_ptr(pcm, dshare); - return 0; - } -@@ -342,6 +343,7 @@ static int snd_pcm_dshare_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dshare) - int err; - - snd_pcm_hwsync(dshare->spcm); -+ dshare->slave_appl_ptr = dshare->slave_hw_ptr = *dshare->spcm->hw.ptr; - snd_pcm_direct_reset_slave_ptr(pcm, dshare); - err = snd_timer_start(dshare->timer); - if (err < 0) -diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c -index d08b6241..58b1e534 100644 ---- a/src/pcm/pcm_dsnoop.c -+++ b/src/pcm/pcm_dsnoop.c -@@ -278,6 +278,7 @@ static int snd_pcm_dsnoop_reset(snd_pcm_t *pcm) - dsnoop->hw_ptr %= pcm->period_size; - dsnoop->appl_ptr = dsnoop->hw_ptr; - dsnoop->slave_appl_ptr = dsnoop->slave_hw_ptr; -+ snd_pcm_direct_reset_slave_ptr(pcm, dsnoop); - return 0; - } - -@@ -285,12 +286,13 @@ static int snd_pcm_dsnoop_start(snd_pcm_t *pcm) - { - snd_pcm_direct_t *dsnoop = pcm->private_data; - int err; -- -+ - if (dsnoop->state != SND_PCM_STATE_PREPARED) - return -EBADFD; - snd_pcm_hwsync(dsnoop->spcm); - snoop_timestamp(pcm); - dsnoop->slave_appl_ptr = dsnoop->slave_hw_ptr; -+ snd_pcm_direct_reset_slave_ptr(pcm, dsnoop); - err = snd_timer_start(dsnoop->timer); - if (err < 0) - return err; -@@ -627,6 +629,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, - dsnoop->max_periods = opts->max_periods; - dsnoop->var_periodsize = opts->var_periodsize; - dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr; -+ dsnoop->hw_ptr_alignment = opts->hw_ptr_alignment; - - retry: - if (first_instance) { -@@ -771,6 +774,12 @@ pcm.name { - ipc_key INT # unique IPC key - ipc_key_add_uid BOOL # add current uid to unique IPC key - ipc_perm INT # IPC permissions (octal, default 0600) -+ hw_ptr_alignment STR # Slave application and hw pointer alignment type -+ # STR can be one of the below strings : -+ # no -+ # roundup -+ # rounddown -+ # auto (default) - slave STR - # or - slave { # Slave definition -@@ -795,6 +804,25 @@ pcm.name { - } - \endcode - -+hw_ptr_alignment specifies slave application and hw -+pointer alignment type. By default hw_ptr_alignment is auto. Below are -+the possible configurations: -+- no: minimal latency with minimal frames dropped at startup. But -+ wakeup of application (return from snd_pcm_wait() or poll()) can -+ take up to 2 * period. -+- roundup: It is guaranteed that all frames will be played at -+ startup. But the latency will increase upto period-1 frames. -+- rounddown: It is guaranteed that a wakeup will happen for each -+ period and frames can be written from application. But on startup -+ upto period-1 frames will be dropped. -+- auto: Selects the best approach depending on the used period and -+ buffer size. -+ If the application buffer size is < 2 * application period, -+ "roundup" will be selected to avoid over runs. If the slave_period -+ is < 10ms we could expect that there are low latency -+ requirements. Therefore "rounddown" will be chosen to avoid long -+ wakeup times. Else "no" will be chosen. -+ - \subsection pcm_plugins_dsnoop_funcref Function reference - -
      --- -2.20.1 - - -From 5f2e5af61b0b8cfbf310e8b1e08a034d993e432f Mon Sep 17 00:00:00 2001 -From: Adam Miartus -Date: Tue, 21 May 2019 15:32:47 +0200 -Subject: [PATCH 04/25] pcm: file: add support for infile reading in non - interleaved mode - -add helper function to copy input file data to buffer mapped by areas, -in case of an error, do not fill the areas, allowing device read buffer -to be provided to api caller - -previously unused rbuf variable is reused for this purpose - -Signed-off-by: Adam Miartus -Reviewed-by: Timo Wischer -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_file.c | 67 ++++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 56 insertions(+), 11 deletions(-) - -diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c -index 3a19cef9..3c682659 100644 ---- a/src/pcm/pcm_file.c -+++ b/src/pcm/pcm_file.c -@@ -77,6 +77,7 @@ typedef struct { - snd_pcm_uframes_t appl_ptr; - snd_pcm_uframes_t file_ptr_bytes; - snd_pcm_uframes_t wbuf_size; -+ snd_pcm_uframes_t rbuf_size; - size_t wbuf_size_bytes; - size_t wbuf_used_bytes; - char *wbuf; -@@ -266,6 +267,39 @@ static int snd_pcm_file_open_output_file(snd_pcm_file_t *file) - return 0; - } - -+/* fill areas with data from input file, return bytes red */ -+static int snd_pcm_file_areas_read_infile(snd_pcm_t *pcm, -+ const snd_pcm_channel_area_t *areas, -+ snd_pcm_uframes_t offset, -+ snd_pcm_uframes_t frames) -+{ -+ snd_pcm_file_t *file = pcm->private_data; -+ snd_pcm_channel_area_t areas_if[pcm->channels]; -+ ssize_t bytes; -+ -+ if (file->ifd < 0) -+ return -EBADF; -+ -+ if (file->rbuf == NULL) -+ return -ENOMEM; -+ -+ if (file->rbuf_size < frames) { -+ SYSERR("requested more frames than pcm buffer"); -+ return -ENOMEM; -+ } -+ -+ bytes = read(file->ifd, file->rbuf, snd_pcm_frames_to_bytes(pcm, frames)); -+ if (bytes < 0) { -+ SYSERR("read from file failed, error: %d", bytes); -+ return bytes; -+ } -+ -+ snd_pcm_areas_from_buf(pcm, areas_if, file->rbuf); -+ snd_pcm_areas_copy(areas, offset, areas_if, 0, pcm->channels, snd_pcm_bytes_to_frames(pcm, bytes), pcm->format); -+ -+ return bytes; -+} -+ - static void setup_wav_header(snd_pcm_t *pcm, struct wav_fmt *fmt) - { - fmt->fmt = TO_LE16(0x01); -@@ -568,19 +602,19 @@ static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm - { - snd_pcm_file_t *file = pcm->private_data; - snd_pcm_channel_area_t areas[pcm->channels]; -- snd_pcm_sframes_t n; -+ snd_pcm_sframes_t frames; - -- if (file->ifd >= 0) { -- SNDERR("DEBUG: Noninterleaved read not yet implemented.\n"); -- return 0; /* TODO: Noninterleaved read */ -- } -+ __snd_pcm_lock(pcm); -+ frames = _snd_pcm_readn(file->gen.slave, bufs, size); -+ if (frames <= 0) -+ return frames; - -- n = _snd_pcm_readn(file->gen.slave, bufs, size); -- if (n > 0) { -- snd_pcm_areas_from_bufs(pcm, areas, bufs); -- snd_pcm_file_add_frames(pcm, areas, 0, n); -- } -- return n; -+ snd_pcm_areas_from_bufs(pcm, areas, bufs); -+ snd_pcm_file_areas_read_infile(pcm, areas, 0, frames); -+ snd_pcm_file_add_frames(pcm, areas, 0, frames); -+ -+ __snd_pcm_unlock(pcm); -+ return frames; - } - - static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm, -@@ -609,9 +643,11 @@ static int snd_pcm_file_hw_free(snd_pcm_t *pcm) - free(file->wbuf); - free(file->wbuf_areas); - free(file->final_fname); -+ free(file->rbuf); - file->wbuf = NULL; - file->wbuf_areas = NULL; - file->final_fname = NULL; -+ file->rbuf = NULL; - return snd_pcm_hw_free(file->gen.slave); - } - -@@ -638,6 +674,15 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - snd_pcm_file_hw_free(pcm); - return -ENOMEM; - } -+ assert(!file->rbuf); -+ file->rbuf_size = slave->buffer_size; -+ file->rbuf_size_bytes = snd_pcm_frames_to_bytes(slave, file->rbuf_size); -+ file->rbuf_used_bytes = 0; -+ file->rbuf = malloc(file->rbuf_size_bytes); -+ if (file->rbuf == NULL) { -+ snd_pcm_file_hw_free(pcm); -+ return -ENOMEM; -+ } - file->appl_ptr = file->file_ptr_bytes = 0; - for (channel = 0; channel < slave->channels; ++channel) { - snd_pcm_channel_area_t *a = &file->wbuf_areas[channel]; --- -2.20.1 - - -From 349b42f5477c904fa3e10bac2fa2429fad2cbc65 Mon Sep 17 00:00:00 2001 -From: Adam Miartus -Date: Tue, 21 May 2019 15:33:08 +0200 -Subject: [PATCH 05/25] pcm: file: use snd_pcm_file_areas_read_infile for readi - -use previously introduced helper function, this commit unifies behavior -of readi and readn - -corner case behavior of readi is changed by this commit, previously, -in case 0 bytes were red from file (EOF), frames = 0 was returned, -signaling api user as if no data was red from slave, after the patch, -amount of frames red from slave with data red from slave stored in buffer -is returned when EOF is reached - -Signed-off-by: Adam Miartus -Reviewed-by: Timo Wischer -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_file.c | 27 +++++++++++++-------------- - 1 file changed, 13 insertions(+), 14 deletions(-) - -diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c -index 3c682659..dcaa41d1 100644 ---- a/src/pcm/pcm_file.c -+++ b/src/pcm/pcm_file.c -@@ -579,22 +579,21 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc - { - snd_pcm_file_t *file = pcm->private_data; - snd_pcm_channel_area_t areas[pcm->channels]; -- snd_pcm_sframes_t n; -+ snd_pcm_sframes_t frames; -+ -+ __snd_pcm_lock(pcm); -+ -+ frames = _snd_pcm_readi(file->gen.slave, buffer, size); -+ if (frames <= 0) -+ return frames; - -- n = _snd_pcm_readi(file->gen.slave, buffer, size); -- if (n <= 0) -- return n; -- if (file->ifd >= 0) { -- __snd_pcm_lock(pcm); -- n = read(file->ifd, buffer, n * pcm->frame_bits / 8); -- __snd_pcm_unlock(pcm); -- if (n < 0) -- return n; -- n = n * 8 / pcm->frame_bits; -- } - snd_pcm_areas_from_buf(pcm, areas, buffer); -- snd_pcm_file_add_frames(pcm, areas, 0, n); -- return n; -+ snd_pcm_file_areas_read_infile(pcm, areas, 0, frames); -+ snd_pcm_file_add_frames(pcm, areas, 0, frames); -+ -+ __snd_pcm_unlock(pcm); -+ -+ return frames; - } - - /* locking */ --- -2.20.1 - - -From 33c7ea0865b7f87cef1c3d3e767734c0edd02e84 Mon Sep 17 00:00:00 2001 -From: Adam Miartus -Date: Thu, 23 May 2019 11:44:30 +0200 -Subject: [PATCH 06/25] pcm: file: add missing unlock on early return - -Signed-off-by: Adam Miartus -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_file.c | 8 ++++++-- + src/ucm/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) -diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c -index dcaa41d1..8e2c70b1 100644 ---- a/src/pcm/pcm_file.c -+++ b/src/pcm/pcm_file.c -@@ -584,8 +584,10 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc - __snd_pcm_lock(pcm); +diff --git a/src/ucm/main.c b/src/ucm/main.c +index 252e50d9..b80db65f 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -1160,8 +1160,10 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr, - frames = _snd_pcm_readi(file->gen.slave, buffer, size); -- if (frames <= 0) -+ if (frames <= 0) { -+ __snd_pcm_unlock(pcm); - return frames; -+ } + modifier = find_modifier(uc_mgr, verb, name, 0); + if (modifier) { +- if (modifier->dev_list.type != type) ++ if (modifier->dev_list.type != type) { ++ *list = NULL; + return 0; ++ } + return get_list(&modifier->dev_list.list, list, + struct dev_list_node, list, + name); +@@ -1169,8 +1171,10 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr, - snd_pcm_areas_from_buf(pcm, areas, buffer); - snd_pcm_file_areas_read_infile(pcm, areas, 0, frames); -@@ -605,8 +607,10 @@ static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm - - __snd_pcm_lock(pcm); - frames = _snd_pcm_readn(file->gen.slave, bufs, size); -- if (frames <= 0) -+ if (frames <= 0) { -+ __snd_pcm_unlock(pcm); - return frames; -+ } - - snd_pcm_areas_from_bufs(pcm, areas, bufs); - snd_pcm_file_areas_read_infile(pcm, areas, 0, frames); + device = find_device(uc_mgr, verb, name, 0); + if (device) { +- if (device->dev_list.type != type) ++ if (device->dev_list.type != type) { ++ *list = NULL; + return 0; ++ } + return get_list(&device->dev_list.list, list, + struct dev_list_node, list, + name); -- 2.20.1 -From 108a2f43791fe769fd58726881b12ad908ebd2e0 Mon Sep 17 00:00:00 2001 -From: Takashi Iwai -Date: Thu, 18 Apr 2019 20:40:18 +0200 -Subject: [PATCH 07/25] ucm: Add UCM profile for CX2072X codec on - Baytrail/Cherrytrail profiles +From ebdd2b6cdb8119cf75f0dd0a3b283d271b3a547e Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 30 Nov 2019 20:31:55 +0100 +Subject: [PATCH 03/16] ucm: add _identifiers list -Adding a new Conexant CX2072X codec profile and reusing the existing -BYT/CHT platform snippets. - -Currently tested only on ASUS E200HA laptop. - -Signed-off-by: Takashi Iwai +Signed-off-by: Jaroslav Kysela --- - configure.ac | 2 ++ - src/conf/ucm/Makefile.am | 1 + - src/conf/ucm/bytcht-cx2072x/HiFi.conf | 24 ++++++++++++++++++ - src/conf/ucm/bytcht-cx2072x/Makefile.am | 4 +++ - .../ucm/bytcht-cx2072x/bytcht-cx2072x.conf | 8 ++++++ - src/conf/ucm/codecs/Makefile.am | 1 + - src/conf/ucm/codecs/cx2072x/DisableSeq.conf | 7 ++++++ - src/conf/ucm/codecs/cx2072x/EnableSeq.conf | 13 ++++++++++ - src/conf/ucm/codecs/cx2072x/HeadPhones.conf | 24 ++++++++++++++++++ - src/conf/ucm/codecs/cx2072x/HeadsetMic.conf | 25 +++++++++++++++++++ - src/conf/ucm/codecs/cx2072x/InternalMic.conf | 24 ++++++++++++++++++ - src/conf/ucm/codecs/cx2072x/Makefile.am | 6 +++++ - src/conf/ucm/codecs/cx2072x/Speaker.conf | 23 +++++++++++++++++ - 13 files changed, 162 insertions(+) - create mode 100644 src/conf/ucm/bytcht-cx2072x/HiFi.conf - create mode 100644 src/conf/ucm/bytcht-cx2072x/Makefile.am - create mode 100644 src/conf/ucm/bytcht-cx2072x/bytcht-cx2072x.conf - create mode 100644 src/conf/ucm/codecs/cx2072x/DisableSeq.conf - create mode 100644 src/conf/ucm/codecs/cx2072x/EnableSeq.conf - create mode 100644 src/conf/ucm/codecs/cx2072x/HeadPhones.conf - create mode 100644 src/conf/ucm/codecs/cx2072x/HeadsetMic.conf - create mode 100644 src/conf/ucm/codecs/cx2072x/InternalMic.conf - create mode 100644 src/conf/ucm/codecs/cx2072x/Makefile.am - create mode 100644 src/conf/ucm/codecs/cx2072x/Speaker.conf + include/use-case.h | 1 + + src/ucm/main.c | 268 ++++++++++++++++++++++++++++++++++----------- + 2 files changed, 208 insertions(+), 61 deletions(-) -diff --git a/configure.ac b/configure.ac -index 0fb34de4..2e955760 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -720,6 +720,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \ - src/conf/ucm/ASUSTeKCOMPUTERINC.-T100HAN-1.0-T100HAN/Makefile \ - src/conf/ucm/broadwell-rt286/Makefile \ - src/conf/ucm/broxton-rt298/Makefile \ -+ src/conf/ucm/bytcht-cx2072x/Makefile \ - src/conf/ucm/bytcht-es8316/Makefile \ - src/conf/ucm/bytcht-es8316-mono-spk-in1-mic/Makefile \ - src/conf/ucm/bytcht-es8316-mono-spk-in2-mic/Makefile \ -@@ -765,6 +766,7 @@ AC_OUTPUT(Makefile doc/Makefile doc/pictures/Makefile doc/doxygen.cfg \ - src/conf/ucm/tegraalc5632/Makefile \ - src/conf/ucm/VEYRON-I2S/Makefile \ - src/conf/ucm/codecs/Makefile \ -+ src/conf/ucm/codecs/cx2072x/Makefile \ - src/conf/ucm/codecs/es8316/Makefile \ - src/conf/ucm/codecs/nau8824/Makefile \ - src/conf/ucm/codecs/rt5640/Makefile \ -diff --git a/src/conf/ucm/Makefile.am b/src/conf/ucm/Makefile.am -index e9f88ed6..02257048 100644 ---- a/src/conf/ucm/Makefile.am -+++ b/src/conf/ucm/Makefile.am -@@ -4,6 +4,7 @@ platforms \ - ASUSTeKCOMPUTERINC.-T100HAN-1.0-T100HAN \ - broadwell-rt286 \ - broxton-rt298 \ -+bytcht-cx2072x \ - bytcht-es8316 \ - bytcht-es8316-mono-spk-in1-mic \ - bytcht-es8316-mono-spk-in2-mic \ -diff --git a/src/conf/ucm/bytcht-cx2072x/HiFi.conf b/src/conf/ucm/bytcht-cx2072x/HiFi.conf -new file mode 100644 -index 00000000..e9c1f757 ---- /dev/null -+++ b/src/conf/ucm/bytcht-cx2072x/HiFi.conf -@@ -0,0 +1,24 @@ -+SectionVerb { -+ EnableSequence [ -+ cdev "hw:bytchtcx2072x" -+ -+ -+ ] -+ -+ DisableSequence [ -+ cdev "hw:bytchtcx2072x" -+ -+ -+ ] -+ -+ Value { -+ PlaybackPCM "hw:bytchtcx2072x" -+ CapturePCM "hw:bytchtcx2072x" -+ } -+} -+ -+ -+ -+ -+ -+ -diff --git a/src/conf/ucm/bytcht-cx2072x/Makefile.am b/src/conf/ucm/bytcht-cx2072x/Makefile.am -new file mode 100644 -index 00000000..373b2a77 ---- /dev/null -+++ b/src/conf/ucm/bytcht-cx2072x/Makefile.am -@@ -0,0 +1,4 @@ -+alsaconfigdir = @ALSA_CONFIG_DIR@ -+ucmdir = $(alsaconfigdir)/ucm/bytcht-cx2072x -+ucm_DATA = bytcht-cx2072x.conf HiFi.conf -+EXTRA_DIST = $(ucm_DATA) -diff --git a/src/conf/ucm/bytcht-cx2072x/bytcht-cx2072x.conf b/src/conf/ucm/bytcht-cx2072x/bytcht-cx2072x.conf -new file mode 100644 -index 00000000..fce04456 ---- /dev/null -+++ b/src/conf/ucm/bytcht-cx2072x/bytcht-cx2072x.conf -@@ -0,0 +1,8 @@ -+SectionUseCase."HiFi" { -+ File "HiFi.conf" -+ Comment "Play HiFi quality Music" -+} -+ -+SectionDefaults [ -+ cdev "hw:bytchtcx2072x" -+] -diff --git a/src/conf/ucm/codecs/Makefile.am b/src/conf/ucm/codecs/Makefile.am -index f78fd081..5987b9cf 100644 ---- a/src/conf/ucm/codecs/Makefile.am -+++ b/src/conf/ucm/codecs/Makefile.am -@@ -1,4 +1,5 @@ - SUBDIRS=\ -+cx2072x \ - es8316 \ - rt5640 \ - rt5645 \ -diff --git a/src/conf/ucm/codecs/cx2072x/DisableSeq.conf b/src/conf/ucm/codecs/cx2072x/DisableSeq.conf -new file mode 100644 -index 00000000..1e3d5489 ---- /dev/null -+++ b/src/conf/ucm/codecs/cx2072x/DisableSeq.conf -@@ -0,0 +1,7 @@ -+# Output Configuration -+cset "name='I2S DAC1L Switch' off" -+cset "name='I2S DAC1R Switch' off" -+ -+# Input Configuration -+cset "name='I2S ADC1L Switch' off" -+cset "name='I2S ADC1R Switch' off" -diff --git a/src/conf/ucm/codecs/cx2072x/EnableSeq.conf b/src/conf/ucm/codecs/cx2072x/EnableSeq.conf -new file mode 100644 -index 00000000..fb8e3fe2 ---- /dev/null -+++ b/src/conf/ucm/codecs/cx2072x/EnableSeq.conf -@@ -0,0 +1,13 @@ -+# Disable all inputs / outputs -+cset "name='Ext Spk Switch' off" -+cset "name='Headphone Switch' off" -+cset "name='Headset Mic Switch' off" -+cset "name='Int Mic Switch' off" -+ -+# Output Configuration -+cset "name='I2S DAC1L Switch' on" -+cset "name='I2S DAC1R Switch' on" -+ -+# Input Configuration -+cset "name='I2S ADC1L Switch' on" -+cset "name='I2S ADC1R Switch' on" -diff --git a/src/conf/ucm/codecs/cx2072x/HeadPhones.conf b/src/conf/ucm/codecs/cx2072x/HeadPhones.conf -new file mode 100644 -index 00000000..4e3ff950 ---- /dev/null -+++ b/src/conf/ucm/codecs/cx2072x/HeadPhones.conf -@@ -0,0 +1,24 @@ -+SectionDevice."Headphones" { -+ Comment "Headphones" -+ -+ ConflictingDevice [ -+ "Speaker" -+ ] -+ -+ EnableSequence [ -+ cdev "hw:bytchtcx2072x" -+ cset "name='Headphone Switch' on" -+ cset "name='PortA Out En Switch' on" -+ ] -+ -+ DisableSequence [ -+ cdev "hw:bytchtcx2072x" -+ cset "name='Headphone Switch' off" -+ cset "name='PortA Out En Switch' off" -+ ] -+ -+ Value { -+ PlaybackChannels "2" -+ JackControl "Headphone Jack" -+ } -+} -diff --git a/src/conf/ucm/codecs/cx2072x/HeadsetMic.conf b/src/conf/ucm/codecs/cx2072x/HeadsetMic.conf -new file mode 100644 -index 00000000..26b8df16 ---- /dev/null -+++ b/src/conf/ucm/codecs/cx2072x/HeadsetMic.conf -@@ -0,0 +1,25 @@ -+SectionDevice."HeadsetMic" { -+ Comment "Headset Microphone" -+ -+ ConflictingDevice [ -+ "InternalMic" -+ ] -+ -+ EnableSequence [ -+ cdev "hw:bytchtcx2072x" -+ cset "name='Headset Mic Switch' on" -+ cset "name='ADC1 Mux' 'PortD Switch'" -+ cset "name='PortD In En Switch' on" -+ ] -+ -+ DisableSequence [ -+ cdev "hw:bytchtcx2072x" -+ cset "name='Headset Mic Switch' off" -+ cset "name='PortD In En Switch' off" -+ ] -+ -+ Value { -+ CaptureChannels "2" -+ JackControl "Headset Mic Jack" -+ } -+} -diff --git a/src/conf/ucm/codecs/cx2072x/InternalMic.conf b/src/conf/ucm/codecs/cx2072x/InternalMic.conf -new file mode 100644 -index 00000000..a3e14538 ---- /dev/null -+++ b/src/conf/ucm/codecs/cx2072x/InternalMic.conf -@@ -0,0 +1,24 @@ -+SectionDevice."InternalMic" { -+ Comment "Internal Microphone" -+ -+ ConflictingDevice [ -+ "HeadsetMic" -+ ] -+ -+ EnableSequence [ -+ cdev "hw:bytchtcx2072x" -+ cset "name='Int Mic Switch' on" -+ cset "name='ADC1 Mux' 'PortC Switch'" -+ cset "name='PortC In En Switch' on" -+ ] -+ -+ DisableSequence [ -+ cdev "hw:bytchtcx2072x" -+ cset "name='Int Mic Switch' off" -+ cset "name='PortC In En Switch' off" -+ ] -+ -+ Value { -+ CaptureChannels "2" -+ } -+} -diff --git a/src/conf/ucm/codecs/cx2072x/Makefile.am b/src/conf/ucm/codecs/cx2072x/Makefile.am -new file mode 100644 -index 00000000..2990fd09 ---- /dev/null -+++ b/src/conf/ucm/codecs/cx2072x/Makefile.am -@@ -0,0 +1,6 @@ -+alsaconfigdir = @ALSA_CONFIG_DIR@ -+ucmdir = $(alsaconfigdir)/ucm/codecs/cx2072x -+ucm_DATA = EnableSeq.conf DisableSeq.conf \ -+ HeadPhones.conf Speaker.conf \ -+ InternalMic.conf HeadsetMic.conf -+EXTRA_DIST = $(ucm_DATA) -diff --git a/src/conf/ucm/codecs/cx2072x/Speaker.conf b/src/conf/ucm/codecs/cx2072x/Speaker.conf -new file mode 100644 -index 00000000..55e2b2ba ---- /dev/null -+++ b/src/conf/ucm/codecs/cx2072x/Speaker.conf -@@ -0,0 +1,23 @@ -+SectionDevice."Speaker" { -+ Comment "Speakers" -+ -+ ConflictingDevice [ -+ "Headphones" -+ ] -+ -+ EnableSequence [ -+ cdev "hw:bytchtcx2072x" -+ cset "name='Ext Spk Switch' on" -+ cset "name='PortG Out En Switch' on" -+ ] -+ -+ DisableSequence [ -+ cdev "hw:bytchtcx2072x" -+ cset "name='Ext Spk Switch' off" -+ cset "name='PortG Out En Switch' off" -+ ] -+ -+ Value { -+ PlaybackChannels "2" -+ } -+} --- -2.20.1 - - -From e520f454803acfdb9af5cd7224129b37904eef4a Mon Sep 17 00:00:00 2001 -From: Adam Miartus -Date: Thu, 23 May 2019 15:00:39 +0200 -Subject: [PATCH 08/25] pcm: add mmap_begin callback to snd_pcm_fast_ops_t api - -main motivation for adding the callback is to use it to enable operation -on mmaped buffer before user access for pcm_file plugin - -support for MMAP read access with masking by data from input file is not -implemented for pcm_file plugin, by adding this callback implementing -such feature can be done by rewriting next continuous portion of buffer -on each mmap_begin call - -plugins like softvol use pcm_plugin interface and overwrite the buffer by -looping around it in avail_update callback, this patch hopes to simplify -the task by adding new api callback, removing the need for rewriting -pcm_file (to use pcm_plugin callbacks) and careful checking when looping -around whole mmaped buffer - -Signed-off-by: Adam Miartus -Reviewed-by: Timo Wischer -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm.c | 6 ++++++ - src/pcm/pcm_local.h | 1 + - 2 files changed, 7 insertions(+) - -diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c -index 3a71d79b..323926e1 100644 ---- a/src/pcm/pcm.c -+++ b/src/pcm/pcm.c -@@ -7129,7 +7129,13 @@ int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, - snd_pcm_uframes_t f; - snd_pcm_uframes_t avail; - const snd_pcm_channel_area_t *xareas; -+ - assert(pcm && areas && offset && frames); -+ -+ if (pcm->fast_ops->mmap_begin) -+ return pcm->fast_ops->mmap_begin(pcm->fast_op_arg, areas, offset, frames); -+ -+ /* fallback for plugins that do not specify new callback */ - xareas = snd_pcm_mmap_areas(pcm); - if (xareas == NULL) - return -EBADFD; -diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h -index d52229d8..d5726eb2 100644 ---- a/src/pcm/pcm_local.h -+++ b/src/pcm/pcm_local.h -@@ -184,6 +184,7 @@ typedef struct { - int (*poll_descriptors)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space); /* locked */ - int (*poll_revents)(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); /* locked */ - int (*may_wait_for_avail_min)(snd_pcm_t *pcm, snd_pcm_uframes_t avail); -+ int (*mmap_begin)(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames); /* locked */ - } snd_pcm_fast_ops_t; +diff --git a/include/use-case.h b/include/use-case.h +index 8e7e838c..85c58ac0 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -206,6 +206,7 @@ int snd_use_case_free_list(const char *list[], int items); + * - _enadevs - get list of enabled devices + * - _enamods - get list of enabled modifiers + * ++ * - _identifiers/{modifier}|{device}[/{verb}] - list of value identifiers + * - _supporteddevs/{modifier}|{device}[/{verb}] - list of supported devices + * - _conflictingdevs/{modifier}|{device}[/{verb}] - list of conflicting devices + * +diff --git a/src/ucm/main.c b/src/ucm/main.c +index b80db65f..d2078a23 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -1072,7 +1072,6 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr) + /** + * \brief Get list of verbs in pair verbname+comment + * \param list Returned list +- * \param verbname For verb (NULL = current) + * \return Number of list entries if success, otherwise a negative error code + */ + static int get_verb_list(snd_use_case_mgr_t *uc_mgr, const char **list[]) +@@ -1181,7 +1180,6 @@ static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr, + } - struct _snd_pcm { --- -2.20.1 - - -From fe7ff721a954c3f8c2183febc7c3fa5736357b67 Mon Sep 17 00:00:00 2001 -From: Adam Miartus -Date: Thu, 23 May 2019 15:00:40 +0200 -Subject: [PATCH 09/25] pcm: file: add infile read support for mmap mode - -mmap_begin callback is used to copy data from input file to mmaped -buffer - -guard for corner use of api (multiple mmap_begin calls by user) is -introduced to check if next continuous buffer was already overwritten - -buffer is overwritten with input file data only in case of stream capture - -Signed-off-by: Adam Miartus -Reviewed-by: Timo Wischer -Signed-off-by: Takashi Iwai ---- - src/pcm/pcm_file.c | 31 +++++++++++++++++++++++++++++++ - 1 file changed, 31 insertions(+) - -diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c -index 8e2c70b1..52cc10a9 100644 ---- a/src/pcm/pcm_file.c -+++ b/src/pcm/pcm_file.c -@@ -88,6 +88,7 @@ typedef struct { - size_t buffer_bytes; - struct wav_fmt wav_header; - size_t filelen; -+ char ifmmap_overwritten; - } snd_pcm_file_t; - - #if __BYTE_ORDER == __LITTLE_ENDIAN -@@ -630,6 +631,8 @@ static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm, - const snd_pcm_channel_area_t *areas; - snd_pcm_sframes_t result; - -+ file->ifmmap_overwritten = 0; -+ - result = snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz); - if (result >= 0) { - assert(ofs == offset && siz == size); -@@ -640,6 +643,32 @@ static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm, - return result; + return -ENOENT; +- } -+static int snd_pcm_file_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, -+ snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames) -+{ -+ snd_pcm_file_t *file = pcm->private_data; -+ snd_pcm_channel_area_t areas_if[pcm->channels]; -+ snd_pcm_uframes_t frames_if; -+ void *buffer = NULL; -+ int result; -+ -+ result = snd_pcm_mmap_begin(file->gen.slave, areas, offset, frames); -+ if (result < 0) -+ return result; -+ -+ if (pcm->stream != SND_PCM_STREAM_CAPTURE) -+ return result; -+ -+ /* user may run mmap_begin without mmap_commit multiple times in row */ -+ if (file->ifmmap_overwritten) -+ return result; -+ file->ifmmap_overwritten = 1; -+ -+ snd_pcm_file_areas_read_infile(pcm, *areas, *offset, *frames); -+ -+ return result; -+} -+ - static int snd_pcm_file_hw_free(snd_pcm_t *pcm) - { - snd_pcm_file_t *file = pcm->private_data; -@@ -666,6 +695,7 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) - file->wbuf_size = slave->buffer_size * 2; - file->wbuf_size_bytes = snd_pcm_frames_to_bytes(slave, file->wbuf_size); - file->wbuf_used_bytes = 0; -+ file->ifmmap_overwritten = 0; - assert(!file->wbuf); - file->wbuf = malloc(file->wbuf_size_bytes); - if (file->wbuf == NULL) { -@@ -777,6 +807,7 @@ static const snd_pcm_fast_ops_t snd_pcm_file_fast_ops = { - .poll_descriptors = snd_pcm_generic_poll_descriptors, - .poll_revents = snd_pcm_generic_poll_revents, - .htimestamp = snd_pcm_generic_htimestamp, -+ .mmap_begin = snd_pcm_file_mmap_begin, - }; - /** --- -2.20.1 - - -From 47bc6d534102aca9cc2aed1b6bdd5633ef645a3f Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 10:27:25 +0200 -Subject: [PATCH 10/25] aserver: fix resource leak coverity - -Signed-off-by: Jaroslav Kysela ---- - aserver/aserver.c | 33 +++++++++++++++++++-------------- - 1 file changed, 19 insertions(+), 14 deletions(-) - -diff --git a/aserver/aserver.c b/aserver/aserver.c -index 066414d8..6d20f330 100644 ---- a/aserver/aserver.c -+++ b/aserver/aserver.c -@@ -75,6 +75,7 @@ static int make_local_socket(const char *filename) - if (bind(sock, (struct sockaddr *) addr, size) < 0) { - int result = -errno; - SYSERROR("bind failed"); -+ close(sock); - return result; - } +@@ -1210,41 +1208,201 @@ static int get_conflicting_device_list(snd_use_case_mgr_t *uc_mgr, -@@ -101,6 +102,7 @@ static int make_inet_socket(int port) - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - int result = -errno; - SYSERROR("bind failed"); -+ close(sock); - return result; - } + #ifndef DOC_HIDDEN + struct myvalue { +- struct list_head list; +- char *value; ++ struct list_head list; ++ const char *text; + }; + #endif -@@ -916,10 +918,9 @@ static int inet_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED - - static int server(const char *sockname, int port) - { -- int err; -+ int err, result, sockn = -1, socki = -1; - unsigned int k; - long open_max; -- int result; - - if (!sockname && port < 0) - return -EINVAL; -@@ -933,36 +934,36 @@ static int server(const char *sockname, int port) - waiters = calloc((size_t) open_max, sizeof(*waiters)); - - if (sockname) { -- int sock = make_local_socket(sockname); -- if (sock < 0) -- return sock; -- if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ sockn = make_local_socket(sockname); -+ if (sockn < 0) -+ return sockn; -+ if (fcntl(sockn, F_SETFL, O_NONBLOCK) < 0) { - result = -errno; - SYSERROR("fcntl O_NONBLOCK failed"); - goto _end; - } -- if (listen(sock, 4) < 0) { -+ if (listen(sockn, 4) < 0) { - result = -errno; - SYSERROR("listen failed"); - goto _end; - } -- add_waiter(sock, POLLIN, local_handler, NULL); -+ add_waiter(sockn, POLLIN, local_handler, NULL); - } - if (port >= 0) { -- int sock = make_inet_socket(port); -- if (sock < 0) -- return sock; -- if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { -+ socki = make_inet_socket(port); -+ if (socki < 0) -+ return socki; -+ if (fcntl(socki, F_SETFL, O_NONBLOCK) < 0) { - result = -errno; - SYSERROR("fcntl failed"); - goto _end; - } -- if (listen(sock, 4) < 0) { -+ if (listen(socki, 4) < 0) { - result = -errno; - SYSERROR("listen failed"); - goto _end; - } -- add_waiter(sock, POLLIN, inet_handler, NULL); -+ add_waiter(socki, POLLIN, inet_handler, NULL); - } - - while (1) { -@@ -991,6 +992,10 @@ static int server(const char *sockname, int port) - } - } - _end: -+ if (sockn >= 0) -+ close(sockn); -+ if (socki >= 0) -+ close(socki); - free(pollfds); - free(waiters); - return result; --- -2.20.1 - - -From 4aa960c48b4d292425597d283f3ef15d02590082 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 10:39:05 +0200 -Subject: [PATCH 11/25] src/conf.c: add missing va_end() call (coverity) - -Signed-off-by: Jaroslav Kysela ---- - src/conf.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/conf.c b/src/conf.c -index cda5518e..3a3c91bf 100644 ---- a/src/conf.c -+++ b/src/conf.c -@@ -3034,8 +3034,10 @@ int snd_config_save(snd_config_t *config, snd_output_t *out) - if (!k) \ - break; \ - err = fcn(config, k, &n); \ -- if (err < 0) \ -+ if (err < 0) { \ -+ va_end(arg); \ - return err; \ -+ } \ - config = n; \ - } \ - va_end(arg); \ -@@ -3056,8 +3058,10 @@ int snd_config_save(snd_config_t *config, snd_output_t *out) - if (!k) \ - break; \ - err = fcn(root, config, k, &n); \ -- if (err < 0) \ -+ if (err < 0) { \ -+ va_end(arg); \ - return err; \ -+ } \ - config = n; \ - } \ - va_end(arg); \ --- -2.20.1 - - -From 990b1a53ed800caac0bab1c2b7987205569861fe Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 10:44:49 +0200 -Subject: [PATCH 12/25] config: parse_string() fix the dynamic buffer - allocation failure code (coverity) - -Signed-off-by: Jaroslav Kysela ---- - src/conf.c | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/src/conf.c b/src/conf.c -index 3a3c91bf..3e4b76a3 100644 ---- a/src/conf.c -+++ b/src/conf.c -@@ -4747,8 +4747,11 @@ static int parse_string(const char **ptr, char **val) - return -EINVAL; - case '\\': - c = parse_char(ptr); -- if (c < 0) -+ if (c < 0) { -+ if (alloc > bufsize) -+ free(buf); - return c; -+ } - break; - default: - (*ptr)++; -@@ -4768,12 +4771,17 @@ static int parse_string(const char **ptr, char **val) - alloc *= 2; - if (old_alloc == bufsize) { - buf = malloc(alloc); -+ if (!buf) -+ return -ENOMEM; - memcpy(buf, _buf, old_alloc); - } else { -- buf = realloc(buf, alloc); -+ char *buf2 = realloc(buf, alloc); -+ if (!buf2) { -+ free(buf); -+ return -ENOMEM; -+ } -+ buf = buf2; - } -- if (!buf) -- return -ENOMEM; - } - buf[idx++] = c; - } --- -2.20.1 - - -From 51881cacc05e7d5e3cc8fc1ec9a4ac93a6327703 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 10:51:47 +0200 -Subject: [PATCH 13/25] control_shm: remove duplicate code (coverity) - -Signed-off-by: Jaroslav Kysela ---- - src/control/control_shm.c | 18 +++--------------- - 1 file changed, 3 insertions(+), 15 deletions(-) - -diff --git a/src/control/control_shm.c b/src/control/control_shm.c -index d7b41398..1d9de8b7 100644 ---- a/src/control/control_shm.c -+++ b/src/control/control_shm.c -@@ -302,13 +302,9 @@ static int snd_ctl_shm_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev) - { - snd_ctl_shm_t *shm = ctl->private_data; - volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; -- int err; - ctrl->u.pcm_prefer_subdevice = subdev; - ctrl->cmd = SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE; -- err = snd_ctl_shm_action(ctl); -- if (err < 0) -- return err; -- return err; -+ return snd_ctl_shm_action(ctl); - } - - static int snd_ctl_shm_rawmidi_next_device(snd_ctl_t *ctl, int * device) -@@ -343,26 +339,18 @@ static int snd_ctl_shm_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev) - { - snd_ctl_shm_t *shm = ctl->private_data; - volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; -- int err; - ctrl->u.rawmidi_prefer_subdevice = subdev; - ctrl->cmd = SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE; -- err = snd_ctl_shm_action(ctl); -- if (err < 0) -- return err; -- return err; -+ return snd_ctl_shm_action(ctl); - } - - static int snd_ctl_shm_set_power_state(snd_ctl_t *ctl, unsigned int state) - { - snd_ctl_shm_t *shm = ctl->private_data; - volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; -- int err; - ctrl->u.power_state = state; - ctrl->cmd = SNDRV_CTL_IOCTL_POWER; -- err = snd_ctl_shm_action(ctl); -- if (err < 0) -- return err; -- return err; -+ return snd_ctl_shm_action(ctl); - } - - static int snd_ctl_shm_get_power_state(snd_ctl_t *ctl, unsigned int *state) --- -2.20.1 - - -From d6ba264038fde08baf5e62bdde2a5614792db5c8 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 10:53:09 +0200 -Subject: [PATCH 14/25] control_shm: add missing socket close to the error path - (coverity) - -Signed-off-by: Jaroslav Kysela ---- - src/control/control_shm.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/control/control_shm.c b/src/control/control_shm.c -index 1d9de8b7..40d42643 100644 ---- a/src/control/control_shm.c -+++ b/src/control/control_shm.c -@@ -424,8 +424,10 @@ static int make_local_socket(const char *filename) - addr->sun_family = AF_LOCAL; - memcpy(addr->sun_path, filename, l); - -- if (connect(sock, (struct sockaddr *) addr, size) < 0) -+ if (connect(sock, (struct sockaddr *) addr, size) < 0) { -+ close(sock); - return -errno; -+ } - return sock; - } - --- -2.20.1 - - -From d5a1cf35b710d255508e56ed19633e1fbf41a2d4 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 10:57:20 +0200 -Subject: [PATCH 15/25] pcm: fix memory leak in _snd_pcm_parse_config_chmaps() - (coverity) - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c -index 323926e1..fa51ca99 100644 ---- a/src/pcm/pcm.c -+++ b/src/pcm/pcm.c -@@ -8391,6 +8391,7 @@ _snd_pcm_parse_config_chmaps(snd_config_t *conf) - free(chmap); - goto error; - } -+ free(chmap); - nums++; - } - return maps; --- -2.20.1 - - -From 22ade9b8c150240a960ca683ee6d8f53ce8bc6ea Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 11:09:43 +0200 -Subject: [PATCH 16/25] pcm_file: call pclose() correctly for popen() - (coverity) - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_file.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c -index 52cc10a9..99db3754 100644 ---- a/src/pcm/pcm_file.c -+++ b/src/pcm/pcm_file.c -@@ -227,7 +227,14 @@ static int snd_pcm_file_open_output_file(snd_pcm_file_t *file) - file->final_fname); - return -errno; - } -- fd = fileno(pipe); -+ fd = dup(fileno(pipe)); -+ err = -errno; -+ pclose(pipe); -+ if (fd < 0) { -+ SYSERR("unable to dup pipe file handle for command %s", -+ file->final_fname); -+ return err; ++/** ++ * \brief Convert myvalue list string list ++ * \param list myvalue list ++ * \param res string list ++ * \retval Number of list entries if success, otherwise a negativer error code ++ */ ++static int myvalue_to_str_list(struct list_head *list, char ***res) ++{ ++ struct list_head *pos; ++ struct myvalue *value; ++ char **p; ++ int cnt; ++ ++ cnt = alloc_str_list(list, 1, res); ++ if (cnt < 0) ++ return cnt; ++ p = *res; ++ list_for_each(pos, list) { ++ value = list_entry(pos, struct myvalue, list); ++ *p = strdup(value->text); ++ if (*p == NULL) { ++ snd_use_case_free_list((const char **)p, cnt); ++ return -ENOMEM; + } - } else { - if (file->trunc) - fd = open(file->final_fname, O_WRONLY|O_CREAT|O_TRUNC, --- -2.20.1 - - -From 3ae743efea704c16c9464f38d502c23759b71245 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 11:11:46 +0200 -Subject: [PATCH 17/25] pcm_hw: close file descriptor in the error path in - snd_pcm_hw_open() (coverity) - -Signed-off-by: Jaroslav Kysela ---- - src/pcm/pcm_hw.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c -index 91370a88..77d4dae1 100644 ---- a/src/pcm/pcm_hw.c -+++ b/src/pcm/pcm_hw.c -@@ -1724,12 +1724,15 @@ int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name, - } - if (info.subdevice != (unsigned int) subdevice) { - close(fd); -+ fd = -1; - goto __again; - } - } - snd_ctl_close(ctl); - return snd_pcm_hw_open_fd(pcmp, name, fd, sync_ptr_ioctl); - _err: -+ if (fd >= 0) -+ close(fd); - snd_ctl_close(ctl); - return ret; - } --- -2.20.1 - - -From 8ab0393b42e08655a5fee0a8e84b3ba84932465b Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 20:31:24 +0200 -Subject: [PATCH 18/25] rawmidi: use snd_dlobj_cache_get2() in rawmidi open - (coverity) - -Use proper reference counting for the dynamic symbol. - -Signed-off-by: Jaroslav Kysela ---- - include/local.h | 3 +++ - src/dlmisc.c | 41 +++++++++++++++++++++++++++++------ - src/rawmidi/rawmidi.c | 43 ++++++++++++++++--------------------- - src/rawmidi/rawmidi_local.h | 2 +- - 4 files changed, 57 insertions(+), 32 deletions(-) - -diff --git a/include/local.h b/include/local.h -index 5edad317..e8390df5 100644 ---- a/include/local.h -+++ b/include/local.h -@@ -328,6 +328,8 @@ static inline int snd_open_device(const char *filename, int fmode) - /* make local functions really local */ - #define snd_dlobj_cache_get \ - snd1_dlobj_cache_get -+#define snd_dlobj_cache_get2 \ -+ snd1_dlobj_cache_get2 - #define snd_dlobj_cache_put \ - snd1_dlobj_cache_put - #define snd_dlobj_cache_cleanup \ -@@ -341,6 +343,7 @@ static inline int snd_open_device(const char *filename, int fmode) - - /* dlobj cache */ - void *snd_dlobj_cache_get(const char *lib, const char *name, const char *version, int verbose); -+void *snd_dlobj_cache_get2(const char *lib, const char *name, const char *version, int verbose); - int snd_dlobj_cache_put(void *open_func); - void snd_dlobj_cache_cleanup(void); - -diff --git a/src/dlmisc.c b/src/dlmisc.c -index 012e61bc..8c8f3ff7 100644 ---- a/src/dlmisc.c -+++ b/src/dlmisc.c -@@ -251,15 +251,15 @@ static inline void snd_dlobj_unlock(void) {} - - static LIST_HEAD(pcm_dlobj_list); - --void *snd_dlobj_cache_get(const char *lib, const char *name, -- const char *version, int verbose) -+static struct dlobj_cache * -+snd_dlobj_cache_get0(const char *lib, const char *name, -+ const char *version, int verbose) - { - struct list_head *p; - struct dlobj_cache *c; - void *func, *dlobj; - char errbuf[256]; - -- snd_dlobj_lock(); - list_for_each(p, &pcm_dlobj_list) { - c = list_entry(p, struct dlobj_cache, list); - if (c->lib && lib && strcmp(c->lib, lib) != 0) -@@ -270,9 +270,7 @@ void *snd_dlobj_cache_get(const char *lib, const char *name, - continue; - if (strcmp(c->name, name) == 0) { - c->refcnt++; -- func = c->func; -- snd_dlobj_unlock(); -- return func; -+ return c; - } - } - -@@ -285,7 +283,6 @@ void *snd_dlobj_cache_get(const char *lib, const char *name, - SNDERR("Cannot open shared library %s (%s)", - lib ? lib : "[builtin]", - errbuf); -- snd_dlobj_unlock(); - return NULL; - } - -@@ -314,6 +311,36 @@ void *snd_dlobj_cache_get(const char *lib, const char *name, - c->dlobj = dlobj; - c->func = func; - list_add_tail(&c->list, &pcm_dlobj_list); -+ return c; -+} -+ -+void *snd_dlobj_cache_get(const char *lib, const char *name, -+ const char *version, int verbose) -+{ -+ struct dlobj_cache *c; -+ void *func = NULL; -+ -+ snd_dlobj_lock(); -+ c = snd_dlobj_cache_get0(lib, name, version, verbose); -+ if (c) -+ func = c->func; -+ snd_dlobj_unlock(); -+ return func; -+} -+ -+void *snd_dlobj_cache_get2(const char *lib, const char *name, -+ const char *version, int verbose) -+{ -+ struct dlobj_cache *c; -+ void *func = NULL; -+ -+ snd_dlobj_lock(); -+ c = snd_dlobj_cache_get0(lib, name, version, verbose); -+ if (c) { -+ func = c->func; -+ /* double reference */ -+ c->refcnt++; ++ p++; + } - snd_dlobj_unlock(); - return func; - } -diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c -index 2f419142..1b5f8525 100644 ---- a/src/rawmidi/rawmidi.c -+++ b/src/rawmidi/rawmidi.c -@@ -162,7 +162,7 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp - snd_config_t *rawmidi_conf, int mode) - { - const char *str; -- char buf[256], errbuf[256]; -+ char buf[256]; - int err; - snd_config_t *conf, *type_conf = NULL; - snd_config_iterator_t i, next; -@@ -174,7 +174,6 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp - #ifndef PIC - extern void *snd_rawmidi_open_symbols(void); - #endif -- void *h = NULL; - if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) { - if (name) - SNDERR("Invalid type for RAWMIDI %s definition", name); -@@ -239,41 +238,37 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp - #ifndef PIC - snd_rawmidi_open_symbols(); - #endif -- h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf)); -- if (h) -- open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION)); -- err = 0; -- if (!h) { -- SNDERR("Cannot open shared library %s (%s)", lib, errbuf); -- err = -ENOENT; -- } else if (!open_func) { -- SNDERR("symbol %s is not defined inside %s", open_name, lib); -- snd_dlclose(h); -+ open_func = snd_dlobj_cache_get2(lib, open_name, -+ SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION), 1); -+ if (!open_func) { - err = -ENXIO; -+ goto _err; - } -- _err: - if (type_conf) - snd_config_delete(type_conf); -- if (err >= 0) -- err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode); -- if (err < 0) { -- if (h) -- snd_dlclose(h); -- return err; -- } -+ err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode); -+ if (err < 0) -+ goto _err; - if (inputp) { -- (*inputp)->dl_handle = h; h = NULL; -+ (*inputp)->open_func = open_func; - snd_rawmidi_params_default(*inputp, ¶ms); - err = snd_rawmidi_params(*inputp, ¶ms); - assert(err >= 0); - } - if (outputp) { -- (*outputp)->dl_handle = h; -+ (*outputp)->open_func = open_func; - snd_rawmidi_params_default(*outputp, ¶ms); - err = snd_rawmidi_params(*outputp, ¶ms); - assert(err >= 0); - } - return 0; ++ return cnt; ++} + -+ _err: -+ if (open_func) -+ snd_dlobj_cache_put(open_func); -+ if (type_conf) -+ snd_config_delete(type_conf); ++/** ++ * \brief Free myvalue list ++ * \param list myvalue list ++ */ ++static void myvalue_list_free(struct list_head *list) ++{ ++ struct list_head *pos, *npos; ++ struct myvalue *value; ++ ++ list_for_each_safe(pos, npos, list) { ++ value = list_entry(pos, struct myvalue, list); ++ list_del(&value->list); ++ free(value); ++ } ++} ++ ++/** ++ * \brief Merge one value to the myvalue list ++ * \param list The list with values ++ * \param value The value to be merged (without duplicates) ++ * \return 1 if dup, 0 if success, otherwise a negative error code ++ */ ++static int merge_value(struct list_head *list, const char *text) ++{ ++ struct list_head *pos; ++ struct myvalue *value; ++ ++ list_for_each(pos, list) { ++ value = list_entry(pos, struct myvalue, list); ++ if (strcmp(value->text, text) == 0) ++ return 1; ++ } ++ value = malloc(sizeof(*value)); ++ if (value == NULL) ++ return -ENOMEM; ++ value->text = text; ++ list_add_tail(&value->list, list); ++ return 0; ++} ++ ++/** ++ * \brief Find all values for given identifier ++ * \param list Returned list ++ * \param source Source list with ucm_value structures ++ * \return Zero if success, otherwise a negative error code ++ */ ++static int add_identifiers(struct list_head *list, ++ struct list_head *source) ++{ ++ struct ucm_value *v; ++ struct list_head *pos; ++ int err; ++ ++ list_for_each(pos, source) { ++ v = list_entry(pos, struct ucm_value, list); ++ err = merge_value(list, v->name); ++ if (err < 0) ++ return err; ++ } ++ return 0; ++} ++ ++/** ++ * \brief Find all values for given identifier ++ * \param list Returned list ++ * \param identifier Identifier ++ * \param source Source list with ucm_value structures ++ */ + static int add_values(struct list_head *list, + const char *identifier, + struct list_head *source) + { +- struct ucm_value *v; +- struct myvalue *val; +- struct list_head *pos, *pos1; +- int match; ++ struct ucm_value *v; ++ struct list_head *pos; ++ int err; + +- list_for_each(pos, source) { +- v = list_entry(pos, struct ucm_value, list); +- if (check_identifier(identifier, v->name)) { +- match = 0; +- list_for_each(pos1, list) { +- val = list_entry(pos1, struct myvalue, list); +- if (strcmp(val->value, v->data) == 0) { +- match = 1; +- break; +- } +- } +- if (!match) { +- val = malloc(sizeof(struct myvalue)); +- if (val == NULL) +- return -ENOMEM; +- val->value = v->data; +- list_add_tail(&val->list, list); +- } +- } +- } +- return 0; ++ list_for_each(pos, source) { ++ v = list_entry(pos, struct ucm_value, list); ++ if (check_identifier(identifier, v->name)) { ++ err = merge_value(list, v->data); ++ if (err < 0) ++ return err; ++ } ++ } ++ return 0; ++} ++ ++/** ++ * \brief compare two identifiers ++ */ ++static int identifier_cmp(const void *_a, const void *_b) ++{ ++ const char * const *a = _a; ++ const char * const *b = _b; ++ return strcmp(*a, *b); ++} ++ ++/** ++ * \brief Get list of available identifiers ++ * \param list Returned list ++ * \param name Name of verb or modifier to query ++ * \return Number of list entries if success, otherwise a negative error code ++ */ ++static int get_identifiers_list(snd_use_case_mgr_t *uc_mgr, ++ const char **list[], char *name) ++{ ++ struct use_case_verb *verb; ++ struct use_case_modifier *modifier; ++ struct use_case_device *device; ++ struct list_head mylist; ++ struct list_head *value_list; ++ char *str, **res; ++ int err; ++ ++ if (!name) ++ return -ENOENT; ++ ++ str = strchr(name, '/'); ++ if (str) { ++ *str = '\0'; ++ verb = find_verb(uc_mgr, str + 1); ++ } ++ else { ++ verb = uc_mgr->active_verb; ++ } ++ if (!verb) ++ return -ENOENT; ++ ++ value_list = NULL; ++ modifier = find_modifier(uc_mgr, verb, name, 0); ++ if (modifier) { ++ value_list = &modifier->value_list; ++ } else { ++ device = find_device(uc_mgr, verb, name, 0); ++ if (device) ++ value_list = &device->value_list; ++ } ++ if (value_list == NULL) ++ return -ENOENT; ++ ++ INIT_LIST_HEAD(&mylist); ++ err = add_identifiers(&mylist, &uc_mgr->value_list); ++ if (err < 0) ++ goto __fail; ++ err = add_identifiers(&mylist, &verb->value_list); ++ if (err < 0) ++ goto __fail; ++ err = add_identifiers(&mylist, value_list); ++ if (err < 0) ++ goto __fail; ++ err = myvalue_to_str_list(&mylist, &res); ++ if (err > 0) ++ *list = (const char **)res; ++ else if (err == 0) ++ *list = NULL; ++__fail: ++ myvalue_list_free(&mylist); ++ if (err <= 0) ++ return err; ++ qsort(*list, err, sizeof(char *), identifier_cmp); + return err; } - static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, -@@ -350,8 +345,8 @@ int snd_rawmidi_close(snd_rawmidi_t *rawmidi) - assert(rawmidi); - err = rawmidi->ops->close(rawmidi); - free(rawmidi->name); -- if (rawmidi->dl_handle) -- snd_dlclose(rawmidi->dl_handle); -+ if (rawmidi->open_func) -+ snd_dlobj_cache_put(rawmidi->open_func); - free(rawmidi); - return err; + /** +@@ -1258,8 +1416,7 @@ static int get_value_list(snd_use_case_mgr_t *uc_mgr, + const char **list[], + char *verbname) + { +- struct list_head mylist, *pos, *npos; +- struct myvalue *val; ++ struct list_head mylist, *pos; + struct use_case_verb *verb; + struct use_case_device *dev; + struct use_case_modifier *mod; +@@ -1292,26 +1449,13 @@ static int get_value_list(snd_use_case_mgr_t *uc_mgr, + if (err < 0) + goto __fail; + } +- err = alloc_str_list(&mylist, 1, &res); +- if (err >= 0) { ++ err = myvalue_to_str_list(&mylist, &res); ++ if (err > 0) + *list = (const char **)res; +- list_for_each(pos, &mylist) { +- val = list_entry(pos, struct myvalue, list); +- *res = strdup(val->value); +- if (*res == NULL) { +- snd_use_case_free_list((const char **)res, err); +- err = -ENOMEM; +- goto __fail; +- } +- res++; +- } +- } ++ else if (err == 0) ++ *list = NULL; + __fail: +- list_for_each_safe(pos, npos, &mylist) { +- val = list_entry(pos, struct myvalue, list); +- list_del(&val->list); +- free(val); +- } ++ myvalue_list_free(&mylist); + return err; } -diff --git a/src/rawmidi/rawmidi_local.h b/src/rawmidi/rawmidi_local.h -index d76b35a3..721e1ec9 100644 ---- a/src/rawmidi/rawmidi_local.h -+++ b/src/rawmidi/rawmidi_local.h -@@ -37,7 +37,7 @@ typedef struct { - } snd_rawmidi_ops_t; - struct _snd_rawmidi { -- void *dl_handle; -+ void *open_func; - char *name; - snd_rawmidi_type_t type; - snd_rawmidi_stream_t stream; +@@ -1381,21 +1525,23 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + } else { + str = NULL; + } +- if (check_identifier(identifier, "_devices")) +- err = get_device_list(uc_mgr, list, str); ++ if (check_identifier(identifier, "_devices")) ++ err = get_device_list(uc_mgr, list, str); + else if (check_identifier(identifier, "_modifiers")) +- err = get_modifier_list(uc_mgr, list, str); +- else if (check_identifier(identifier, "_supporteddevs")) +- err = get_supported_device_list(uc_mgr, list, str); +- else if (check_identifier(identifier, "_conflictingdevs")) +- err = get_conflicting_device_list(uc_mgr, list, str); ++ err = get_modifier_list(uc_mgr, list, str); ++ else if (check_identifier(identifier, "_identifiers")) ++ err = get_identifiers_list(uc_mgr, list, str); ++ else if (check_identifier(identifier, "_supporteddevs")) ++ err = get_supported_device_list(uc_mgr, list, str); ++ else if (check_identifier(identifier, "_conflictingdevs")) ++ err = get_conflicting_device_list(uc_mgr, list, str); + else if (identifier[0] == '_') + err = -ENOENT; +- else +- err = get_value_list(uc_mgr, identifier, list, str); +- if (str) +- free(str); +- } ++ else ++ err = get_value_list(uc_mgr, identifier, list, str); ++ if (str) ++ free(str); ++ } + __end: + pthread_mutex_unlock(&uc_mgr->mutex); + return err; -- 2.20.1 -From 6efa23f2837a6fa9982b4f34b837401a66941ee3 Mon Sep 17 00:00:00 2001 +From 5ee5ef31b5ff3fb7c904054cb9cac7478a727f7c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela -Date: Fri, 24 May 2019 20:45:26 +0200 -Subject: [PATCH 19/25] rawmidi_hw: add sanity check for the invalid stream - arguments (coverity) +Date: Sun, 1 Dec 2019 14:26:40 +0100 +Subject: [PATCH 04/16] namehint: correct the @args check + +BugLink: https://github.com/alsa-project/alsa-plugins/issues/3 +Signed-off-by: Jaroslav Kysela +--- + src/control/namehint.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/control/namehint.c b/src/control/namehint.c +index 808df6b5..4927ef97 100644 +--- a/src/control/namehint.c ++++ b/src/control/namehint.c +@@ -348,6 +348,12 @@ static int try_config(snd_config_t *config, + goto __cleanup; + if (snd_config_search(res, "@args", &cfg) >= 0) { + snd_config_for_each(i, next, cfg) { ++ /* skip the argument list */ ++ snd_config_get_id(snd_config_iterator_entry(i), &str); ++ while (*str && *str >= '0' && *str <= '9') str++; ++ if (*str == '\0') ++ continue; ++ /* the argument definition must have the default */ + if (snd_config_search(snd_config_iterator_entry(i), + "default", NULL) < 0) { + err = -EINVAL; +-- +2.20.1 + + +From 6055f8a584296abfc0cec0439ceb708f0eddcc9d Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 1 Dec 2019 14:30:54 +0100 +Subject: [PATCH 05/16] namehint: improve the previous patch (check the + returned value) Signed-off-by: Jaroslav Kysela --- - src/rawmidi/rawmidi_hw.c | 2 ++ + src/control/namehint.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/control/namehint.c b/src/control/namehint.c +index 4927ef97..60c48ae3 100644 +--- a/src/control/namehint.c ++++ b/src/control/namehint.c +@@ -349,7 +349,8 @@ static int try_config(snd_config_t *config, + if (snd_config_search(res, "@args", &cfg) >= 0) { + snd_config_for_each(i, next, cfg) { + /* skip the argument list */ +- snd_config_get_id(snd_config_iterator_entry(i), &str); ++ if (snd_config_get_id(snd_config_iterator_entry(i), &str) < 0) ++ continue; + while (*str && *str >= '0' && *str <= '9') str++; + if (*str == '\0') + continue; +-- +2.20.1 + + +From 4dddcf733d56a13f4d042fefa1fb6230c09f1f65 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 2 Dec 2019 11:56:30 +0100 +Subject: [PATCH 06/16] ucm: docs - allow spaces in device names for JackHWMute + +Signed-off-by: Jaroslav Kysela +--- + include/use-case.h | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/include/use-case.h b/include/use-case.h +index 85c58ac0..e1f58027 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -326,7 +326,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * - Valid values: "soft" (software attenuation) + * - EDIDFile + * - Path to EDID file for HDMI devices +- * - JackControl, JackDev, JackHWMute ++ * - JackControl, JackDev + * - Jack information for a device. The jack status can be reported via + * a kcontrol and/or via an input device. **JackControl** is the + * kcontrol name of the jack, and **JackDev** is the input device id of +@@ -334,17 +334,18 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * JackDev value should be "foo"). UCM configuration files should + * contain both JackControl and JackDev when possible, because + * applications are likely to support only one or the other. +- * +- * If **JackHWMute** is set, it indicates that when the jack is plugged +- * in, the hardware automatically mutes some other device(s). The +- * JackHWMute value is a space-separated list of device names (this +- * isn't compatible with device names with spaces in them, so don't use +- * such device names!). Note that JackHWMute should be used only when +- * the hardware enforces the automatic muting. If the hardware doesn't +- * enforce any muting, it may still be tempting to set JackHWMute to +- * trick upper software layers to e.g. automatically mute speakers when +- * headphones are plugged in, but that's application policy +- * configuration that doesn't belong to UCM configuration files. ++ * - JackHWMute ++ * If this value is set, it indicates that when the jack is plugged ++ * in, the hardware automatically mutes some other device(s). The ++ * value is a space-separated list of device names. If the device ++ * name contains space, it must be enclosed to ' or ", e.g.: ++ * JackHWMute "'Dock Headphone' Headphone" ++ * Note that JackHWMute should be used only when the hardware enforces ++ * the automatic muting. If the hardware doesn't enforce any muting, it ++ * may still be tempting to set JackHWMute to trick upper software layers ++ * to e.g. automatically mute speakers when headphones are plugged in, ++ * but that's application policy configuration that doesn't belong ++ * to UCM configuration files. + * - MinBufferLevel + * - This is used on platform where reported buffer level is not accurate. + * E.g. "512", which holds 512 samples in device buffer. Note: this will +-- +2.20.1 + + +From 2a286ca9a8415571181ce58027686ec332a834e9 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 2 Dec 2019 11:57:18 +0100 +Subject: [PATCH 07/16] use-case: docs - add PlaybackMixerCopy and + CaptureMixerCopy + +Signed-off-by: Jaroslav Kysela +--- + include/use-case.h | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/include/use-case.h b/include/use-case.h +index e1f58027..71fcc949 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -309,8 +309,14 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * - PlaybackMixerElem + * - mixer element playback identifier + * - can be parsed using snd_use_case_parse_selem_id() ++ * - PlaybackMixerCopy ++ * - additional mixer element playback identifier ++ * - can be parsed using snd_use_case_parse_selem_id() ++ * - those elements should copy the volume and switch settings ++ * - element identifiers are separated using the | character + * - PlaybackMasterElem + * - mixer element playback identifier for the master control ++ * - can be parsed using snd_use_case_parse_selem_id() + * - PlaybackMasterType + * - type of the master volume control + * - Valid values: "soft" (software attenuation) +@@ -319,8 +325,14 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * - CaptureMixerElem + * - mixer element capture identifier + * - can be parsed using snd_use_case_parse_selem_id() ++ * - CaptureMixerCopy ++ * - additional mixer element capture identifier ++ * - can be parsed using snd_use_case_parse_selem_id() ++ * - those elements should copy the volume and switch settings ++ * - element identifiers are separated using the | character + * - CaptureMasterElem + * - mixer element playback identifier for the master control ++ * - can be parsed using snd_use_case_parse_selem_id() + * - CaptureMasterType + * - type of the master volume control + * - Valid values: "soft" (software attenuation) +-- +2.20.1 + + +From a0fc4447bb7c7f9a850a0a85f3a5a32c1509caf4 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 3 Dec 2019 15:01:04 +0100 +Subject: [PATCH 08/16] ucm: docs - add JackCTL, rearrange JackControl and + JackDev + +Signed-off-by: Jaroslav Kysela +--- + include/use-case.h | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/include/use-case.h b/include/use-case.h +index 71fcc949..25998cb9 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -338,14 +338,20 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * - Valid values: "soft" (software attenuation) + * - EDIDFile + * - Path to EDID file for HDMI devices +- * - JackControl, JackDev +- * - Jack information for a device. The jack status can be reported via +- * a kcontrol and/or via an input device. **JackControl** is the +- * kcontrol name of the jack, and **JackDev** is the input device id of +- * the jack (if the full input device path is /dev/input/by-id/foo, the +- * JackDev value should be "foo"). UCM configuration files should +- * contain both JackControl and JackDev when possible, because +- * applications are likely to support only one or the other. ++ * - JackCTL ++ * - jack control device name ++ * - JackControl ++ * - jack control identificator ++ * - can be parsed using snd_use_case_parse_ctl_elem_id() ++ * - UCM configuration files should contain both JackControl and JackDev ++ * when possible, because applications are likely to support only one ++ * or the other ++ * - JackDev ++ * - the input device id of the jack (if the full input device path is ++ * /dev/input/by-id/foo, the JackDev value should be "foo") ++ * - UCM configuration files should contain both JackControl and JackDev ++ * when possible, because applications are likely to support only one ++ * or the other + * - JackHWMute + * If this value is set, it indicates that when the jack is plugged + * in, the hardware automatically mutes some other device(s). The +-- +2.20.1 + + +From e59034a0bec257cc7422a1e9436d936be8696a6f Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 3 Dec 2019 18:27:39 +0100 +Subject: [PATCH 09/16] ucm: Do not fail to parse configs on cards with an + empty CardComponents lists + +Since the UCM profiles for all Bay- and Cherry-Trail SST cards have been +moved over to UCM2, parsing them fails with: + +ALSA lib ucm_subs.c:220:(uc_mgr_get_substituted_value) variable '${CardComponents}' is not defined in this context! + +This completely breaks audio support on all Bay- and Cherry-Trail devices. + +This is caused by these non-SOF ASoC using cards having an empty +CardComponents list. Which in itself is fine, but is rejected by +the ucm_subs.c code. This commit changes the ucm_subs code to accept +an empty string as a valid value for CardComponents restoring audio +functionality on these boards. + +Signed-off-by: Hans de Goede +Signed-off-by: Jaroslav Kysela +--- + src/ucm/ucm_subs.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c +index 00afa9e3..90e395f0 100644 +--- a/src/ucm/ucm_subs.c ++++ b/src/ucm/ucm_subs.c +@@ -25,6 +25,7 @@ + */ + + #include "ucm_local.h" ++#include + #include + #include + +@@ -145,10 +146,11 @@ static char *rval_sysfs(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char + return strdup(path); + } + +-#define MATCH_VARIABLE(name, id, fcn) \ ++#define MATCH_VARIABLE(name, id, fcn, empty_ok) \ + if (strncmp((name), (id), sizeof(id) - 1) == 0) { \ + rval = fcn(uc_mgr); \ + idsize = sizeof(id) - 1; \ ++ allow_empty = (empty_ok); \ + goto __rval; \ + } + +@@ -189,12 +191,14 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr, + + while (*value) { + if (*value == '$' && *(value+1) == '{') { +- MATCH_VARIABLE(value, "${ConfName}", rval_conf_name); +- MATCH_VARIABLE(value, "${CardId}", rval_card_id); +- MATCH_VARIABLE(value, "${CardDriver}", rval_card_driver); +- MATCH_VARIABLE(value, "${CardName}", rval_card_name); +- MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname); +- MATCH_VARIABLE(value, "${CardComponents}", rval_card_components); ++ bool allow_empty = false; ++ ++ MATCH_VARIABLE(value, "${ConfName}", rval_conf_name, false); ++ MATCH_VARIABLE(value, "${CardId}", rval_card_id, false); ++ MATCH_VARIABLE(value, "${CardDriver}", rval_card_driver, false); ++ MATCH_VARIABLE(value, "${CardName}", rval_card_name, false); ++ MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname, false); ++ MATCH_VARIABLE(value, "${CardComponents}", rval_card_components, true); + MATCH_VARIABLE2(value, "${env:", rval_env); + MATCH_VARIABLE2(value, "${sys:", rval_sysfs); + err = -EINVAL; +@@ -208,7 +212,7 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr, + } + goto __error; + __rval: +- if (rval == NULL || rval[0] == '\0') { ++ if (rval == NULL || (!allow_empty && rval[0] == '\0')) { + free(rval); + strncpy(r, value, idsize); + r[idsize] = '\0'; +-- +2.20.1 + + +From 8e2c70add782f997f7c269ed3f722888e56ff024 Mon Sep 17 00:00:00 2001 +From: Fabrice Fontaine +Date: Tue, 3 Dec 2019 18:56:40 +0100 +Subject: [PATCH 10/16] src/ucm/main.c: fix build without mixer + +Commit 4ce38a5ff466d18039b2606938f866ea3a6c9f3c breaks the build without +mixer on: + + CCLD libasound.la +/home/buildroot/autobuild/instance-1/output-1/host/lib/gcc/xtensa-buildroot-linux-uclibc/8.3.0/../../../../xtensa-buildroot-linux-uclibc/bin/ld: ucm/.libs/libucm.a(main.o): in function `snd_use_case_set': +main.c:(.text+0x185c): undefined reference to `snd_mixer_selem_id_parse' + +Fixes: http://autobuild.buildroot.org/results/4d91c9f82a2a61c50c457a851073b85cc09ea345 + +Signed-off-by: Fabrice Fontaine +Signed-off-by: Jaroslav Kysela +--- + src/ucm/main.c | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/src/rawmidi/rawmidi_hw.c b/src/rawmidi/rawmidi_hw.c -index 7cc8c0d1..eaa8a76d 100644 ---- a/src/rawmidi/rawmidi_hw.c -+++ b/src/rawmidi/rawmidi_hw.c -@@ -186,6 +186,8 @@ int snd_rawmidi_hw_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, - *inputp = NULL; - if (outputp) - *outputp = NULL; -+ if (!inputp && !outputp) -+ return -EINVAL; - - if ((ret = snd_ctl_hw_open(&ctl, NULL, card, 0)) < 0) - return ret; --- -2.20.1 - - -From 0d97f53c25b4dd36d3f6511fae85b597aebc61a1 Mon Sep 17 00:00:00 2001 -From: Jaroslav Kysela -Date: Fri, 24 May 2019 20:52:00 +0200 -Subject: [PATCH 20/25] topology: various coverity fixes - -Signed-off-by: Jaroslav Kysela ---- - src/topology/ctl.c | 4 ++-- - src/topology/data.c | 19 +++++++++++++------ - src/topology/parser.c | 5 +++-- - 3 files changed, 18 insertions(+), 10 deletions(-) - -diff --git a/src/topology/ctl.c b/src/topology/ctl.c -index 9c13b12c..a0962522 100644 ---- a/src/topology/ctl.c -+++ b/src/topology/ctl.c -@@ -880,8 +880,8 @@ int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, - if (enum_ctl->texts != NULL) { - for (i = 0; i < num_items; i++) { - if (enum_ctl->texts[i] != NULL) -- strncpy(ec->texts[i], enum_ctl->texts[i], -- SNDRV_CTL_ELEM_ID_NAME_MAXLEN); -+ snd_strlcpy(ec->texts[i], enum_ctl->texts[i], -+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN); - } - } - -diff --git a/src/topology/data.c b/src/topology/data.c -index fd72abbb..aa2b87e7 100644 ---- a/src/topology/data.c -+++ b/src/topology/data.c -@@ -124,12 +124,12 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem) - - if (fclose(fp) == EOF) { - SNDERR("Cannot close data file."); -- ret = -errno; -- goto err; -+ return -errno; - } - return 0; - - err: -+ fclose(fp); - if (priv) - free(priv); - return ret; -@@ -422,7 +422,7 @@ static unsigned int get_tuple_size(int type) - static int copy_tuples(struct tplg_elem *elem, - struct tplg_vendor_tuples *tuples, struct tplg_vendor_tokens *tokens) +diff --git a/src/ucm/main.c b/src/ucm/main.c +index d2078a23..61922f10 100644 +--- a/src/ucm/main.c ++++ b/src/ucm/main.c +@@ -2115,8 +2115,10 @@ int snd_use_case_parse_selem_id(snd_mixer_selem_id_t *dst, + const char *ucm_id, + const char *value) { -- struct snd_soc_tplg_private *priv = elem->data; -+ struct snd_soc_tplg_private *priv = elem->data, *priv2; - struct tplg_tuple_set *tuple_set; - struct tplg_tuple *tuple; - struct snd_soc_tplg_vendor_array *array; -@@ -447,10 +447,17 @@ static int copy_tuples(struct tplg_elem *elem, - return -EINVAL; - } - -- if (priv != NULL) -- priv = realloc(priv, sizeof(*priv) + size); -- else -+ if (priv != NULL) { -+ priv2 = realloc(priv, sizeof(*priv) + size); -+ if (priv2 == NULL) { -+ free(priv); -+ priv = NULL; -+ } else { -+ priv = priv2; -+ } -+ } else { - priv = calloc(1, sizeof(*priv) + size); -+ } - if (!priv) - return -ENOMEM; - -diff --git a/src/topology/parser.c b/src/topology/parser.c -index cfc20e00..a7cff1c3 100644 ---- a/src/topology/parser.c -+++ b/src/topology/parser.c -@@ -237,8 +237,9 @@ static int tplg_load_config(const char *file, snd_config_t **cfg) - - ret = snd_input_stdio_attach(&in, fp, 1); - if (ret < 0) { -+ fclose(fp); - SNDERR("error: could not attach stdio %s", file); -- goto err; -+ return ret; - } - ret = snd_config_top(&top); - if (ret < 0) -@@ -261,7 +262,7 @@ static int tplg_load_config(const char *file, snd_config_t **cfg) - err_load: - snd_config_delete(top); - err: -- fclose(fp); -+ snd_input_close(in); - return ret; ++#ifdef BUILD_MIXER + if (strcmp(ucm_id, "PlaybackMixerId") == 0 || + strcmp(ucm_id, "CaptureMixerId") == 0) + return snd_mixer_selem_id_parse(dst, value); ++#endif + return -EINVAL; } - -- 2.20.1 -From ed156a218644e3334bc452ef2bc948409735c330 Mon Sep 17 00:00:00 2001 +From ad8527d81b09c4d0edd054b5b1468ce1c50b23cb Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela -Date: Fri, 24 May 2019 21:11:00 +0200 -Subject: [PATCH 21/25] ucm: coverity fixes +Date: Wed, 4 Dec 2019 09:49:40 +0100 +Subject: [PATCH 11/16] alsa.m4: another try to fix the libatopology detection Signed-off-by: Jaroslav Kysela --- - src/ucm/parser.c | 18 ++++++++++++++---- - src/ucm/utils.c | 12 +++++++++--- - 2 files changed, 23 insertions(+), 7 deletions(-) + utils/alsa.m4 | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) -diff --git a/src/ucm/parser.c b/src/ucm/parser.c -index ad6bcec7..61d5d7f9 100644 ---- a/src/ucm/parser.c -+++ b/src/ucm/parser.c -@@ -1114,7 +1114,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr, - if (err < 0) { - uc_error("error: %s failed to parse verb", - file); -- return err; -+ goto _err; - } - continue; - } -@@ -1126,7 +1126,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr, - if (err < 0) { - uc_error("error: %s failed to parse device", - file); -- return err; -+ goto _err; - } - continue; - } -@@ -1138,18 +1138,24 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr, - if (err < 0) { - uc_error("error: %s failed to parse modifier", - file); -- return err; -+ goto _err; - } - continue; - } - } +diff --git a/utils/alsa.m4 b/utils/alsa.m4 +index 4c457f0d..320e4336 100644 +--- a/utils/alsa.m4 ++++ b/utils/alsa.m4 +@@ -22,6 +22,7 @@ alsa_save_CFLAGS="$CFLAGS" + alsa_save_LDFLAGS="$LDFLAGS" + alsa_save_LIBS="$LIBS" + alsa_found=yes ++alsa_topology_found=no -+ snd_config_delete(cfg); -+ - /* use case verb must have at least 1 device */ - if (list_empty(&verb->device_list)) { - uc_error("error: no use case device defined", file); - return -EINVAL; - } - return 0; -+ -+ _err: -+ snd_config_delete(cfg); -+ return err; - } + dnl + dnl Get the cflags and libraries for alsa +@@ -158,11 +159,17 @@ AC_CHECK_LIB([asound], [snd_ctl_open],, + alsa_found=no] + ) + if test "x$enable_atopology" = "xyes"; then ++alsa_topology_found=yes + AC_CHECK_LIB([atopology], [snd_tplg_new],, + [ifelse([$3], , [AC_MSG_ERROR(No linkable libatopology was found.)]) +- alsa_found=no] ++ alsa_topology_found=no, ++] + ) + fi ++else ++if test "x$enable_atopology" = "xyes"; then ++ alsa_topology_found=yes ++fi + fi - /* -@@ -1399,6 +1405,7 @@ next_card: - - return -1; - } -+ - static int load_master_config(const char *card_name, snd_config_t **cfg) - { - char filename[MAX_FILE]; -@@ -1610,8 +1617,11 @@ int uc_mgr_scan_master_configs(const char **_list[]) - } - free(namelist); - -- if (err >= 0) -+ if (err >= 0) { - *_list = list; -+ } else { -+ free(list); -+ } - - return err; - } -diff --git a/src/ucm/utils.c b/src/ucm/utils.c -index 14227e0a..efd5a979 100644 ---- a/src/ucm/utils.c -+++ b/src/ucm/utils.c -@@ -58,14 +58,18 @@ int uc_mgr_config_load(const char *file, snd_config_t **cfg) - int err; - - fp = fopen(file, "r"); -- err = fp == NULL ? -errno : snd_input_stdio_attach(&in, fp, 1); -- if (err < 0) { -+ if (!fp) { -+ err = -errno; -+ __err0: - uc_error("could not open configuration file %s", file); - return err; - } -+ err = snd_input_stdio_attach(&in, fp, 1); -+ if (err < 0) -+ goto __err0; - err = snd_config_top(&top); - if (err < 0) -- return err; -+ goto __err1; - - default_path = getenv(ALSA_CONFIG_UCM_VAR); - if (!default_path || !*default_path) -@@ -88,6 +92,8 @@ int uc_mgr_config_load(const char *file, snd_config_t **cfg) - - __err2: - snd_config_delete(top); -+ __err1: -+ snd_input_close(in); - return err; - } + if test "x$alsa_found" = "xyes" ; then +@@ -183,7 +190,7 @@ fi + dnl add the alsa topology library; must be at the end + AC_MSG_CHECKING(for ALSA topology LDFLAGS) +-if test "x$enable_atopology" = "xyes"; then ++if test "x$alsa_topology_found" = "xyes"; then + ALSA_TOPOLOGY_LIBS="$ALSA_TOPOLOGY_LIBS -latopology" + fi + AC_MSG_RESULT($ALSA_TOPOLOGY_LIBS) -- 2.20.1 -From 022c790aabc300eabad4da8947a3f2bdadce41e1 Mon Sep 17 00:00:00 2001 +From 555a5dbdabc5ed3be1ca81865abdb997bc3a6082 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela -Date: Mon, 27 May 2019 13:57:12 +0200 -Subject: [PATCH 22/25] pcm_file: coverity fixes (including double locking) +Date: Thu, 5 Dec 2019 16:59:05 +0100 +Subject: [PATCH 12/16] ucm: docs - add Mic/DigitalMic and multiple devices + comments Signed-off-by: Jaroslav Kysela --- - src/pcm/pcm_file.c | 16 ++++++---------- - 1 file changed, 6 insertions(+), 10 deletions(-) + include/use-case.h | 8 ++++++++ + 1 file changed, 8 insertions(+) -diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c -index 99db3754..54142a3d 100644 ---- a/src/pcm/pcm_file.c -+++ b/src/pcm/pcm_file.c -@@ -296,7 +296,10 @@ static int snd_pcm_file_areas_read_infile(snd_pcm_t *pcm, - return -ENOMEM; - } - -- bytes = read(file->ifd, file->rbuf, snd_pcm_frames_to_bytes(pcm, frames)); -+ bytes = snd_pcm_frames_to_bytes(pcm, frames); -+ if (bytes < 0) -+ return bytes; -+ bytes = read(file->ifd, file->rbuf, bytes); - if (bytes < 0) { - SYSERR("read from file failed, error: %d", bytes); - return bytes; -@@ -589,18 +592,14 @@ static snd_pcm_sframes_t snd_pcm_file_readi(snd_pcm_t *pcm, void *buffer, snd_pc - snd_pcm_channel_area_t areas[pcm->channels]; - snd_pcm_sframes_t frames; - -- __snd_pcm_lock(pcm); -- - frames = _snd_pcm_readi(file->gen.slave, buffer, size); -- if (frames <= 0) { -- __snd_pcm_unlock(pcm); -+ if (frames <= 0) - return frames; -- } - - snd_pcm_areas_from_buf(pcm, areas, buffer); - snd_pcm_file_areas_read_infile(pcm, areas, 0, frames); -+ __snd_pcm_lock(pcm); - snd_pcm_file_add_frames(pcm, areas, 0, frames); -- - __snd_pcm_unlock(pcm); - - return frames; -@@ -654,9 +653,6 @@ static int snd_pcm_file_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t - snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames) - { - snd_pcm_file_t *file = pcm->private_data; -- snd_pcm_channel_area_t areas_if[pcm->channels]; -- snd_pcm_uframes_t frames_if; -- void *buffer = NULL; - int result; - - result = snd_pcm_mmap_begin(file->gen.slave, areas, offset, frames); +diff --git a/include/use-case.h b/include/use-case.h +index 25998cb9..1736da25 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -114,10 +114,18 @@ extern "C" { + * + * Physical system devices the render and capture audio. Devices can be OR'ed + * together to support audio on simultaneous devices. ++ * ++ * If multiple devices with the same name exists, the number suffixes should ++ * be added to these names like HDMI1,HDMI2,HDMI3 etc. No number gaps are ++ * allowed. The names with numbers must be continuous. ++ * ++ * The preference of the devices is determined by the priority value. + */ + #define SND_USE_CASE_DEV_NONE "None" /**< None Device */ + #define SND_USE_CASE_DEV_SPEAKER "Speaker" /**< Speaker Device */ + #define SND_USE_CASE_DEV_LINE "Line" /**< Line Device */ ++#define SND_USE_CASE_DEV_MIC "Mic" /**< Integrated Analog Microphone */ ++#define SND_USE_CASE_DEV_DIGITAL_MIC "DigitalMic" /**< Integrated Digital Microphone */ + #define SND_USE_CASE_DEV_HEADPHONES "Headphones" /**< Headphones Device */ + #define SND_USE_CASE_DEV_HEADSET "Headset" /**< Headset Device */ + #define SND_USE_CASE_DEV_HANDSET "Handset" /**< Handset Device */ -- 2.20.1 -From c6e7fd8b1e0d8729c7220734ca0b529c35d926ed Mon Sep 17 00:00:00 2001 +From 1ad660ddeecb2a364f1ca62aa60f256f7029cfdc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela -Date: Mon, 27 May 2019 14:05:12 +0200 -Subject: [PATCH 23/25] topology: next round of coverity fixes +Date: Thu, 5 Dec 2019 17:01:31 +0100 +Subject: [PATCH 13/16] ucm: docs - remove DigitalMic, it does not have sense Signed-off-by: Jaroslav Kysela --- - src/topology/data.c | 5 ++--- - src/topology/parser.c | 7 +++++-- - 2 files changed, 7 insertions(+), 5 deletions(-) + include/use-case.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) -diff --git a/src/topology/data.c b/src/topology/data.c -index aa2b87e7..b3f4421f 100644 ---- a/src/topology/data.c -+++ b/src/topology/data.c -@@ -88,8 +88,7 @@ static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem) - if (fp == NULL) { - SNDERR("error: invalid data file path '%s'\n", - filename); -- ret = -errno; -- goto err; -+ return -errno; - } - - fseek(fp, 0L, SEEK_END); -@@ -463,6 +462,7 @@ static int copy_tuples(struct tplg_elem *elem, - - off = priv->size; - priv->size = size; /* update private data size */ -+ elem->data = priv; - - array = (struct snd_soc_tplg_vendor_array *)(priv->data + off); - array->size = set_size; -@@ -499,7 +499,6 @@ static int copy_tuples(struct tplg_elem *elem, - } - } - -- elem->data = priv; - return 0; - } - -diff --git a/src/topology/parser.c b/src/topology/parser.c -index a7cff1c3..5940692d 100644 ---- a/src/topology/parser.c -+++ b/src/topology/parser.c -@@ -253,8 +253,10 @@ static int tplg_load_config(const char *file, snd_config_t **cfg) - } - - ret = snd_input_close(in); -- if (ret < 0) -+ if (ret < 0) { -+ in = NULL; - goto err_load; -+ } - - *cfg = top; - return 0; -@@ -262,7 +264,8 @@ static int tplg_load_config(const char *file, snd_config_t **cfg) - err_load: - snd_config_delete(top); - err: -- snd_input_close(in); -+ if (in) -+ snd_input_close(in); - return ret; - } - +diff --git a/include/use-case.h b/include/use-case.h +index 1736da25..214a2a4c 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -124,8 +124,7 @@ extern "C" { + #define SND_USE_CASE_DEV_NONE "None" /**< None Device */ + #define SND_USE_CASE_DEV_SPEAKER "Speaker" /**< Speaker Device */ + #define SND_USE_CASE_DEV_LINE "Line" /**< Line Device */ +-#define SND_USE_CASE_DEV_MIC "Mic" /**< Integrated Analog Microphone */ +-#define SND_USE_CASE_DEV_DIGITAL_MIC "DigitalMic" /**< Integrated Digital Microphone */ ++#define SND_USE_CASE_DEV_MIC "Mic" /**< Integrated Microphone */ + #define SND_USE_CASE_DEV_HEADPHONES "Headphones" /**< Headphones Device */ + #define SND_USE_CASE_DEV_HEADSET "Headset" /**< Headset Device */ + #define SND_USE_CASE_DEV_HANDSET "Handset" /**< Handset Device */ -- 2.20.1 -From ac6df1106c314de5d027176d910b9bc43a1fa7f9 Mon Sep 17 00:00:00 2001 +From 5473c5d677915b88d5c93d5bcc6cd16bb6a40342 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela -Date: Mon, 27 May 2019 20:10:32 +0200 -Subject: [PATCH 24/25] pcm_file: another locking fix (coverity) +Date: Thu, 5 Dec 2019 17:19:06 +0100 +Subject: [PATCH 14/16] ucm: docs - change the Mic description to simple + Microphone Device Signed-off-by: Jaroslav Kysela --- - src/pcm/pcm_file.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) + include/use-case.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c -index 54142a3d..1ef80b59 100644 ---- a/src/pcm/pcm_file.c -+++ b/src/pcm/pcm_file.c -@@ -612,18 +612,16 @@ static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm - snd_pcm_channel_area_t areas[pcm->channels]; - snd_pcm_sframes_t frames; - -- __snd_pcm_lock(pcm); - frames = _snd_pcm_readn(file->gen.slave, bufs, size); -- if (frames <= 0) { -- __snd_pcm_unlock(pcm); -+ if (frames <= 0) - return frames; -- } - - snd_pcm_areas_from_bufs(pcm, areas, bufs); - snd_pcm_file_areas_read_infile(pcm, areas, 0, frames); -+ __snd_pcm_lock(pcm); - snd_pcm_file_add_frames(pcm, areas, 0, frames); -- - __snd_pcm_unlock(pcm); -+ - return frames; - } - +diff --git a/include/use-case.h b/include/use-case.h +index 214a2a4c..b04f7b9d 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -124,7 +124,7 @@ extern "C" { + #define SND_USE_CASE_DEV_NONE "None" /**< None Device */ + #define SND_USE_CASE_DEV_SPEAKER "Speaker" /**< Speaker Device */ + #define SND_USE_CASE_DEV_LINE "Line" /**< Line Device */ +-#define SND_USE_CASE_DEV_MIC "Mic" /**< Integrated Microphone */ ++#define SND_USE_CASE_DEV_MIC "Mic" /**< Microphone Device */ + #define SND_USE_CASE_DEV_HEADPHONES "Headphones" /**< Headphones Device */ + #define SND_USE_CASE_DEV_HEADSET "Headset" /**< Headset Device */ + #define SND_USE_CASE_DEV_HANDSET "Handset" /**< Handset Device */ -- 2.20.1 -From 5905af199670ca34eaaafbd3319d94d230b7e4d4 Mon Sep 17 00:00:00 2001 +From ca67e823833213e140a09ce43b6399b7676616df Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela -Date: Mon, 27 May 2019 20:10:52 +0200 -Subject: [PATCH 25/25] ucm: another coverity fix in uc_mgr_config_load() +Date: Fri, 6 Dec 2019 11:11:54 +0100 +Subject: [PATCH 15/16] ucm: docs - add note about the sequences and device + split +Signed-off-by: Jaroslav Kysela --- - src/ucm/utils.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) + include/use-case.h | 5 +++++ + 1 file changed, 5 insertions(+) -diff --git a/src/ucm/utils.c b/src/ucm/utils.c -index efd5a979..5607304e 100644 ---- a/src/ucm/utils.c -+++ b/src/ucm/utils.c -@@ -85,15 +85,18 @@ int uc_mgr_config_load(const char *file, snd_config_t **cfg) - goto __err2; - } - err = snd_input_close(in); -- if (err < 0) -+ if (err < 0) { -+ in = NULL; - goto __err2; -+ } - *cfg = top; - return 0; - - __err2: -- snd_config_delete(top); -+ snd_config_delete(top); - __err1: -- snd_input_close(in); -+ if (in) -+ snd_input_close(in); - return err; - } - +diff --git a/include/use-case.h b/include/use-case.h +index b04f7b9d..2efcb4d8 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -119,6 +119,11 @@ extern "C" { + * be added to these names like HDMI1,HDMI2,HDMI3 etc. No number gaps are + * allowed. The names with numbers must be continuous. + * ++ * If EnableSequence/DisableSequence controls independent paths in the hardware ++ * it is also recommended to split playback and capture UCM devices and use ++ * the number suffixes. Example use case: Use the integrated microphone ++ * in the laptop instead the microphone in headphones. ++ * + * The preference of the devices is determined by the priority value. + */ + #define SND_USE_CASE_DEV_NONE "None" /**< None Device */ +-- +2.20.1 + + +From f828dfe549fbab0a920768c63ebd3478272954eb Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 10 Dec 2019 11:48:06 +0100 +Subject: [PATCH 16/16] ucm: docs - remove MixerCopy values, add Priority for + verb, improve priority docs + +Signed-off-by: Jaroslav Kysela +--- + include/use-case.h | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +diff --git a/include/use-case.h b/include/use-case.h +index 2efcb4d8..134303af 100644 +--- a/include/use-case.h ++++ b/include/use-case.h +@@ -274,6 +274,10 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * Recommended names for values: + * - TQ + * - Tone Quality ++ * - Priority ++ * - priority value (1-10000), higher value means higher priority ++ * - valid only for verbs ++ * - for devices - PlaybackPriority and CapturePriority + * - PlaybackPCM + * - full PCM playback device name + * - PlaybackPCMIsDummy +@@ -301,7 +305,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * - playback control switch identifier string + * - can be parsed using snd_use_case_parse_ctl_elem_id() + * - PlaybackPriority +- * - priority value (1-10000), default value is 100, higher value means lower priority ++ * - priority value (1-10000), higher value means higher priority + * - CaptureRate + * - capture device sample rate + * - CaptureChannels +@@ -315,17 +319,12 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * - capture control switch identifier string + * - can be parsed using snd_use_case_parse_ctl_elem_id() + * - CapturePriority +- * - priority value (1-10000), default value is 100, higher value means lower priority ++ * - priority value (1-10000), higher value means higher priority + * - PlaybackMixer + * - name of playback mixer + * - PlaybackMixerElem + * - mixer element playback identifier + * - can be parsed using snd_use_case_parse_selem_id() +- * - PlaybackMixerCopy +- * - additional mixer element playback identifier +- * - can be parsed using snd_use_case_parse_selem_id() +- * - those elements should copy the volume and switch settings +- * - element identifiers are separated using the | character + * - PlaybackMasterElem + * - mixer element playback identifier for the master control + * - can be parsed using snd_use_case_parse_selem_id() +@@ -337,11 +336,6 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, + * - CaptureMixerElem + * - mixer element capture identifier + * - can be parsed using snd_use_case_parse_selem_id() +- * - CaptureMixerCopy +- * - additional mixer element capture identifier +- * - can be parsed using snd_use_case_parse_selem_id() +- * - those elements should copy the volume and switch settings +- * - element identifiers are separated using the | character + * - CaptureMasterElem + * - mixer element playback identifier for the master control + * - can be parsed using snd_use_case_parse_selem_id() -- 2.20.1 diff --git a/SOURCES/sof-hda-dsp-HiFi.conf b/SOURCES/sof-hda-dsp-HiFi.conf new file mode 100644 index 0000000..a97b34f --- /dev/null +++ b/SOURCES/sof-hda-dsp-HiFi.conf @@ -0,0 +1,169 @@ +# Use case Configuration for sof-hda-dsp + +SectionVerb { + EnableSequence [ + cset "name='Auto-Mute Mode' 'Disabled'" + cset "name='Master Playback Volume' 100" + cset "name='Speaker Playback Volume' 100" + cset "name='Headphone Playback Volume' 100" + cset "name='Capture Volume' 50" + cset "name='Mic Boost Volume' 100" + cset "name='Dmic0 Capture Volume' 100" + ] +} + +SectionDevice."Headphones1" { + Comment "Headphones" + + EnableSequence [ + cset "name='Headphone Playback Switch' on" + ] + + DisableSequence [ + cset "name='Headphone Playback Switch' off" + ] + + Value { + PlaybackPriority 200 + PlaybackPCM "hw:${CardId},0" + PlaybackMixerElem "Headphone" + PlaybackMixerMaster "Master" + PlaybackVolume "Headphone Playback Volume" + PlaybackSwitch "Headphone Playback Switch" + PlaybackChannels "2" + If.jack { + Condition { + Type ControlExists + Control "iface=CARD,name='Headphone Mic Jack'" + } + True { + JackControl "Headphone Mic Jack" + } + False { + JackControl "Headphone Jack" + } + } + } +} + +SectionDevice."Speaker" { + Comment "Speaker" + + If.seq { + Condition { + Type ControlExists + Control "name='Bass Speaker Playback Switch'" + } + True { + EnableSequence [ + cset "name='Speaker Playback Switch' on" + cset "name='Bass Speaker Playback Switch' on" + ] + + DisableSequence [ + cset "name='Speaker Playback Switch' off" + cset "name='Bass Speaker Playback Switch' off" + ] + } + False { + EnableSequence [ + cset "name='Speaker Playback Switch' on" + ] + + DisableSequence [ + cset "name='Speaker Playback Switch' off" + ] + } + } + + Value { + PlaybackPriority 100 + PlaybackPCM "hw:${CardId},0" + PlaybackMixerElem "Speaker" + PlaybackMasterElem "Master" + PlaybackVolume "Speaker Playback Volume" + PlaybackSwitch "Speaker Playback Switch" + PlaybackChannels "2" + } +} + +If.monomic { + Condition { + Type ControlExists + Control "name='Input Source'" + ControlEnum "Headphone Mic" + } + After.SectionDevice "Mic" + True { + SectionDevice."Headphones2" { + Comment "Headphones Stereo Microphone" + + ConflictingDevice [ + "HeadsetMic" + ] + + EnableSequence [ + cset "name='Input Source' 'Headphone Mic'" + ] + + Value { + CapturePriority 200 + + JackControl "Headphone Mic Jack" + } + } + + SectionDevice."Headset" { + Comment "Headset Mono Microphone" + + EnableSequence [ + cset "name='Input Source' Headset Mic" + ] + + Value { + CapturePriority 300 + + JackControl "Headphone Mic Jack" + } + } + } + False { + SectionDevice."Headphones2" { + Comment "Headphones Stereo Microphone" + + Value { + CapturePriority 200 + + JackControl "Mic Jack" + } + } + } +} + +SectionDevice."Mic" { + Comment "Digital Microphone" + + Value { + CapturePriority 100 + CapturePCM "hw:${CardId},6" + CaptureChannels 4 + If.vol { + Condition { + Type ControlExists + Control "name='Dmic0 Capture Switch'" + } + True { + CaptureMixerElem "Dmic0" + CaptureVolume "Dmic0 Capture Volume" + CaptureSwitch "Dmic0 Capture Switch" + } + False { + # v1.3 SOF firmware + CaptureMixerElem "PGA10.0 10 Master" + CaptureVolume "PGA10.0 10 Master Capture Volume" + } + } + } +} + + diff --git a/SPECS/alsa-lib.spec b/SPECS/alsa-lib.spec index 1469320..aada023 100644 --- a/SPECS/alsa-lib.spec +++ b/SPECS/alsa-lib.spec @@ -2,18 +2,25 @@ #define prever_dot .rc3 #define postver a +%define version_alsa_lib 1.2.1.2 +%define version_alsa_ucm 1.2.1.2 +%define version_alsa_tplg 1.2.1 + Summary: The Advanced Linux Sound Architecture (ALSA) library Name: alsa-lib -Version: 1.1.9 -Release: 4%{?prever_dot}%{?dist} +Version: %{version_alsa_lib} +Release: 2%{?prever_dot}%{?dist} License: LGPLv2+ Group: System Environment/Libraries URL: http://www.alsa-project.org/ Source: ftp://ftp.alsa-project.org/pub/lib/%{name}-%{version}%{?prever}%{?postver}.tar.bz2 +Source1: ftp://ftp.alsa-project.org/pub/lib/alsa-ucm-conf-%{version_alsa_ucm}.tar.bz2 +Source2: ftp://ftp.alsa-project.org/pub/lib/alsa-topology-conf-%{version_alsa_tplg}.tar.bz2 Source10: asound.conf Source11: modprobe-dist-alsa.conf Source12: modprobe-dist-oss.conf +Source20: sof-hda-dsp-HiFi.conf Patch0: alsa-git.patch Patch1: alsa-lib-1.1.9-config.patch Patch2: alsa-lib-1.0.14-glibc-open.patch @@ -47,7 +54,8 @@ against the ALSA libraries and interfaces. Summary: ALSA Use Case Manager configuration Group: System Environment/Libraries BuildArch: noarch -Requires: %{name} = %{version}-%{release} +License: BSD +Requires: %{name} >= %{version_alsa_ucm} %description -n alsa-ucm The Advanced Linux Sound Architecture (ALSA) Universal Configuration @@ -57,7 +65,8 @@ Manager allows configuration of Audio input/output names and routing Summary: ALSA Topology configuration Group: System Environment/Libraries BuildArch: noarch -Requires: %{name} = %{version}-%{release} +License: BSD +Requires: %{name} >= %{version_alsa_tplg} %description -n alsa-topology The Advanced Linux Sound Architecture (ALSA) topology configuration @@ -89,6 +98,8 @@ make DESTDIR=%{buildroot} install mkdir -p %{buildroot}/%{_lib} mv %{buildroot}%{_libdir}/libasound.so.* %{buildroot}/%{_lib} ln -snf ../../%{_lib}/libasound.so.2 %{buildroot}%{_libdir}/libasound.so +mv %{buildroot}%{_libdir}/libatopology.so.* %{buildroot}/%{_lib} +ln -snf ../../%{_lib}/libatopology.so.2 %{buildroot}%{_libdir}/libatopology.so # Install global configuration files mkdir -p -m 755 %{buildroot}/etc @@ -100,12 +111,23 @@ install -p -m 644 %{SOURCE11} %{buildroot}%{sysmodprobedir}/dist-alsa.conf # bug#926973, place this file to the doc directory install -p -m 644 %{SOURCE12} . -# Create UCM directory +# Create UCM directories mkdir -p %{buildroot}/%{_datadir}/alsa/ucm +mkdir -p %{buildroot}/%{_datadir}/alsa/ucm2 + +# Unpack UCMs +tar xvjf %{SOURCE1} -C %{buildroot}/%{_datadir}/alsa ucm ucm2 + +# Workaround for old pulseaudio +if [ "%version_alsa_ucm" != "1.2.1.2" ]; then echo "Remove!"; exit 1; fi +cp %{SOURCE20} %{buildroot}/%{_datadir}/alsa/ucm2/sof-hda-dsp/HiFi.conf # Create topology directory mkdir -p %{buildroot}/%{_datadir}/alsa/topology +# Unpack topologies +tar xvjf %{SOURCE2} -C %{buildroot}/%{_datadir}/alsa topology + # Remove libtool archives. find %{buildroot} -name '*.la' -delete @@ -122,10 +144,12 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %doc doc/asoundrc.txt modprobe-dist-oss.conf %config %{_sysconfdir}/asound.conf /%{_lib}/libasound.so.* +/%{_lib}/libatopology.so.* %{_bindir}/aserver #{_libdir}/alsa-lib/ %{_datadir}/alsa/ %exclude %{_datadir}/alsa/ucm +%exclude %{_datadir}/alsa/ucm2 %exclude %{_datadir}/alsa/topology %{sysmodprobedir}/dist-* @@ -134,16 +158,28 @@ rm %{buildroot}/%{_includedir}/asoundlib.h %{_includedir}/alsa/ %{_includedir}/sys/asoundlib.h %{_libdir}/libasound.so +%{_libdir}/libatopology.so %{_libdir}/pkgconfig/alsa.pc +%{_libdir}/pkgconfig/alsa-topology.pc %{_datadir}/aclocal/alsa.m4 %files -n alsa-ucm +# BSD %{_datadir}/alsa/ucm +%{_datadir}/alsa/ucm2 %files -n alsa-topology +# BSD %{_datadir}/alsa/topology %changelog +* Tue Dec 10 2019 Jaroslav Kysela - 1.2.1.2-2 +- Updated to 1.2.1.2 +- UCM fixes + +* Fri Nov 15 2019 Jaroslav Kysela - 1.2.1-2 +- Updated to 1.2.1 + * Mon May 27 2019 Jaroslav Kysela - 1.1.9-4 - Moved topology files to alsa-topology - Updated to 1.1.9