diff --git a/.alsa-lib.metadata b/.alsa-lib.metadata new file mode 100644 index 0000000..c9df5ae --- /dev/null +++ b/.alsa-lib.metadata @@ -0,0 +1 @@ +2404e1c377428908c5188076d5652a2a1ecd028e SOURCES/alsa-lib-1.1.9.tar.bz2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7200175 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/alsa-lib-1.1.9.tar.bz2 diff --git a/SOURCES/alsa-git.patch b/SOURCES/alsa-git.patch new file mode 100644 index 0000000..2662484 --- /dev/null +++ b/SOURCES/alsa-git.patch @@ -0,0 +1,2202 @@ +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 + +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. + +Signed-off-by: Vanitha Channaiah +Signed-off-by: Takashi Iwai +--- + 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(-) + +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) + { + 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); + 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 + +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 +--- + 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 ++++++-- + 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); + + frames = _snd_pcm_readi(file->gen.slave, buffer, size); +- if (frames <= 0) ++ if (frames <= 0) { ++ __snd_pcm_unlock(pcm); + return frames; ++ } + + 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); +-- +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 + +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 +--- + 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 + +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; + + 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; + } + ++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; + } + +@@ -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; + } + +@@ -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; ++ } + } 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++; ++ } + 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; ++ ++ _err: ++ if (open_func) ++ snd_dlobj_cache_put(open_func); ++ if (type_conf) ++ snd_config_delete(type_conf); ++ 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; + } +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; +-- +2.20.1 + + +From 6efa23f2837a6fa9982b4f34b837401a66941ee3 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) + +Signed-off-by: Jaroslav Kysela +--- + src/rawmidi/rawmidi_hw.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) + { +- 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; + } + +-- +2.20.1 + + +From ed156a218644e3334bc452ef2bc948409735c330 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 + +Signed-off-by: Jaroslav Kysela +--- + src/ucm/parser.c | 18 ++++++++++++++---- + src/ucm/utils.c | 12 +++++++++--- + 2 files changed, 23 insertions(+), 7 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; + } + } + ++ 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; + } + + /* +@@ -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; + } + +-- +2.20.1 + + +From 022c790aabc300eabad4da8947a3f2bdadce41e1 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) + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_file.c | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +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); +-- +2.20.1 + + +From c6e7fd8b1e0d8729c7220734ca0b529c35d926ed 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 + +Signed-off-by: Jaroslav Kysela +--- + src/topology/data.c | 5 ++--- + src/topology/parser.c | 7 +++++-- + 2 files changed, 7 insertions(+), 5 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; + } + +-- +2.20.1 + + +From ac6df1106c314de5d027176d910b9bc43a1fa7f9 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) + +Signed-off-by: Jaroslav Kysela +--- + src/pcm/pcm_file.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +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; + } + +-- +2.20.1 + + +From 5905af199670ca34eaaafbd3319d94d230b7e4d4 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() + +--- + src/ucm/utils.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +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; + } + +-- +2.20.1 + diff --git a/SOURCES/alsa-lib-1.0.14-glibc-open.patch b/SOURCES/alsa-lib-1.0.14-glibc-open.patch new file mode 100644 index 0000000..bc625bd --- /dev/null +++ b/SOURCES/alsa-lib-1.0.14-glibc-open.patch @@ -0,0 +1,11 @@ +--- alsa-lib-1.0.14/aserver/aserver.c 2007-05-31 10:05:13.000000000 +0200 ++++ alsa-lib-1.0.14.lennart/aserver/aserver.c 2007-08-15 15:53:32.000000000 +0200 +@@ -35,6 +35,8 @@ + + #include "aserver.h" + ++#undef open ++ + char *command; + + #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) diff --git a/SOURCES/alsa-lib-1.1.9-config.patch b/SOURCES/alsa-lib-1.1.9-config.patch new file mode 100644 index 0000000..f8c2c59 --- /dev/null +++ b/SOURCES/alsa-lib-1.1.9-config.patch @@ -0,0 +1,44 @@ +diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf +index 09980586..c4525f0b 100644 +--- a/src/conf/alsa.conf ++++ b/src/conf/alsa.conf +@@ -67,8 +67,7 @@ defaults.pcm.nonblock 1 + defaults.pcm.compat 0 + defaults.pcm.minperiodtime 5000 # in us + defaults.pcm.ipc_key 5678293 +-defaults.pcm.ipc_gid audio +-defaults.pcm.ipc_perm 0660 ++defaults.pcm.ipc_perm 0600 + defaults.pcm.dmix.max_periods 0 + defaults.pcm.dmix.channels 2 + defaults.pcm.dmix.rate 48000 +diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf +index 7fa5c8b2..97936a82 100644 +--- a/src/conf/pcm/dmix.conf ++++ b/src/conf/pcm/dmix.conf +@@ -48,10 +48,6 @@ pcm.!dmix { + @func refer + name defaults.pcm.ipc_key + } +- ipc_gid { +- @func refer +- name defaults.pcm.ipc_gid +- } + ipc_perm { + @func refer + name defaults.pcm.ipc_perm +diff --git a/src/conf/pcm/dsnoop.conf b/src/conf/pcm/dsnoop.conf +index abbd44f7..528fb6ad 100644 +--- a/src/conf/pcm/dsnoop.conf ++++ b/src/conf/pcm/dsnoop.conf +@@ -41,10 +41,6 @@ pcm.!dsnoop { + @func refer + name defaults.pcm.ipc_key + } +- ipc_gid { +- @func refer +- name defaults.pcm.ipc_gid +- } + ipc_perm { + @func refer + name defaults.pcm.ipc_perm diff --git a/SOURCES/asound.conf b/SOURCES/asound.conf new file mode 100644 index 0000000..da7ab7c --- /dev/null +++ b/SOURCES/asound.conf @@ -0,0 +1,3 @@ +# +# Place your global alsa-lib configuration here... +# diff --git a/SOURCES/modprobe-dist-alsa.conf b/SOURCES/modprobe-dist-alsa.conf new file mode 100644 index 0000000..cf31fa6 --- /dev/null +++ b/SOURCES/modprobe-dist-alsa.conf @@ -0,0 +1,9 @@ +# ALSA Sound Support +# +# We want to ensure that snd-seq is always loaded for those who want to use +# the sequencer interface, but we can't do this automatically through udev +# at the moment...so we have this rule (just for the moment). +# +# Remove the following line if you don't want the sequencer. + +install snd-pcm /sbin/modprobe --ignore-install snd-pcm && /sbin/modprobe snd-seq diff --git a/SOURCES/modprobe-dist-oss.conf b/SOURCES/modprobe-dist-oss.conf new file mode 100644 index 0000000..21f93cc --- /dev/null +++ b/SOURCES/modprobe-dist-oss.conf @@ -0,0 +1,8 @@ +# OSS Sound Support +# This has been disabled in F11 onwards because it can interfere with the +# PulseAudio sound service (a legacy OSS application can prevent PulseAudio +# applications from playing sound by preventing PulseAudio from (re-)opening +# the sound device). To re-enable support, copy this file to +# the /etc/modprobe.d directory. +# +install snd-pcm /sbin/modprobe --ignore-install snd-pcm && /sbin/modprobe snd-pcm-oss && /sbin/modprobe snd-seq-device && /sbin/modprobe snd-seq-oss diff --git a/SPECS/alsa-lib.spec b/SPECS/alsa-lib.spec new file mode 100644 index 0000000..1469320 --- /dev/null +++ b/SPECS/alsa-lib.spec @@ -0,0 +1,322 @@ +#define prever rc3 +#define prever_dot .rc3 +#define postver a + +Summary: The Advanced Linux Sound Architecture (ALSA) library +Name: alsa-lib +Version: 1.1.9 +Release: 4%{?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 +Source10: asound.conf +Source11: modprobe-dist-alsa.conf +Source12: modprobe-dist-oss.conf +Patch0: alsa-git.patch +Patch1: alsa-lib-1.1.9-config.patch +Patch2: alsa-lib-1.0.14-glibc-open.patch + +BuildRequires: doxygen +BuildRequires: autoconf automake libtool +Requires(post): /sbin/ldconfig, coreutils + +%description +The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI +functionality to the Linux operating system. + +This package includes the ALSA runtime libraries to simplify application +programming and provide higher level functionality as well as support for +the older OSS API, providing binary compatibility for most OSS programs. + +%package devel +Summary: Development files from the ALSA library +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig + +%description devel +The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI +functionality to the Linux operating system. + +This package includes the ALSA development libraries for developing +against the ALSA libraries and interfaces. + +%package -n alsa-ucm +Summary: ALSA Use Case Manager configuration +Group: System Environment/Libraries +BuildArch: noarch +Requires: %{name} = %{version}-%{release} + +%description -n alsa-ucm +The Advanced Linux Sound Architecture (ALSA) Universal Configuration +Manager allows configuration of Audio input/output names and routing + +%package -n alsa-topology +Summary: ALSA Topology configuration +Group: System Environment/Libraries +BuildArch: noarch +Requires: %{name} = %{version}-%{release} + +%description -n alsa-topology +The Advanced Linux Sound Architecture (ALSA) topology configuration +contains alsa-lib configuration of SoC topology + +%prep +%setup -q -n %{name}-%{version}%{?prever}%{?postver} +%patch0 -p1 -b .alsa-git +%patch1 -p1 -b .config +%patch2 -p1 -b .glibc-open + +%build +autoreconf -vif +%configure --disable-aload --with-plugindir=%{_libdir}/alsa-lib --disable-alisp + +# Remove useless /usr/lib64 rpath on 64bit archs +sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool +sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool + +make %{?_smp_mflags} V=1 +make doc + +%install +%global sysmodprobedir %{_prefix}/lib/modprobe.d + +make DESTDIR=%{buildroot} install + +# We need the library to be available even before /usr might be mounted +mkdir -p %{buildroot}/%{_lib} +mv %{buildroot}%{_libdir}/libasound.so.* %{buildroot}/%{_lib} +ln -snf ../../%{_lib}/libasound.so.2 %{buildroot}%{_libdir}/libasound.so + +# Install global configuration files +mkdir -p -m 755 %{buildroot}/etc +install -p -m 644 %{SOURCE10} %{buildroot}/etc + +# Install the modprobe files for ALSA +mkdir -p -m 755 %{buildroot}%{sysmodprobedir} +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 +mkdir -p %{buildroot}/%{_datadir}/alsa/ucm + +# Create topology directory +mkdir -p %{buildroot}/%{_datadir}/alsa/topology + +# Remove libtool archives. +find %{buildroot} -name '*.la' -delete + +# Remove /usr/include/asoundlib.h +rm %{buildroot}/%{_includedir}/asoundlib.h + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc doc/asoundrc.txt modprobe-dist-oss.conf +%config %{_sysconfdir}/asound.conf +/%{_lib}/libasound.so.* +%{_bindir}/aserver +#{_libdir}/alsa-lib/ +%{_datadir}/alsa/ +%exclude %{_datadir}/alsa/ucm +%exclude %{_datadir}/alsa/topology +%{sysmodprobedir}/dist-* + +%files devel +%doc TODO doc/doxygen/ +%{_includedir}/alsa/ +%{_includedir}/sys/asoundlib.h +%{_libdir}/libasound.so +%{_libdir}/pkgconfig/alsa.pc +%{_datadir}/aclocal/alsa.m4 + +%files -n alsa-ucm +%{_datadir}/alsa/ucm + +%files -n alsa-topology +%{_datadir}/alsa/topology + +%changelog +* Mon May 27 2019 Jaroslav Kysela - 1.1.9-4 +- Moved topology files to alsa-topology +- Updated to 1.1.9 + +* Fri Jan 25 2019 Jaroslav Kysela - 1.1.6-3 +- Sync with the RHEL 7 +- Add Dell WD15/WD19 Dock to USB-Audio.conf and create UCM configs +- Resolves: rhbz#1664247 + +* Wed Apr 04 2018 Jaroslav Kysela - 1.1.6-2 +- Changed add-on directory to /etc/alsa/conf.d + +* Tue Apr 03 2018 Jaroslav Kysela - 1.1.6-1 +- Updated to 1.1.6 + +* Wed Feb 07 2018 Fedora Release Engineering - 1.1.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Tue Nov 14 2017 Jaroslav Kysela - 1.1.5-1 +- Updated to 1.1.5 + +* Wed Aug 02 2017 Fedora Release Engineering - 1.1.4.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 1.1.4.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Tue Jun 13 2017 Jaroslav Kysela - 1.1.4.1-1 +- Updated to 1.1.4.1 + +* Fri May 12 2017 Jaroslav Kysela - 1.1.4-1 +- Updated to 1.1.4 + +* Mon Mar 20 2017 Peter Robinson 1.1.3-3 +- Add upstream patch for Raspberry Pi HDMI audio + +* Fri Feb 10 2017 Fedora Release Engineering - 1.1.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Tue Dec 20 2016 Jaroslav Kysela - 1.1.3-1 +- Updated to 1.1.3 + +* Tue Aug 2 2016 Jaroslav Kysela - 1.1.2-1 +- Updated to 1.1.2 + +* Tue Jul 19 2016 Bastien Nocera - 1.1.1-2 +- Add Surface 3 configuration file + +* Thu Mar 31 2016 Jaroslav Kysela - 1.1.1-1 +- Updated to 1.1.1 + +* Wed Feb 03 2016 Fedora Release Engineering - 1.1.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Mon Nov 9 2015 Jaroslav Kysela - 1.1.0-3 +- Replaced source files with the alsa-lib v1.1.0 final + +* Thu Nov 5 2015 Jaroslav Kysela - 1.1.0-2 +- Replaced source files with the alsa-lib v1.1.0 test2 + +* Tue Oct 27 2015 Jaroslav Kysela - 1.1.0-1 +- Updated to 1.1.0 test1 + +* Tue Jun 16 2015 Fedora Release Engineering - 1.0.29-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Thu Feb 26 2015 Jaroslav Kysela - 1.0.29-1 +- Updated to 1.0.29 + +* Sat Feb 21 2015 Till Maas - 1.0.28-4 +- Rebuilt for Fedora 23 Change + https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code + +* Tue Feb 3 2015 Peter Robinson 1.0.28-3 +- Add UCM sub package +- Use %%license + +* Fri Aug 15 2014 Fedora Release Engineering - 1.0.28-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Thu Jul 24 2014 Peter Robinson 1.0.28-1 +- Update to 1.0.28 + +* Sat Jun 07 2014 Fedora Release Engineering - 1.0.27.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Thu Aug 1 2013 Ville Skyttä - 1.0.27.2-2 +- Fix build with unversioned %%{_docdir_fmt}. + +* Mon Jul 08 2013 Jaroslav Kysela - 1.0.27.2-1 +- Updated to 1.0.27.2 + +* Thu May 30 2013 Jaroslav Kysela - 1.0.27.1-2 +- Fixed bug#953352 + +* Tue May 21 2013 Jaroslav Kysela - 1.0.27.1-1 +- Updated to 1.0.27.1 + +* Tue May 07 2013 Rex Dieter 1.0.27-3 +- pull in upstream fix for building in C90 mode + +* Thu Apr 11 2013 Jaroslav Kysela - 1.0.27-2 +- move dist-oss.conf to doc as modprobe-dist-oss.conf + +* Thu Apr 11 2013 Jaroslav Kysela - 1.0.27-1 +- Updated to 1.0.27 + +* Wed Apr 03 2013 Stephen Gallagher - 1.0.26-4 +- Add upstream patch to explicitly include sys/types.h + +* Wed Feb 13 2013 Fedora Release Engineering - 1.0.26-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Dec 3 2012 Peter Robinson 1.0.26-2 +- Create and own ucm directory so alsaucm doesn't crash. +- Cleanup and modernise spec + +* Thu Sep 6 2012 Jaroslav Kysela - 1.0.26-1 +- Updated to 1.0.26 + +* Thu Jul 26 2012 Michael Schwendt - 1.0.25-6 +- Don't package ancient ChangeLog that ends at alsa-lib 0.2.0 (#510212). + +* Wed Jul 18 2012 Fedora Release Engineering - 1.0.25-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed May 2 2012 Josh Boyer - 1.0.25-4 +- Install ALSA related module conf files + +* Wed Feb 1 2012 Jaroslav Kysela - 1.0.25-3 +- Remove the pulse audio configuration from /etc/asound.conf + +* Sat Jan 28 2012 Jaroslav Kysela - 1.0.25-1 +- Updated to 1.0.25 final + +* Thu Jan 12 2012 Fedora Release Engineering - 1.0.24-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Feb 07 2011 Fedora Release Engineering - 1.0.24-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Fri Jan 28 2011 Jaroslav Kysela - 1.0.24-1 +- Updated to 1.0.24 final + +* Tue Nov 9 2010 Jochen Schmitt 1.0.23-2 +- Set plugindir to %%{_libdir}/alsa-lib (bz#651507) + +* Fri Apr 16 2010 Jaroslav Kysela - 1.0.23-1 +- Updated to 1.0.23 final + +* Mon Dec 28 2009 Jaroslav Kysela - 1.0.22-1 +- Updated to 1.0.22 final +- Fix file descriptor leak in pcm_hw plugin +- Fix sound distortions for S24_LE - softvol plugin + +* Wed Sep 9 2009 Jaroslav Kysela - 1.0.21-3 +- Add Speaker and Beep control names to mixer weight list +- Fix redhat bug #521988 + +* Wed Sep 2 2009 Jaroslav Kysela - 1.0.21-1 +- Updated to 1.0.21 final + +* Fri Jul 24 2009 Fedora Release Engineering - 1.0.20-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed May 6 2009 Jaroslav Kysela - 1.0.20-1 +- Updated to 1.0.20 final + +* Mon Feb 23 2009 Fedora Release Engineering - 1.0.19-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Wed Feb 4 2009 Jaroslav Kysela - 1.0.19-2 +- Make doxygen documentation same for all architectures (bz#465205) + +* Tue Jan 20 2009 Jaroslav Kysela - 1.0.19-1 +- Updated to 1.0.19 final