static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream, struct snd_pcm_sw_params32 __user *src) { struct snd_pcm_sw_params params; snd_pcm_uframes_t boundary; int err; memset(¶ms, 0, sizeof(params)); if (get_user(params.tstamp_mode, &src->tstamp_mode) || get_user(params.period_step, &src->period_step) || get_user(params.sleep_min, &src->sleep_min) || get_user(params.avail_min, &src->avail_min) || get_user(params.xfer_align, &src->xfer_align) || get_user(params.start_threshold, &src->start_threshold) || get_user(params.stop_threshold, &src->stop_threshold) || 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, ¶ms); if (err < 0) return err; if (boundary && put_user(boundary, &src->boundary)) return -EFAULT; return err; }
static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, struct snd_pcm_sync_ptr32 __user *src) { struct snd_pcm_runtime *runtime = substream->runtime; volatile struct snd_pcm_mmap_status *status; volatile struct snd_pcm_mmap_control *control; u32 sflags; struct snd_pcm_mmap_control scontrol; struct snd_pcm_mmap_status sstatus; snd_pcm_uframes_t boundary; int err; if (snd_BUG_ON(!runtime)) return -EINVAL; if (get_user(sflags, &src->flags) || get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || get_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { err = snd_pcm_hwsync(substream); if (err < 0) return err; } status = runtime->status; control = runtime->control; boundary = recalculate_boundary(runtime); if (! boundary) boundary = 0x7fffffff; 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 % 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 % boundary; sstatus.tstamp = status->tstamp; sstatus.suspended_state = status->suspended_state; sstatus.audio_tstamp = status->audio_tstamp; snd_pcm_stream_unlock_irq(substream); if (put_user(sstatus.state, &src->s.status.state) || put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || put_user(sstatus.suspended_state, &src->s.status.suspended_state) || compat_put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) || put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || put_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; return 0; }
/* both for HW_PARAMS and HW_REFINE */ static int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) { struct sndrv_pcm_hw_params32 __user *data32; struct sndrv_pcm_hw_params *data; snd_pcm_file_t *pcm_file; snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; int err; if (sanity_check_pcm(file)) return -ENOTTY; if (! (pcm_file = file->private_data)) return -ENOTTY; if (! (substream = pcm_file->substream)) return -ENOTTY; if (! (runtime = substream->runtime)) return -ENOTTY; data32 = compat_ptr(arg); data = kmalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) return -ENOMEM; if (copy_from_user(data, data32, sizeof(*data32))) { err = -EFAULT; goto error; } if (native_ctl == SNDRV_PCM_IOCTL_HW_REFINE) err = snd_pcm_hw_refine(substream, data); else err = snd_pcm_hw_params(substream, data); if (err < 0) goto error; if (copy_to_user(data32, data, sizeof(*data32)) || __put_user((u32)data->fifo_size, &data32->fifo_size)) { err = -EFAULT; goto error; } if (native_ctl == SNDRV_PCM_IOCTL_HW_PARAMS) recalculate_boundary(runtime); error: kfree(data); return err; }
/* both for HW_PARAMS and HW_REFINE */ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, int refine, struct snd_pcm_hw_params32 __user *data32) { struct snd_pcm_hw_params *data; struct snd_pcm_runtime *runtime; int err; if (! (runtime = substream->runtime)) return -ENOTTY; data = kmalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; /* only fifo_size (RO from userspace) is different, so just copy all */ if (copy_from_user(data, data32, sizeof(*data32))) { err = -EFAULT; goto error; } if (refine) err = snd_pcm_hw_refine(substream, data); else err = snd_pcm_hw_params(substream, data); if (err < 0) goto error; if (copy_to_user(data32, data, sizeof(*data32)) || put_user(data->fifo_size, &data32->fifo_size)) { err = -EFAULT; goto error; } if (! refine) { unsigned int new_boundary = recalculate_boundary(runtime); if (new_boundary) runtime->boundary = new_boundary; } error: kfree(data); return err; }
static inline int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) { struct sndrv_pcm_hw_params32 *data32; struct sndrv_pcm_hw_params *data; mm_segment_t oldseg; int err; data32 = kmalloc(sizeof(*data32), GFP_KERNEL); data = kmalloc(sizeof(*data), GFP_KERNEL); if (data32 == NULL || data == NULL) { err = -ENOMEM; goto __end; } if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) { err = -EFAULT; goto __end; } memset(data, 0, sizeof(*data)); convert_from_32(pcm_hw_params, data, data32); oldseg = get_fs(); set_fs(KERNEL_DS); err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); set_fs(oldseg); if (err < 0) goto __end; err = 0; convert_to_32(pcm_hw_params, data32, data); if (copy_to_user((void __user *)arg, data32, sizeof(*data32))) err = -EFAULT; else recalculate_boundary(file); __end: if (data) kfree(data); if (data32) kfree(data32); return err; }
/* FIXME: need to check whether fop->ioctl is sane */ if (! (pcm_file = file->private_data)) return 0x7fffffffUL; if (! (substream = pcm_file->substream)) return 0x7fffffffUL; if (! (runtime = substream->runtime)) return 0x7fffffffUL; boundary = runtime->buffer_size; if (boundary == 0) return 0x7fffffffUL; while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size) boundary *= 2; return (u32)boundary; } DEFINE_ALSA_IOCTL1(pcm_sw_params, data.boundary = recalculate_boundary(file, data.boundary), data32.boundary = recalculate_boundary(file, data.boundary)); static inline int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) { struct sndrv_pcm_hw_params32 *data32; struct snd_pcm_hw_params *data; mm_segment_t oldseg; int err; data32 = kmalloc(sizeof(*data32), GFP_KERNEL); data = kmalloc(sizeof(*data), GFP_KERNEL); if (data32 == NULL || data == NULL) { err = -ENOMEM; goto __end; } if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {