0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/compat.h>
0010
0011 struct snd_rawmidi_params32 {
0012 s32 stream;
0013 u32 buffer_size;
0014 u32 avail_min;
0015 unsigned int no_active_sensing;
0016 unsigned int mode;
0017 unsigned char reserved[12];
0018 } __attribute__((packed));
0019
0020 static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
0021 struct snd_rawmidi_params32 __user *src)
0022 {
0023 struct snd_rawmidi_params params;
0024 unsigned int val;
0025
0026 if (get_user(params.stream, &src->stream) ||
0027 get_user(params.buffer_size, &src->buffer_size) ||
0028 get_user(params.avail_min, &src->avail_min) ||
0029 get_user(params.mode, &src->mode) ||
0030 get_user(val, &src->no_active_sensing))
0031 return -EFAULT;
0032 params.no_active_sensing = val;
0033 switch (params.stream) {
0034 case SNDRV_RAWMIDI_STREAM_OUTPUT:
0035 if (!rfile->output)
0036 return -EINVAL;
0037 return snd_rawmidi_output_params(rfile->output, ¶ms);
0038 case SNDRV_RAWMIDI_STREAM_INPUT:
0039 if (!rfile->input)
0040 return -EINVAL;
0041 return snd_rawmidi_input_params(rfile->input, ¶ms);
0042 }
0043 return -EINVAL;
0044 }
0045
0046 struct compat_snd_rawmidi_status64 {
0047 s32 stream;
0048 u8 rsvd[4];
0049 s64 tstamp_sec;
0050 s64 tstamp_nsec;
0051 u32 avail;
0052 u32 xruns;
0053 unsigned char reserved[16];
0054 } __attribute__((packed));
0055
0056 static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile,
0057 struct compat_snd_rawmidi_status64 __user *src)
0058 {
0059 int err;
0060 struct snd_rawmidi_status64 status;
0061 struct compat_snd_rawmidi_status64 compat_status;
0062
0063 if (get_user(status.stream, &src->stream))
0064 return -EFAULT;
0065
0066 switch (status.stream) {
0067 case SNDRV_RAWMIDI_STREAM_OUTPUT:
0068 if (!rfile->output)
0069 return -EINVAL;
0070 err = snd_rawmidi_output_status(rfile->output, &status);
0071 break;
0072 case SNDRV_RAWMIDI_STREAM_INPUT:
0073 if (!rfile->input)
0074 return -EINVAL;
0075 err = snd_rawmidi_input_status(rfile->input, &status);
0076 break;
0077 default:
0078 return -EINVAL;
0079 }
0080 if (err < 0)
0081 return err;
0082
0083 compat_status = (struct compat_snd_rawmidi_status64) {
0084 .stream = status.stream,
0085 .tstamp_sec = status.tstamp_sec,
0086 .tstamp_nsec = status.tstamp_nsec,
0087 .avail = status.avail,
0088 .xruns = status.xruns,
0089 };
0090
0091 if (copy_to_user(src, &compat_status, sizeof(*src)))
0092 return -EFAULT;
0093
0094 return 0;
0095 }
0096
0097 enum {
0098 SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
0099 SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
0100 SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64),
0101 };
0102
0103 static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
0104 {
0105 struct snd_rawmidi_file *rfile;
0106 void __user *argp = compat_ptr(arg);
0107
0108 rfile = file->private_data;
0109 switch (cmd) {
0110 case SNDRV_RAWMIDI_IOCTL_PVERSION:
0111 case SNDRV_RAWMIDI_IOCTL_INFO:
0112 case SNDRV_RAWMIDI_IOCTL_DROP:
0113 case SNDRV_RAWMIDI_IOCTL_DRAIN:
0114 return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
0115 case SNDRV_RAWMIDI_IOCTL_PARAMS32:
0116 return snd_rawmidi_ioctl_params_compat(rfile, argp);
0117 case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32:
0118 return snd_rawmidi_ioctl_status32(rfile, argp);
0119 case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64:
0120 return snd_rawmidi_ioctl_status_compat64(rfile, argp);
0121 }
0122 return -ENOIOCTLCMD;
0123 }