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