Merge tag 'core-mm-2021-02-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
[linux-2.6-microblaze.git] / sound / core / rawmidi_compat.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   32bit -> 64bit ioctl wrapper for raw MIDI API
4  *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
5  */
6
7 /* This file included from rawmidi.c */
8
9 #include <linux/compat.h>
10
11 struct snd_rawmidi_params32 {
12         s32 stream;
13         u32 buffer_size;
14         u32 avail_min;
15         unsigned int no_active_sensing; /* avoid bit-field */
16         unsigned char reserved[16];
17 } __attribute__((packed));
18
19 static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
20                                            struct snd_rawmidi_params32 __user *src)
21 {
22         struct snd_rawmidi_params params;
23         unsigned int val;
24
25         if (get_user(params.stream, &src->stream) ||
26             get_user(params.buffer_size, &src->buffer_size) ||
27             get_user(params.avail_min, &src->avail_min) ||
28             get_user(val, &src->no_active_sensing))
29                 return -EFAULT;
30         params.no_active_sensing = val;
31         switch (params.stream) {
32         case SNDRV_RAWMIDI_STREAM_OUTPUT:
33                 if (!rfile->output)
34                         return -EINVAL;
35                 return snd_rawmidi_output_params(rfile->output, &params);
36         case SNDRV_RAWMIDI_STREAM_INPUT:
37                 if (!rfile->input)
38                         return -EINVAL;
39                 return snd_rawmidi_input_params(rfile->input, &params);
40         }
41         return -EINVAL;
42 }
43
44 struct compat_snd_rawmidi_status64 {
45         s32 stream;
46         u8 rsvd[4]; /* alignment */
47         s64 tstamp_sec;
48         s64 tstamp_nsec;
49         u32 avail;
50         u32 xruns;
51         unsigned char reserved[16];
52 } __attribute__((packed));
53
54 static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile,
55                                              struct compat_snd_rawmidi_status64 __user *src)
56 {
57         int err;
58         struct snd_rawmidi_status64 status;
59         struct compat_snd_rawmidi_status64 compat_status;
60
61         if (get_user(status.stream, &src->stream))
62                 return -EFAULT;
63
64         switch (status.stream) {
65         case SNDRV_RAWMIDI_STREAM_OUTPUT:
66                 if (!rfile->output)
67                         return -EINVAL;
68                 err = snd_rawmidi_output_status(rfile->output, &status);
69                 break;
70         case SNDRV_RAWMIDI_STREAM_INPUT:
71                 if (!rfile->input)
72                         return -EINVAL;
73                 err = snd_rawmidi_input_status(rfile->input, &status);
74                 break;
75         default:
76                 return -EINVAL;
77         }
78         if (err < 0)
79                 return err;
80
81         compat_status = (struct compat_snd_rawmidi_status64) {
82                 .stream = status.stream,
83                 .tstamp_sec = status.tstamp_sec,
84                 .tstamp_nsec = status.tstamp_nsec,
85                 .avail = status.avail,
86                 .xruns = status.xruns,
87         };
88
89         if (copy_to_user(src, &compat_status, sizeof(*src)))
90                 return -EFAULT;
91
92         return 0;
93 }
94
95 enum {
96         SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
97         SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
98         SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64),
99 };
100
101 static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
102 {
103         struct snd_rawmidi_file *rfile;
104         void __user *argp = compat_ptr(arg);
105
106         rfile = file->private_data;
107         switch (cmd) {
108         case SNDRV_RAWMIDI_IOCTL_PVERSION:
109         case SNDRV_RAWMIDI_IOCTL_INFO:
110         case SNDRV_RAWMIDI_IOCTL_DROP:
111         case SNDRV_RAWMIDI_IOCTL_DRAIN:
112                 return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
113         case SNDRV_RAWMIDI_IOCTL_PARAMS32:
114                 return snd_rawmidi_ioctl_params_compat(rfile, argp);
115         case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32:
116                 return snd_rawmidi_ioctl_status32(rfile, argp);
117         case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64:
118                 return snd_rawmidi_ioctl_status_compat64(rfile, argp);
119         }
120         return -ENOIOCTLCMD;
121 }