11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * 32bit -> 64bit ioctl wrapper for raw MIDI API 41da177e4SLinus Torvalds * Copyright (c) by Takashi Iwai <tiwai@suse.de> 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds /* This file included from rawmidi.c */ 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #include <linux/compat.h> 101da177e4SLinus Torvalds 1148c9d417STakashi Iwai struct snd_rawmidi_params32 { 121da177e4SLinus Torvalds s32 stream; 131da177e4SLinus Torvalds u32 buffer_size; 141da177e4SLinus Torvalds u32 avail_min; 151da177e4SLinus Torvalds unsigned int no_active_sensing; /* avoid bit-field */ 161da177e4SLinus Torvalds unsigned char reserved[16]; 171da177e4SLinus Torvalds } __attribute__((packed)); 181da177e4SLinus Torvalds 1948c9d417STakashi Iwai static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, 2048c9d417STakashi Iwai struct snd_rawmidi_params32 __user *src) 211da177e4SLinus Torvalds { 2248c9d417STakashi Iwai struct snd_rawmidi_params params; 231da177e4SLinus Torvalds unsigned int val; 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds if (get_user(params.stream, &src->stream) || 261da177e4SLinus Torvalds get_user(params.buffer_size, &src->buffer_size) || 271da177e4SLinus Torvalds get_user(params.avail_min, &src->avail_min) || 281da177e4SLinus Torvalds get_user(val, &src->no_active_sensing)) 291da177e4SLinus Torvalds return -EFAULT; 301da177e4SLinus Torvalds params.no_active_sensing = val; 311da177e4SLinus Torvalds switch (params.stream) { 321da177e4SLinus Torvalds case SNDRV_RAWMIDI_STREAM_OUTPUT: 338a56ef4fSTakashi Iwai if (!rfile->output) 348a56ef4fSTakashi Iwai return -EINVAL; 351da177e4SLinus Torvalds return snd_rawmidi_output_params(rfile->output, ¶ms); 361da177e4SLinus Torvalds case SNDRV_RAWMIDI_STREAM_INPUT: 378a56ef4fSTakashi Iwai if (!rfile->input) 388a56ef4fSTakashi Iwai return -EINVAL; 391da177e4SLinus Torvalds return snd_rawmidi_input_params(rfile->input, ¶ms); 401da177e4SLinus Torvalds } 411da177e4SLinus Torvalds return -EINVAL; 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds 4448c9d417STakashi Iwai struct snd_rawmidi_status32 { 451da177e4SLinus Torvalds s32 stream; 461da177e4SLinus Torvalds struct compat_timespec tstamp; 471da177e4SLinus Torvalds u32 avail; 481da177e4SLinus Torvalds u32 xruns; 491da177e4SLinus Torvalds unsigned char reserved[16]; 501da177e4SLinus Torvalds } __attribute__((packed)); 511da177e4SLinus Torvalds 5248c9d417STakashi Iwai static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, 5348c9d417STakashi Iwai struct snd_rawmidi_status32 __user *src) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds int err; 5648c9d417STakashi Iwai struct snd_rawmidi_status status; 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds if (get_user(status.stream, &src->stream)) 591da177e4SLinus Torvalds return -EFAULT; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds switch (status.stream) { 621da177e4SLinus Torvalds case SNDRV_RAWMIDI_STREAM_OUTPUT: 638a56ef4fSTakashi Iwai if (!rfile->output) 648a56ef4fSTakashi Iwai return -EINVAL; 651da177e4SLinus Torvalds err = snd_rawmidi_output_status(rfile->output, &status); 661da177e4SLinus Torvalds break; 671da177e4SLinus Torvalds case SNDRV_RAWMIDI_STREAM_INPUT: 688a56ef4fSTakashi Iwai if (!rfile->input) 698a56ef4fSTakashi Iwai return -EINVAL; 701da177e4SLinus Torvalds err = snd_rawmidi_input_status(rfile->input, &status); 711da177e4SLinus Torvalds break; 721da177e4SLinus Torvalds default: 731da177e4SLinus Torvalds return -EINVAL; 741da177e4SLinus Torvalds } 751da177e4SLinus Torvalds if (err < 0) 761da177e4SLinus Torvalds return err; 771da177e4SLinus Torvalds 78dd7e3f80STakashi Iwai if (compat_put_timespec(&status.tstamp, &src->tstamp) || 791da177e4SLinus Torvalds put_user(status.avail, &src->avail) || 801da177e4SLinus Torvalds put_user(status.xruns, &src->xruns)) 811da177e4SLinus Torvalds return -EFAULT; 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds return 0; 841da177e4SLinus Torvalds } 851da177e4SLinus Torvalds 862251fbbcSTakashi Iwai #ifdef CONFIG_X86_X32 872251fbbcSTakashi Iwai /* X32 ABI has 64bit timespec and 64bit alignment */ 882251fbbcSTakashi Iwai struct snd_rawmidi_status_x32 { 892251fbbcSTakashi Iwai s32 stream; 902251fbbcSTakashi Iwai u32 rsvd; /* alignment */ 912251fbbcSTakashi Iwai struct timespec tstamp; 922251fbbcSTakashi Iwai u32 avail; 932251fbbcSTakashi Iwai u32 xruns; 942251fbbcSTakashi Iwai unsigned char reserved[16]; 952251fbbcSTakashi Iwai } __attribute__((packed)); 962251fbbcSTakashi Iwai 972251fbbcSTakashi Iwai #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) 982251fbbcSTakashi Iwai 992251fbbcSTakashi Iwai static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, 1002251fbbcSTakashi Iwai struct snd_rawmidi_status_x32 __user *src) 1012251fbbcSTakashi Iwai { 1022251fbbcSTakashi Iwai int err; 1032251fbbcSTakashi Iwai struct snd_rawmidi_status status; 1042251fbbcSTakashi Iwai 1052251fbbcSTakashi Iwai if (get_user(status.stream, &src->stream)) 1062251fbbcSTakashi Iwai return -EFAULT; 1072251fbbcSTakashi Iwai 1082251fbbcSTakashi Iwai switch (status.stream) { 1092251fbbcSTakashi Iwai case SNDRV_RAWMIDI_STREAM_OUTPUT: 1108a56ef4fSTakashi Iwai if (!rfile->output) 1118a56ef4fSTakashi Iwai return -EINVAL; 1122251fbbcSTakashi Iwai err = snd_rawmidi_output_status(rfile->output, &status); 1132251fbbcSTakashi Iwai break; 1142251fbbcSTakashi Iwai case SNDRV_RAWMIDI_STREAM_INPUT: 1158a56ef4fSTakashi Iwai if (!rfile->input) 1168a56ef4fSTakashi Iwai return -EINVAL; 1172251fbbcSTakashi Iwai err = snd_rawmidi_input_status(rfile->input, &status); 1182251fbbcSTakashi Iwai break; 1192251fbbcSTakashi Iwai default: 1202251fbbcSTakashi Iwai return -EINVAL; 1212251fbbcSTakashi Iwai } 1222251fbbcSTakashi Iwai if (err < 0) 1232251fbbcSTakashi Iwai return err; 1242251fbbcSTakashi Iwai 1252251fbbcSTakashi Iwai if (put_timespec(&status.tstamp, &src->tstamp) || 1262251fbbcSTakashi Iwai put_user(status.avail, &src->avail) || 1272251fbbcSTakashi Iwai put_user(status.xruns, &src->xruns)) 1282251fbbcSTakashi Iwai return -EFAULT; 1292251fbbcSTakashi Iwai 1302251fbbcSTakashi Iwai return 0; 1312251fbbcSTakashi Iwai } 1322251fbbcSTakashi Iwai #endif /* CONFIG_X86_X32 */ 1332251fbbcSTakashi Iwai 1341da177e4SLinus Torvalds enum { 13548c9d417STakashi Iwai SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), 13648c9d417STakashi Iwai SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), 1372251fbbcSTakashi Iwai #ifdef CONFIG_X86_X32 1382251fbbcSTakashi Iwai SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32), 1392251fbbcSTakashi Iwai #endif /* CONFIG_X86_X32 */ 1401da177e4SLinus Torvalds }; 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) 1431da177e4SLinus Torvalds { 14448c9d417STakashi Iwai struct snd_rawmidi_file *rfile; 1451da177e4SLinus Torvalds void __user *argp = compat_ptr(arg); 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds rfile = file->private_data; 1481da177e4SLinus Torvalds switch (cmd) { 1491da177e4SLinus Torvalds case SNDRV_RAWMIDI_IOCTL_PVERSION: 1501da177e4SLinus Torvalds case SNDRV_RAWMIDI_IOCTL_INFO: 1511da177e4SLinus Torvalds case SNDRV_RAWMIDI_IOCTL_DROP: 1521da177e4SLinus Torvalds case SNDRV_RAWMIDI_IOCTL_DRAIN: 1531da177e4SLinus Torvalds return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp); 1541da177e4SLinus Torvalds case SNDRV_RAWMIDI_IOCTL_PARAMS32: 1551da177e4SLinus Torvalds return snd_rawmidi_ioctl_params_compat(rfile, argp); 1561da177e4SLinus Torvalds case SNDRV_RAWMIDI_IOCTL_STATUS32: 1571da177e4SLinus Torvalds return snd_rawmidi_ioctl_status_compat(rfile, argp); 1582251fbbcSTakashi Iwai #ifdef CONFIG_X86_X32 1592251fbbcSTakashi Iwai case SNDRV_RAWMIDI_IOCTL_STATUS_X32: 1602251fbbcSTakashi Iwai return snd_rawmidi_ioctl_status_x32(rfile, argp); 1612251fbbcSTakashi Iwai #endif /* CONFIG_X86_X32 */ 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds return -ENOIOCTLCMD; 1641da177e4SLinus Torvalds } 165