128 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * 32bit -> 64bit ioctl wrapper for raw MIDI API4 * Copyright (c) by Takashi Iwai <tiwai@suse.de>5 */6 7/* This file included from rawmidi.c */8 9#include <linux/compat.h>10 11struct 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 20static 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, ¶ms);38 case SNDRV_RAWMIDI_STREAM_INPUT:39 if (!rfile->input)40 return -EINVAL;41 return snd_rawmidi_input_params(rfile->input, ¶ms);42 }43 return -EINVAL;44}45 46struct 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 56static 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 97enum {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 103static 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#endif118 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