1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * 32bit -> 64bit ioctl wrapper for raw MIDI API
4 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
7 /* This file included from rawmidi.c */
9 #include <linux/compat.h>
11 struct snd_rawmidi_params32
{
15 unsigned int no_active_sensing
; /* avoid bit-field */
16 unsigned char reserved
[16];
17 } __attribute__((packed
));
19 static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file
*rfile
,
20 struct snd_rawmidi_params32 __user
*src
)
22 struct snd_rawmidi_params params
;
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
))
30 params
.no_active_sensing
= val
;
31 switch (params
.stream
) {
32 case SNDRV_RAWMIDI_STREAM_OUTPUT
:
35 return snd_rawmidi_output_params(rfile
->output
, ¶ms
);
36 case SNDRV_RAWMIDI_STREAM_INPUT
:
39 return snd_rawmidi_input_params(rfile
->input
, ¶ms
);
44 struct snd_rawmidi_status32
{
46 struct compat_timespec tstamp
;
49 unsigned char reserved
[16];
50 } __attribute__((packed
));
52 static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file
*rfile
,
53 struct snd_rawmidi_status32 __user
*src
)
56 struct snd_rawmidi_status status
;
58 if (get_user(status
.stream
, &src
->stream
))
61 switch (status
.stream
) {
62 case SNDRV_RAWMIDI_STREAM_OUTPUT
:
65 err
= snd_rawmidi_output_status(rfile
->output
, &status
);
67 case SNDRV_RAWMIDI_STREAM_INPUT
:
70 err
= snd_rawmidi_input_status(rfile
->input
, &status
);
78 if (compat_put_timespec(&status
.tstamp
, &src
->tstamp
) ||
79 put_user(status
.avail
, &src
->avail
) ||
80 put_user(status
.xruns
, &src
->xruns
))
87 /* X32 ABI has 64bit timespec and 64bit alignment */
88 struct snd_rawmidi_status_x32
{
90 u32 rsvd
; /* alignment */
91 struct timespec tstamp
;
94 unsigned char reserved
[16];
95 } __attribute__((packed
));
97 #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
99 static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file
*rfile
,
100 struct snd_rawmidi_status_x32 __user
*src
)
103 struct snd_rawmidi_status status
;
105 if (get_user(status
.stream
, &src
->stream
))
108 switch (status
.stream
) {
109 case SNDRV_RAWMIDI_STREAM_OUTPUT
:
112 err
= snd_rawmidi_output_status(rfile
->output
, &status
);
114 case SNDRV_RAWMIDI_STREAM_INPUT
:
117 err
= snd_rawmidi_input_status(rfile
->input
, &status
);
125 if (put_timespec(&status
.tstamp
, &src
->tstamp
) ||
126 put_user(status
.avail
, &src
->avail
) ||
127 put_user(status
.xruns
, &src
->xruns
))
132 #endif /* CONFIG_X86_X32 */
135 SNDRV_RAWMIDI_IOCTL_PARAMS32
= _IOWR('W', 0x10, struct snd_rawmidi_params32
),
136 SNDRV_RAWMIDI_IOCTL_STATUS32
= _IOWR('W', 0x20, struct snd_rawmidi_status32
),
137 #ifdef CONFIG_X86_X32
138 SNDRV_RAWMIDI_IOCTL_STATUS_X32
= _IOWR('W', 0x20, struct snd_rawmidi_status_x32
),
139 #endif /* CONFIG_X86_X32 */
142 static long snd_rawmidi_ioctl_compat(struct file
*file
, unsigned int cmd
, unsigned long arg
)
144 struct snd_rawmidi_file
*rfile
;
145 void __user
*argp
= compat_ptr(arg
);
147 rfile
= file
->private_data
;
149 case SNDRV_RAWMIDI_IOCTL_PVERSION
:
150 case SNDRV_RAWMIDI_IOCTL_INFO
:
151 case SNDRV_RAWMIDI_IOCTL_DROP
:
152 case SNDRV_RAWMIDI_IOCTL_DRAIN
:
153 return snd_rawmidi_ioctl(file
, cmd
, (unsigned long)argp
);
154 case SNDRV_RAWMIDI_IOCTL_PARAMS32
:
155 return snd_rawmidi_ioctl_params_compat(rfile
, argp
);
156 case SNDRV_RAWMIDI_IOCTL_STATUS32
:
157 return snd_rawmidi_ioctl_status_compat(rfile
, argp
);
158 #ifdef CONFIG_X86_X32
159 case SNDRV_RAWMIDI_IOCTL_STATUS_X32
:
160 return snd_rawmidi_ioctl_status_x32(rfile
, argp
);
161 #endif /* CONFIG_X86_X32 */