Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   32bit -> 64bit ioctl wrapper for raw MIDI API
0004  *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
0005  */
0006 
0007 /* This file included from rawmidi.c */
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; /* avoid bit-field */
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, &params);
0038     case SNDRV_RAWMIDI_STREAM_INPUT:
0039         if (!rfile->input)
0040             return -EINVAL;
0041         return snd_rawmidi_input_params(rfile->input, &params);
0042     }
0043     return -EINVAL;
0044 }
0045 
0046 struct compat_snd_rawmidi_status64 {
0047     s32 stream;
0048     u8 rsvd[4]; /* alignment */
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 }