diff options
Diffstat (limited to 'sound/core/pcm_compat.c')
| -rw-r--r-- | sound/core/pcm_compat.c | 154 |
1 files changed, 79 insertions, 75 deletions
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 4b6307df846..af49721ba0e 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -21,8 +21,9 @@ /* This file included from pcm_native.c */ #include <linux/compat.h> +#include <linux/slab.h> -static int snd_pcm_ioctl_delay_compat(snd_pcm_substream_t *substream, +static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream, s32 __user *src) { snd_pcm_sframes_t delay; @@ -39,7 +40,7 @@ static int snd_pcm_ioctl_delay_compat(snd_pcm_substream_t *substream, return err; } -static int snd_pcm_ioctl_rewind_compat(snd_pcm_substream_t *substream, +static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream, u32 __user *src) { snd_pcm_uframes_t frames; @@ -56,7 +57,7 @@ static int snd_pcm_ioctl_rewind_compat(snd_pcm_substream_t *substream, return err < 0 ? err : 0; } -static int snd_pcm_ioctl_forward_compat(snd_pcm_substream_t *substream, +static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream, u32 __user *src) { snd_pcm_uframes_t frames; @@ -73,12 +74,12 @@ static int snd_pcm_ioctl_forward_compat(snd_pcm_substream_t *substream, return err < 0 ? err : 0; } -struct sndrv_pcm_hw_params32 { +struct snd_pcm_hw_params32 { u32 flags; - struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */ - struct sndrv_mask mres[5]; /* reserved masks */ - struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; - struct sndrv_interval ires[9]; /* reserved intervals */ + struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */ + struct snd_mask mres[5]; /* reserved masks */ + struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; + struct snd_interval ires[9]; /* reserved intervals */ u32 rmask; u32 cmask; u32 info; @@ -89,7 +90,7 @@ struct sndrv_pcm_hw_params32 { unsigned char reserved[64]; }; -struct sndrv_pcm_sw_params32 { +struct snd_pcm_sw_params32 { s32 tstamp_mode; u32 period_step; u32 sleep_min; @@ -104,7 +105,7 @@ struct sndrv_pcm_sw_params32 { }; /* recalcuate the boundary within 32bit */ -static snd_pcm_uframes_t recalculate_boundary(snd_pcm_runtime_t *runtime) +static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime) { snd_pcm_uframes_t boundary; @@ -116,10 +117,10 @@ static snd_pcm_uframes_t recalculate_boundary(snd_pcm_runtime_t *runtime) return boundary; } -static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream, - struct sndrv_pcm_sw_params32 __user *src) +static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream, + struct snd_pcm_sw_params32 __user *src) { - snd_pcm_sw_params_t params; + struct snd_pcm_sw_params params; snd_pcm_uframes_t boundary; int err; @@ -149,17 +150,17 @@ static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream, return err; } -struct sndrv_pcm_channel_info32 { +struct snd_pcm_channel_info32 { u32 channel; u32 offset; u32 first; u32 step; }; -static int snd_pcm_ioctl_channel_info_compat(snd_pcm_substream_t *substream, - struct sndrv_pcm_channel_info32 __user *src) +static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream, + struct snd_pcm_channel_info32 __user *src) { - snd_pcm_channel_info_t info; + struct snd_pcm_channel_info info; int err; if (get_user(info.channel, &src->channel) || @@ -178,7 +179,7 @@ static int snd_pcm_ioctl_channel_info_compat(snd_pcm_substream_t *substream, return err; } -struct sndrv_pcm_status32 { +struct snd_pcm_status32 { s32 state; struct compat_timespec trigger_tstamp; struct compat_timespec tstamp; @@ -189,14 +190,16 @@ struct sndrv_pcm_status32 { u32 avail_max; u32 overrange; s32 suspended_state; - unsigned char reserved[60]; + u32 reserved_alignment; + struct compat_timespec audio_tstamp; + unsigned char reserved[56-sizeof(struct compat_timespec)]; } __attribute__((packed)); -static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream, - struct sndrv_pcm_status32 __user *src) +static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, + struct snd_pcm_status32 __user *src) { - snd_pcm_status_t status; + struct snd_pcm_status status; int err; err = snd_pcm_status(substream, &status); @@ -204,42 +207,38 @@ static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream, return err; if (put_user(status.state, &src->state) || - put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) || - put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) || - put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || - put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || + compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || + compat_put_timespec(&status.tstamp, &src->tstamp) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || - put_user(status.suspended_state, &src->suspended_state)) + put_user(status.suspended_state, &src->suspended_state) || + compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp)) return -EFAULT; return err; } /* 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(struct snd_pcm_substream *substream, int refine, - struct sndrv_pcm_hw_params32 __user *data32) + struct snd_pcm_hw_params32 __user *data32) { - struct sndrv_pcm_hw_params *data; - snd_pcm_runtime_t *runtime; + 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 == NULL) - return -ENOMEM; /* only fifo_size is different, so just copy all */ - if (copy_from_user(data, data32, sizeof(*data32))) { - err = -EFAULT; - goto error; - } + data = memdup_user(data32, sizeof(*data32)); + if (IS_ERR(data)) + return PTR_ERR(data); + if (refine) err = snd_pcm_hw_refine(substream, data); else @@ -265,14 +264,14 @@ static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream, /* */ -struct sndrv_xferi32 { +struct snd_xferi32 { s32 result; u32 buf; u32 frames; }; -static int snd_pcm_ioctl_xferi_compat(snd_pcm_substream_t *substream, - int dir, struct sndrv_xferi32 __user *data32) +static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream, + int dir, struct snd_xferi32 __user *data32) { compat_caddr_t buf; u32 frames; @@ -303,7 +302,7 @@ static int snd_pcm_ioctl_xferi_compat(snd_pcm_substream_t *substream, /* snd_xfern needs remapping of bufs */ -struct sndrv_xfern32 { +struct snd_xfern32 { s32 result; u32 bufs; /* this is void **; */ u32 frames; @@ -315,8 +314,8 @@ struct sndrv_xfern32 { * handler there expands again the same 128 pointers on stack, so it is better * to handle the function (calling pcm_readv/writev) directly in this handler. */ -static int snd_pcm_ioctl_xfern_compat(snd_pcm_substream_t *substream, - int dir, struct sndrv_xfern32 __user *data32) +static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, + int dir, struct snd_xfern32 __user *data32) { compat_caddr_t buf; compat_caddr_t __user *bufptr; @@ -344,7 +343,7 @@ static int snd_pcm_ioctl_xfern_compat(snd_pcm_substream_t *substream, kfree(bufs); return -EFAULT; } - bufs[ch] = compat_ptr(ptr); + bufs[i] = compat_ptr(ptr); bufptr++; } if (dir == SNDRV_PCM_STREAM_PLAYBACK) @@ -360,44 +359,46 @@ static int snd_pcm_ioctl_xfern_compat(snd_pcm_substream_t *substream, } -struct sndrv_pcm_mmap_status32 { +struct snd_pcm_mmap_status32 { s32 state; s32 pad1; u32 hw_ptr; struct compat_timespec tstamp; s32 suspended_state; + struct compat_timespec audio_tstamp; } __attribute__((packed)); -struct sndrv_pcm_mmap_control32 { +struct snd_pcm_mmap_control32 { u32 appl_ptr; u32 avail_min; }; -struct sndrv_pcm_sync_ptr32 { +struct snd_pcm_sync_ptr32 { u32 flags; union { - struct sndrv_pcm_mmap_status32 status; + struct snd_pcm_mmap_status32 status; unsigned char reserved[64]; } s; union { - struct sndrv_pcm_mmap_control32 control; + struct snd_pcm_mmap_control32 control; unsigned char reserved[64]; } c; } __attribute__((packed)); -static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream, - struct sndrv_pcm_sync_ptr32 __user *src) +static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, + struct snd_pcm_sync_ptr32 __user *src) { - snd_pcm_runtime_t *runtime = substream->runtime; - volatile struct sndrv_pcm_mmap_status *status; - volatile struct sndrv_pcm_mmap_control *control; + struct snd_pcm_runtime *runtime = substream->runtime; + volatile struct snd_pcm_mmap_status *status; + volatile struct snd_pcm_mmap_control *control; u32 sflags; - struct sndrv_pcm_mmap_control scontrol; - struct sndrv_pcm_mmap_status sstatus; + struct snd_pcm_mmap_control scontrol; + struct snd_pcm_mmap_status sstatus; snd_pcm_uframes_t boundary; int err; - snd_assert(runtime, return -EINVAL); + if (snd_BUG_ON(!runtime)) + return -EINVAL; if (get_user(sflags, &src->flags) || get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || @@ -427,12 +428,14 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream, 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) || - put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) || - put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) || + 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; @@ -444,26 +447,26 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream, /* */ enum { - SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params32), - SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params32), - SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct sndrv_pcm_sw_params32), - SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct sndrv_pcm_status32), + SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32), + SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32), + SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32), + SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32), SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), - SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_pcm_channel_info32), + SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32), SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32), - SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct sndrv_xferi32), - SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32), - SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32), - SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32), - SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32), + SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct snd_xferi32), + SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32), + SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), + SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), + SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), }; static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { - snd_pcm_file_t *pcm_file; - snd_pcm_substream_t *substream; + struct snd_pcm_file *pcm_file; + struct snd_pcm_substream *substream; void __user *argp = compat_ptr(arg); pcm_file = file->private_data; @@ -478,12 +481,13 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l * mmap of PCM status/control records because of the size * incompatibility. */ - substream->no_mmap_ctrl = 1; + pcm_file->no_compat_mmap = 1; switch (cmd) { case SNDRV_PCM_IOCTL_PVERSION: case SNDRV_PCM_IOCTL_INFO: case SNDRV_PCM_IOCTL_TSTAMP: + case SNDRV_PCM_IOCTL_TTSTAMP: case SNDRV_PCM_IOCTL_HWSYNC: case SNDRV_PCM_IOCTL_PREPARE: case SNDRV_PCM_IOCTL_RESET: @@ -497,9 +501,9 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l case SNDRV_PCM_IOCTL_LINK: case SNDRV_PCM_IOCTL_UNLINK: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - return snd_pcm_playback_ioctl1(substream, cmd, argp); + return snd_pcm_playback_ioctl1(file, substream, cmd, argp); else - return snd_pcm_capture_ioctl1(substream, cmd, argp); + return snd_pcm_capture_ioctl1(file, substream, cmd, argp); case SNDRV_PCM_IOCTL_HW_REFINE32: return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); case SNDRV_PCM_IOCTL_HW_PARAMS32: |
