mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -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,9 +7218,8 @@ 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;
 | 
				
			||||||
	snd_pcm_uframes_t f;
 | 
						snd_pcm_uframes_t f;
 | 
				
			||||||
| 
						 | 
					@ -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