Merge remote-tracking branch 'drm-misc/drm-misc-next-fixes' into drm-misc-fixes
[platform/kernel/linux-starfive.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 int mode;
17         unsigned char reserved[12];
18 } __attribute__((packed));
19
20 static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
21                                            struct snd_rawmidi_params32 __user *src)
22 {
23         struct snd_rawmidi_params params;
24         unsigned int val;
25
26         if (get_user(params.stream, &src->stream) ||
27             get_user(params.buffer_size, &src->buffer_size) ||
28             get_user(params.avail_min, &src->avail_min) ||
29             get_user(params.mode, &src->mode) ||
30             get_user(val, &src->no_active_sensing))
31                 return -EFAULT;
32         params.no_active_sensing = val;
33         switch (params.stream) {
34         case SNDRV_RAWMIDI_STREAM_OUTPUT:
35                 if (!rfile->output)
36                         return -EINVAL;
37                 return snd_rawmidi_output_params(rfile->output, &params);
38         case SNDRV_RAWMIDI_STREAM_INPUT:
39                 if (!rfile->input)
40                         return -EINVAL;
41                 return snd_rawmidi_input_params(rfile->input, &params);
42         }
43         return -EINVAL;
44 }
45
46 struct compat_snd_rawmidi_status64 {
47         s32 stream;
48         u8 rsvd[4]; /* alignment */
49         s64 tstamp_sec;
50         s64 tstamp_nsec;
51         u32 avail;
52         u32 xruns;
53         unsigned char reserved[16];
54 } __attribute__((packed));
55
56 static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile,
57                                              struct compat_snd_rawmidi_status64 __user *src)
58 {
59         int err;
60         struct snd_rawmidi_status64 status;
61         struct compat_snd_rawmidi_status64 compat_status;
62
63         if (get_user(status.stream, &src->stream))
64                 return -EFAULT;
65
66         switch (status.stream) {
67         case SNDRV_RAWMIDI_STREAM_OUTPUT:
68                 if (!rfile->output)
69                         return -EINVAL;
70                 err = snd_rawmidi_output_status(rfile->output, &status);
71                 break;
72         case SNDRV_RAWMIDI_STREAM_INPUT:
73                 if (!rfile->input)
74                         return -EINVAL;
75                 err = snd_rawmidi_input_status(rfile->input, &status);
76                 break;
77         default:
78                 return -EINVAL;
79         }
80         if (err < 0)
81                 return err;
82
83         compat_status = (struct compat_snd_rawmidi_status64) {
84                 .stream = status.stream,
85                 .tstamp_sec = status.tstamp_sec,
86                 .tstamp_nsec = status.tstamp_nsec,
87                 .avail = status.avail,
88                 .xruns = status.xruns,
89         };
90
91         if (copy_to_user(src, &compat_status, sizeof(*src)))
92                 return -EFAULT;
93
94         return 0;
95 }
96
97 enum {
98         SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
99         SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
100         SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64),
101 };
102
103 static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
104 {
105         struct snd_rawmidi_file *rfile;
106         void __user *argp = compat_ptr(arg);
107
108         rfile = file->private_data;
109         switch (cmd) {
110         case SNDRV_RAWMIDI_IOCTL_PVERSION:
111         case SNDRV_RAWMIDI_IOCTL_INFO:
112         case SNDRV_RAWMIDI_IOCTL_DROP:
113         case SNDRV_RAWMIDI_IOCTL_DRAIN:
114                 return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
115         case SNDRV_RAWMIDI_IOCTL_PARAMS32:
116                 return snd_rawmidi_ioctl_params_compat(rfile, argp);
117         case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32:
118                 return snd_rawmidi_ioctl_status32(rfile, argp);
119         case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64:
120                 return snd_rawmidi_ioctl_status_compat64(rfile, argp);
121         }
122         return -ENOIOCTLCMD;
123 }