mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-05 13:30:00 -05:00
pcm: hw: add a helper function to query status/control data
When executing ioctl(2) with some commands, applications can request ALSA PCM core to change appl_ptr in kernel space. Below is a list of such operations: - SNDRV_PCM_IOCTL_PREPARE - SNDRV_PCM_IOCTL_RESET - SNDRV_PCM_IOCTL_REWIND - SNDRV_PCM_IOCTL_FORWARD - SNDRV_PCM_IOCTL_WRITEI_FRAMES - SNDRV_PCM_IOCTL_WRITEN_FRAMES - SNDRV_PCM_IOCTL_READI_FRAMES - SNDRV_PCM_IOCTL_READN_FRAMES After these operations, the value of appl_ptr should be synchronized between kernel/user spaces. This commit adds a helper function to query status and control data without issuing the control data just in fallback from failure of control mapping. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
4396c83a4d
commit
ce0905c3ca
1 changed files with 34 additions and 12 deletions
|
|
@ -151,6 +151,20 @@ static int sync_ptr(snd_pcm_hw_t *hw, unsigned int flags)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int query_status_and_control_data(snd_pcm_hw_t *hw)
|
||||||
|
{
|
||||||
|
if (!hw->mmap_control_fallbacked)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query both of control/status data to avoid unexpected change of
|
||||||
|
* control data in kernel space.
|
||||||
|
*/
|
||||||
|
return sync_ptr1(hw,
|
||||||
|
SNDRV_PCM_SYNC_PTR_APPL |
|
||||||
|
SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw)
|
static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw)
|
||||||
{
|
{
|
||||||
if (hw->period_timer_need_poll) {
|
if (hw->period_timer_need_poll) {
|
||||||
|
|
@ -601,7 +615,7 @@ static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
|
||||||
SYSMSG("SNDRV_PCM_IOCTL_PREPARE failed (%i)", err);
|
SYSMSG("SNDRV_PCM_IOCTL_PREPARE failed (%i)", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL);
|
return query_status_and_control_data(hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_hw_reset(snd_pcm_t *pcm)
|
static int snd_pcm_hw_reset(snd_pcm_t *pcm)
|
||||||
|
|
@ -613,7 +627,7 @@ static int snd_pcm_hw_reset(snd_pcm_t *pcm)
|
||||||
SYSMSG("SNDRV_PCM_IOCTL_RESET failed (%i)", err);
|
SYSMSG("SNDRV_PCM_IOCTL_RESET failed (%i)", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL);
|
return query_status_and_control_data(hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_hw_start(snd_pcm_t *pcm)
|
static int snd_pcm_hw_start(snd_pcm_t *pcm)
|
||||||
|
|
@ -688,7 +702,7 @@ static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fra
|
||||||
SYSMSG("SNDRV_PCM_IOCTL_REWIND failed (%i)", err);
|
SYSMSG("SNDRV_PCM_IOCTL_REWIND failed (%i)", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
err = sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL);
|
err = query_status_and_control_data(hw);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return frames;
|
return frames;
|
||||||
|
|
@ -709,7 +723,7 @@ static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t fr
|
||||||
SYSMSG("SNDRV_PCM_IOCTL_FORWARD failed (%i)", err);
|
SYSMSG("SNDRV_PCM_IOCTL_FORWARD failed (%i)", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
err = sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL);
|
err = query_status_and_control_data(hw);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return frames;
|
return frames;
|
||||||
|
|
@ -805,8 +819,10 @@ static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, s
|
||||||
xferi.buf = (char*) buffer;
|
xferi.buf = (char*) buffer;
|
||||||
xferi.frames = size;
|
xferi.frames = size;
|
||||||
xferi.result = 0; /* make valgrind happy */
|
xferi.result = 0; /* make valgrind happy */
|
||||||
err = ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi);
|
if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi) < 0)
|
||||||
err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno;
|
err = -errno;
|
||||||
|
else
|
||||||
|
err = query_status_and_control_data(hw);
|
||||||
#ifdef DEBUG_RW
|
#ifdef DEBUG_RW
|
||||||
fprintf(stderr, "hw_writei: frames = %li, xferi.result = %li, err = %i\n", size, xferi.result, err);
|
fprintf(stderr, "hw_writei: frames = %li, xferi.result = %li, err = %i\n", size, xferi.result, err);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -824,8 +840,10 @@ static snd_pcm_sframes_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_
|
||||||
memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
|
memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
|
||||||
xfern.bufs = bufs;
|
xfern.bufs = bufs;
|
||||||
xfern.frames = size;
|
xfern.frames = size;
|
||||||
err = ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern);
|
if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern) < 0)
|
||||||
err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno;
|
err = -errno;
|
||||||
|
else
|
||||||
|
err = query_status_and_control_data(hw);
|
||||||
#ifdef DEBUG_RW
|
#ifdef DEBUG_RW
|
||||||
fprintf(stderr, "hw_writen: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
|
fprintf(stderr, "hw_writen: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -843,8 +861,10 @@ static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_
|
||||||
xferi.buf = buffer;
|
xferi.buf = buffer;
|
||||||
xferi.frames = size;
|
xferi.frames = size;
|
||||||
xferi.result = 0; /* make valgrind happy */
|
xferi.result = 0; /* make valgrind happy */
|
||||||
err = ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi);
|
if (ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi) < 0)
|
||||||
err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno;
|
err = -errno;
|
||||||
|
else
|
||||||
|
err = query_status_and_control_data(hw);
|
||||||
#ifdef DEBUG_RW
|
#ifdef DEBUG_RW
|
||||||
fprintf(stderr, "hw_readi: frames = %li, result = %li, err = %i\n", size, xferi.result, err);
|
fprintf(stderr, "hw_readi: frames = %li, result = %li, err = %i\n", size, xferi.result, err);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -862,8 +882,10 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u
|
||||||
memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
|
memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
|
||||||
xfern.bufs = bufs;
|
xfern.bufs = bufs;
|
||||||
xfern.frames = size;
|
xfern.frames = size;
|
||||||
err = ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern);
|
if (ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern) < 0)
|
||||||
err = err >= 0 ? sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL) : -errno;
|
err = -errno;
|
||||||
|
else
|
||||||
|
err = query_status_and_control_data(hw);
|
||||||
#ifdef DEBUG_RW
|
#ifdef DEBUG_RW
|
||||||
fprintf(stderr, "hw_readn: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
|
fprintf(stderr, "hw_readn: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue