aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-08-15 09:01:10 -0400
committerJaroslav Kysela <perex@suse.cz>2005-08-30 02:46:06 -0400
commitb27113102f576092cd8f5d6ce8365aa6e2f58134 (patch)
tree9cdbf08c070d430c1959ce2ee60a2714681e8150 /sound
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>
Diffstat (limited to 'sound')
-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 3920bf0eebbf..eef94a15f50a 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -103,10 +103,24 @@ struct sndrv_pcm_sw_params32 {
103 unsigned char reserved[64]; 103 unsigned char reserved[64];
104}; 104};
105 105
106/* recalcuate the boundary within 32bit */
107static snd_pcm_uframes_t recalculate_boundary(snd_pcm_runtime_t *runtime)
108{
109 snd_pcm_uframes_t boundary;
110
111 if (! runtime->buffer_size)
112 return 0;
113 boundary = runtime->buffer_size;
114 while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
115 boundary *= 2;
116 return boundary;
117}
118
106static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream, 119static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
107 struct sndrv_pcm_sw_params32 __user *src) 120 struct sndrv_pcm_sw_params32 __user *src)
108{ 121{
109 snd_pcm_sw_params_t params; 122 snd_pcm_sw_params_t params;
123 snd_pcm_uframes_t boundary;
110 int err; 124 int err;
111 125
112 memset(&params, 0, sizeof(params)); 126 memset(&params, 0, sizeof(params));
@@ -120,10 +134,17 @@ static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
120 get_user(params.silence_threshold, &src->silence_threshold) || 134 get_user(params.silence_threshold, &src->silence_threshold) ||
121 get_user(params.silence_size, &src->silence_size)) 135 get_user(params.silence_size, &src->silence_size))
122 return -EFAULT; 136 return -EFAULT;
137 /*
138 * Check silent_size parameter. Since we have 64bit boundary,
139 * silence_size must be compared with the 32bit boundary.
140 */
141 boundary = recalculate_boundary(substream->runtime);
142 if (boundary && params.silence_size >= boundary)
143 params.silence_size = substream->runtime->boundary;
123 err = snd_pcm_sw_params(substream, &params); 144 err = snd_pcm_sw_params(substream, &params);
124 if (err < 0) 145 if (err < 0)
125 return err; 146 return err;
126 if (put_user(params.boundary, &src->boundary)) 147 if (put_user(boundary, &src->boundary))
127 return -EFAULT; 148 return -EFAULT;
128 return err; 149 return err;
129} 150}
@@ -199,16 +220,6 @@ static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
199 return err; 220 return err;
200} 221}
201 222
202/* recalcuate the boundary within 32bit */
203static void recalculate_boundary(snd_pcm_runtime_t *runtime)
204{
205 if (! runtime->buffer_size)
206 return;
207 runtime->boundary = runtime->buffer_size;
208 while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
209 runtime->boundary *= 2;
210}
211
212/* both for HW_PARAMS and HW_REFINE */ 223/* both for HW_PARAMS and HW_REFINE */
213static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream, 224static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
214 int refine, 225 int refine,
@@ -242,7 +253,7 @@ static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
242 } 253 }
243 254
244 if (! refine) 255 if (! refine)
245 recalculate_boundary(runtime); 256 runtime->boundary = recalculate_boundary(runtime);
246 error: 257 error:
247 kfree(data); 258 kfree(data);
248 return err; 259 return err;
@@ -380,6 +391,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
380 u32 sflags; 391 u32 sflags;
381 struct sndrv_pcm_mmap_control scontrol; 392 struct sndrv_pcm_mmap_control scontrol;
382 struct sndrv_pcm_mmap_status sstatus; 393 struct sndrv_pcm_mmap_status sstatus;
394 snd_pcm_uframes_t boundary;
383 int err; 395 int err;
384 396
385 snd_assert(runtime, return -EINVAL); 397 snd_assert(runtime, return -EINVAL);
@@ -395,17 +407,19 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
395 } 407 }
396 status = runtime->status; 408 status = runtime->status;
397 control = runtime->control; 409 control = runtime->control;
410 boundary = recalculate_boundary(runtime);
398 snd_pcm_stream_lock_irq(substream); 411 snd_pcm_stream_lock_irq(substream);
412 /* FIXME: we should consider the boundary for the sync from app */
399 if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) 413 if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
400 control->appl_ptr = scontrol.appl_ptr; 414 control->appl_ptr = scontrol.appl_ptr;
401 else 415 else
402 scontrol.appl_ptr = control->appl_ptr; 416 scontrol.appl_ptr = control->appl_ptr % boundary;
403 if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) 417 if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
404 control->avail_min = scontrol.avail_min; 418 control->avail_min = scontrol.avail_min;
405 else 419 else
406 scontrol.avail_min = control->avail_min; 420 scontrol.avail_min = control->avail_min;
407 sstatus.state = status->state; 421 sstatus.state = status->state;
408 sstatus.hw_ptr = status->hw_ptr; 422 sstatus.hw_ptr = status->hw_ptr % boundary;
409 sstatus.tstamp = status->tstamp; 423 sstatus.tstamp = status->tstamp;
410 sstatus.suspended_state = status->suspended_state; 424 sstatus.suspended_state = status->suspended_state;
411 snd_pcm_stream_unlock_irq(substream); 425 snd_pcm_stream_unlock_irq(substream);