mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-04 13:30:08 -05:00
pcm: pcm_ioplug - fix the avail_update mmap capture copy issue
It seems that the commit "pcm: ioplug: Transfer all available data"
introduced new regressions (wrong memory access). The second issue
is that the avail_update in ioplug does not move appl_ptr nor hw_ptr,
so it's possible that the transfers may be repetitive.
This patch moves the transfer calls to mmap_begin callback where it
should be. The pointer wraps are handled by design now.
Fixes: 1714332719 ("pcm: ioplug: Transfer all available data")
BugLink: https://github.com/alsa-project/alsa-lib/pull/103
Tested-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
55d59821ff
commit
00eafe98ee
3 changed files with 50 additions and 32 deletions
|
|
@ -7218,8 +7218,7 @@ int snd_pcm_mmap_begin(snd_pcm_t *pcm,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DOC_HIDDEN
|
#ifndef DOC_HIDDEN
|
||||||
/* locked version */
|
int __snd_pcm_mmap_begin_generic(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
|
||||||
int __snd_pcm_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_uframes_t *offset, snd_pcm_uframes_t *frames)
|
||||||
{
|
{
|
||||||
snd_pcm_uframes_t cont;
|
snd_pcm_uframes_t cont;
|
||||||
|
|
@ -7229,9 +7228,6 @@ int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
|
||||||
|
|
||||||
assert(pcm && areas && offset && frames);
|
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 */
|
/* fallback for plugins that do not specify new callback */
|
||||||
xareas = snd_pcm_mmap_areas(pcm);
|
xareas = snd_pcm_mmap_areas(pcm);
|
||||||
if (xareas == NULL)
|
if (xareas == NULL)
|
||||||
|
|
@ -7250,6 +7246,18 @@ int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
|
||||||
*frames = f;
|
*frames = f;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* locked version */
|
||||||
|
int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
|
||||||
|
snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
|
||||||
|
{
|
||||||
|
assert(pcm && areas && offset && frames);
|
||||||
|
|
||||||
|
if (pcm->fast_ops->mmap_begin)
|
||||||
|
return pcm->fast_ops->mmap_begin(pcm->fast_op_arg, areas, offset, frames);
|
||||||
|
|
||||||
|
return __snd_pcm_mmap_begin_generic(pcm, areas, offset, frames);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -697,6 +697,38 @@ static snd_pcm_sframes_t snd_pcm_ioplug_readn(snd_pcm_t *pcm, void **bufs, snd_p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_ioplug_mmap_begin_capture(snd_pcm_t *pcm,
|
||||||
|
const snd_pcm_channel_area_t **areas,
|
||||||
|
snd_pcm_uframes_t *offset,
|
||||||
|
snd_pcm_uframes_t *frames)
|
||||||
|
{
|
||||||
|
ioplug_priv_t *io = pcm->private_data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = __snd_pcm_mmap_begin_generic(pcm, areas, offset, frames);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (io->data->callback->transfer &&
|
||||||
|
pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
|
||||||
|
pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
|
||||||
|
snd_pcm_sframes_t result;
|
||||||
|
result = io->data->callback->transfer(io->data, *areas, *offset, *frames);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_ioplug_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
|
||||||
|
snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
|
||||||
|
{
|
||||||
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
||||||
|
return __snd_pcm_mmap_begin_generic(pcm, areas, offset, frames);
|
||||||
|
return snd_pcm_ioplug_mmap_begin_capture(pcm, areas, offset, frames);
|
||||||
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_ioplug_mmap_commit(snd_pcm_t *pcm,
|
static snd_pcm_sframes_t snd_pcm_ioplug_mmap_commit(snd_pcm_t *pcm,
|
||||||
snd_pcm_uframes_t offset,
|
snd_pcm_uframes_t offset,
|
||||||
snd_pcm_uframes_t size)
|
snd_pcm_uframes_t size)
|
||||||
|
|
@ -707,7 +739,7 @@ static snd_pcm_sframes_t snd_pcm_ioplug_mmap_commit(snd_pcm_t *pcm,
|
||||||
const snd_pcm_channel_area_t *areas;
|
const snd_pcm_channel_area_t *areas;
|
||||||
snd_pcm_uframes_t ofs, frames = size;
|
snd_pcm_uframes_t ofs, frames = size;
|
||||||
|
|
||||||
__snd_pcm_mmap_begin(pcm, &areas, &ofs, &frames);
|
__snd_pcm_mmap_begin_generic(pcm, &areas, &ofs, &frames);
|
||||||
if (ofs != offset)
|
if (ofs != offset)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
return ioplug_priv_transfer_areas(pcm, areas, offset, frames);
|
return ioplug_priv_transfer_areas(pcm, areas, offset, frames);
|
||||||
|
|
@ -727,31 +759,6 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
|
|
||||||
avail = snd_pcm_mmap_avail(pcm);
|
avail = snd_pcm_mmap_avail(pcm);
|
||||||
if (pcm->stream == SND_PCM_STREAM_CAPTURE &&
|
|
||||||
pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED &&
|
|
||||||
pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
|
|
||||||
if (io->data->callback->transfer) {
|
|
||||||
const snd_pcm_channel_area_t *areas;
|
|
||||||
snd_pcm_uframes_t offset, size = UINT_MAX;
|
|
||||||
snd_pcm_sframes_t result;
|
|
||||||
|
|
||||||
__snd_pcm_mmap_begin(pcm, &areas, &offset, &size);
|
|
||||||
result = io->data->callback->transfer(io->data, areas, offset, size);
|
|
||||||
if (result < 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
/* If the available data doesn't fit in the
|
|
||||||
contiguous area at the end of the mmap we
|
|
||||||
must transfer the remaining data to the
|
|
||||||
beginning of the mmap. */
|
|
||||||
if (size < avail) {
|
|
||||||
result = io->data->callback->transfer(io->data, areas,
|
|
||||||
0, avail - size);
|
|
||||||
if (result < 0)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (avail > io->avail_max)
|
if (avail > io->avail_max)
|
||||||
io->avail_max = avail;
|
io->avail_max = avail;
|
||||||
return (snd_pcm_sframes_t)avail;
|
return (snd_pcm_sframes_t)avail;
|
||||||
|
|
@ -947,6 +954,7 @@ static const snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
|
||||||
.poll_descriptors_count = snd_pcm_ioplug_poll_descriptors_count,
|
.poll_descriptors_count = snd_pcm_ioplug_poll_descriptors_count,
|
||||||
.poll_descriptors = snd_pcm_ioplug_poll_descriptors,
|
.poll_descriptors = snd_pcm_ioplug_poll_descriptors,
|
||||||
.poll_revents = snd_pcm_ioplug_poll_revents,
|
.poll_revents = snd_pcm_ioplug_poll_revents,
|
||||||
|
.mmap_begin = snd_pcm_ioplug_mmap_begin,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !DOC_HIDDEN */
|
#endif /* !DOC_HIDDEN */
|
||||||
|
|
|
||||||
|
|
@ -420,6 +420,8 @@ int _snd_pcm_poll_descriptor(snd_pcm_t *pcm);
|
||||||
#define _snd_pcm_async_descriptor _snd_pcm_poll_descriptor /* FIXME */
|
#define _snd_pcm_async_descriptor _snd_pcm_poll_descriptor /* FIXME */
|
||||||
|
|
||||||
/* locked versions */
|
/* locked versions */
|
||||||
|
int __snd_pcm_mmap_begin_generic(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
|
||||||
|
snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames);
|
||||||
int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
|
int __snd_pcm_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_uframes_t *offset, snd_pcm_uframes_t *frames);
|
||||||
snd_pcm_sframes_t __snd_pcm_mmap_commit(snd_pcm_t *pcm,
|
snd_pcm_sframes_t __snd_pcm_mmap_commit(snd_pcm_t *pcm,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue