Commit b2711310 authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela

[ALSA] Fix PCM 32bit compat layer

PCM Midlevel
Fixed the handling of boundary in PCM 32bit compat layer.
Positions in hwsync are bound in the 32bit boundary size.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent cff79742
...@@ -103,10 +103,24 @@ struct sndrv_pcm_sw_params32 { ...@@ -103,10 +103,24 @@ struct sndrv_pcm_sw_params32 {
unsigned char reserved[64]; unsigned char reserved[64];
}; };
/* recalcuate the boundary within 32bit */
static snd_pcm_uframes_t recalculate_boundary(snd_pcm_runtime_t *runtime)
{
snd_pcm_uframes_t boundary;
if (! runtime->buffer_size)
return 0;
boundary = runtime->buffer_size;
while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
boundary *= 2;
return boundary;
}
static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream, static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
struct sndrv_pcm_sw_params32 __user *src) struct sndrv_pcm_sw_params32 __user *src)
{ {
snd_pcm_sw_params_t params; snd_pcm_sw_params_t params;
snd_pcm_uframes_t boundary;
int err; int err;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
...@@ -120,10 +134,17 @@ static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream, ...@@ -120,10 +134,17 @@ static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
get_user(params.silence_threshold, &src->silence_threshold) || get_user(params.silence_threshold, &src->silence_threshold) ||
get_user(params.silence_size, &src->silence_size)) get_user(params.silence_size, &src->silence_size))
return -EFAULT; return -EFAULT;
/*
* Check silent_size parameter. Since we have 64bit boundary,
* silence_size must be compared with the 32bit boundary.
*/
boundary = recalculate_boundary(substream->runtime);
if (boundary && params.silence_size >= boundary)
params.silence_size = substream->runtime->boundary;
err = snd_pcm_sw_params(substream, &params); err = snd_pcm_sw_params(substream, &params);
if (err < 0) if (err < 0)
return err; return err;
if (put_user(params.boundary, &src->boundary)) if (put_user(boundary, &src->boundary))
return -EFAULT; return -EFAULT;
return err; return err;
} }
...@@ -199,16 +220,6 @@ static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream, ...@@ -199,16 +220,6 @@ static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
return err; return err;
} }
/* recalcuate the boundary within 32bit */
static void recalculate_boundary(snd_pcm_runtime_t *runtime)
{
if (! runtime->buffer_size)
return;
runtime->boundary = runtime->buffer_size;
while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
runtime->boundary *= 2;
}
/* both for HW_PARAMS and HW_REFINE */ /* both for HW_PARAMS and HW_REFINE */
static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream, static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
int refine, int refine,
...@@ -242,7 +253,7 @@ static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream, ...@@ -242,7 +253,7 @@ static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
} }
if (! refine) if (! refine)
recalculate_boundary(runtime); runtime->boundary = recalculate_boundary(runtime);
error: error:
kfree(data); kfree(data);
return err; return err;
...@@ -380,6 +391,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream, ...@@ -380,6 +391,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
u32 sflags; u32 sflags;
struct sndrv_pcm_mmap_control scontrol; struct sndrv_pcm_mmap_control scontrol;
struct sndrv_pcm_mmap_status sstatus; struct sndrv_pcm_mmap_status sstatus;
snd_pcm_uframes_t boundary;
int err; int err;
snd_assert(runtime, return -EINVAL); snd_assert(runtime, return -EINVAL);
...@@ -395,17 +407,19 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream, ...@@ -395,17 +407,19 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
} }
status = runtime->status; status = runtime->status;
control = runtime->control; control = runtime->control;
boundary = recalculate_boundary(runtime);
snd_pcm_stream_lock_irq(substream); snd_pcm_stream_lock_irq(substream);
/* FIXME: we should consider the boundary for the sync from app */
if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
control->appl_ptr = scontrol.appl_ptr; control->appl_ptr = scontrol.appl_ptr;
else else
scontrol.appl_ptr = control->appl_ptr; scontrol.appl_ptr = control->appl_ptr % boundary;
if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
control->avail_min = scontrol.avail_min; control->avail_min = scontrol.avail_min;
else else
scontrol.avail_min = control->avail_min; scontrol.avail_min = control->avail_min;
sstatus.state = status->state; sstatus.state = status->state;
sstatus.hw_ptr = status->hw_ptr; sstatus.hw_ptr = status->hw_ptr % boundary;
sstatus.tstamp = status->tstamp; sstatus.tstamp = status->tstamp;
sstatus.suspended_state = status->suspended_state; sstatus.suspended_state = status->suspended_state;
snd_pcm_stream_unlock_irq(substream); snd_pcm_stream_unlock_irq(substream);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment