Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/core/rawmidi_compat.c
26378 views
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 <[email protected]>
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
} __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
} __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
#if IS_ENABLED(CONFIG_SND_UMP)
115
case SNDRV_UMP_IOCTL_ENDPOINT_INFO:
116
case SNDRV_UMP_IOCTL_BLOCK_INFO:
117
#endif
118
return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
119
case SNDRV_RAWMIDI_IOCTL_PARAMS32:
120
return snd_rawmidi_ioctl_params_compat(rfile, argp);
121
case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32:
122
return snd_rawmidi_ioctl_status32(rfile, argp);
123
case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64:
124
return snd_rawmidi_ioctl_status_compat64(rfile, argp);
125
}
126
return -ENOIOCTLCMD;
127
}
128
129