summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-08-15 15:01:10 +0200
committerJaroslav Kysela <perex@suse.cz>2005-08-30 08:46:06 +0200
commitb27113102f576092cd8f5d6ce8365aa6e2f58134 (patch)
tree9cdbf08c070d430c1959ce2ee60a2714681e8150
parentcff79742fc9e80242a9147a348621e4373c76287 (diff)
[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: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/core/pcm_compat.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 3920bf0eebb..eef94a15f50 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -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));
@@ -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;
}
@@ -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,
@@ -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;
@@ -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);
@@ -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);