Skip to content

Commit

Permalink
[ALSA] Fix PCM 32bit compat layer
Browse files Browse the repository at this point in the history
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: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai authored and Jaroslav Kysela committed Aug 30, 2005
1 parent cff7974 commit b271131
Showing 1 changed file with 28 additions and 14 deletions.
42 changes: 28 additions & 14 deletions sound/core/pcm_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,24 @@ struct sndrv_pcm_sw_params32 {
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,
struct sndrv_pcm_sw_params32 __user *src)
{
snd_pcm_sw_params_t params;
snd_pcm_uframes_t boundary;
int err;

memset(&params, 0, sizeof(params));
Expand All @@ -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_size, &src->silence_size))
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);
if (err < 0)
return err;
if (put_user(params.boundary, &src->boundary))
if (put_user(boundary, &src->boundary))
return -EFAULT;
return err;
}
Expand Down Expand Up @@ -199,16 +220,6 @@ static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
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 */
static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
int refine,
Expand Down Expand Up @@ -242,7 +253,7 @@ static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
}

if (! refine)
recalculate_boundary(runtime);
runtime->boundary = recalculate_boundary(runtime);
error:
kfree(data);
return err;
Expand Down Expand Up @@ -380,6 +391,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
u32 sflags;
struct sndrv_pcm_mmap_control scontrol;
struct sndrv_pcm_mmap_status sstatus;
snd_pcm_uframes_t boundary;
int err;

snd_assert(runtime, return -EINVAL);
Expand All @@ -395,17 +407,19 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
}
status = runtime->status;
control = runtime->control;
boundary = recalculate_boundary(runtime);
snd_pcm_stream_lock_irq(substream);
/* FIXME: we should consider the boundary for the sync from app */
if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
control->appl_ptr = scontrol.appl_ptr;
else
scontrol.appl_ptr = control->appl_ptr;
scontrol.appl_ptr = control->appl_ptr % boundary;
if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
control->avail_min = scontrol.avail_min;
else
scontrol.avail_min = control->avail_min;
sstatus.state = status->state;
sstatus.hw_ptr = status->hw_ptr;
sstatus.hw_ptr = status->hw_ptr % boundary;
sstatus.tstamp = status->tstamp;
sstatus.suspended_state = status->suspended_state;
snd_pcm_stream_unlock_irq(substream);
Expand Down

0 comments on commit b271131

Please sign in to comment.