162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 32bit -> 64bit ioctl wrapper for raw MIDI API 462306a36Sopenharmony_ci * Copyright (c) by Takashi Iwai <tiwai@suse.de> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/* This file included from rawmidi.c */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/compat.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistruct snd_rawmidi_params32 { 1262306a36Sopenharmony_ci s32 stream; 1362306a36Sopenharmony_ci u32 buffer_size; 1462306a36Sopenharmony_ci u32 avail_min; 1562306a36Sopenharmony_ci unsigned int no_active_sensing; /* avoid bit-field */ 1662306a36Sopenharmony_ci unsigned int mode; 1762306a36Sopenharmony_ci unsigned char reserved[12]; 1862306a36Sopenharmony_ci} __attribute__((packed)); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, 2162306a36Sopenharmony_ci struct snd_rawmidi_params32 __user *src) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci struct snd_rawmidi_params params; 2462306a36Sopenharmony_ci unsigned int val; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci if (get_user(params.stream, &src->stream) || 2762306a36Sopenharmony_ci get_user(params.buffer_size, &src->buffer_size) || 2862306a36Sopenharmony_ci get_user(params.avail_min, &src->avail_min) || 2962306a36Sopenharmony_ci get_user(params.mode, &src->mode) || 3062306a36Sopenharmony_ci get_user(val, &src->no_active_sensing)) 3162306a36Sopenharmony_ci return -EFAULT; 3262306a36Sopenharmony_ci params.no_active_sensing = val; 3362306a36Sopenharmony_ci switch (params.stream) { 3462306a36Sopenharmony_ci case SNDRV_RAWMIDI_STREAM_OUTPUT: 3562306a36Sopenharmony_ci if (!rfile->output) 3662306a36Sopenharmony_ci return -EINVAL; 3762306a36Sopenharmony_ci return snd_rawmidi_output_params(rfile->output, ¶ms); 3862306a36Sopenharmony_ci case SNDRV_RAWMIDI_STREAM_INPUT: 3962306a36Sopenharmony_ci if (!rfile->input) 4062306a36Sopenharmony_ci return -EINVAL; 4162306a36Sopenharmony_ci return snd_rawmidi_input_params(rfile->input, ¶ms); 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci return -EINVAL; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct compat_snd_rawmidi_status64 { 4762306a36Sopenharmony_ci s32 stream; 4862306a36Sopenharmony_ci u8 rsvd[4]; /* alignment */ 4962306a36Sopenharmony_ci s64 tstamp_sec; 5062306a36Sopenharmony_ci s64 tstamp_nsec; 5162306a36Sopenharmony_ci u32 avail; 5262306a36Sopenharmony_ci u32 xruns; 5362306a36Sopenharmony_ci unsigned char reserved[16]; 5462306a36Sopenharmony_ci} __attribute__((packed)); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile, 5762306a36Sopenharmony_ci struct compat_snd_rawmidi_status64 __user *src) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci int err; 6062306a36Sopenharmony_ci struct snd_rawmidi_status64 status; 6162306a36Sopenharmony_ci struct compat_snd_rawmidi_status64 compat_status; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (get_user(status.stream, &src->stream)) 6462306a36Sopenharmony_ci return -EFAULT; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci switch (status.stream) { 6762306a36Sopenharmony_ci case SNDRV_RAWMIDI_STREAM_OUTPUT: 6862306a36Sopenharmony_ci if (!rfile->output) 6962306a36Sopenharmony_ci return -EINVAL; 7062306a36Sopenharmony_ci err = snd_rawmidi_output_status(rfile->output, &status); 7162306a36Sopenharmony_ci break; 7262306a36Sopenharmony_ci case SNDRV_RAWMIDI_STREAM_INPUT: 7362306a36Sopenharmony_ci if (!rfile->input) 7462306a36Sopenharmony_ci return -EINVAL; 7562306a36Sopenharmony_ci err = snd_rawmidi_input_status(rfile->input, &status); 7662306a36Sopenharmony_ci break; 7762306a36Sopenharmony_ci default: 7862306a36Sopenharmony_ci return -EINVAL; 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci if (err < 0) 8162306a36Sopenharmony_ci return err; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci compat_status = (struct compat_snd_rawmidi_status64) { 8462306a36Sopenharmony_ci .stream = status.stream, 8562306a36Sopenharmony_ci .tstamp_sec = status.tstamp_sec, 8662306a36Sopenharmony_ci .tstamp_nsec = status.tstamp_nsec, 8762306a36Sopenharmony_ci .avail = status.avail, 8862306a36Sopenharmony_ci .xruns = status.xruns, 8962306a36Sopenharmony_ci }; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (copy_to_user(src, &compat_status, sizeof(*src))) 9262306a36Sopenharmony_ci return -EFAULT; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci return 0; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cienum { 9862306a36Sopenharmony_ci SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), 9962306a36Sopenharmony_ci SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), 10062306a36Sopenharmony_ci SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64), 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci struct snd_rawmidi_file *rfile; 10662306a36Sopenharmony_ci void __user *argp = compat_ptr(arg); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci rfile = file->private_data; 10962306a36Sopenharmony_ci switch (cmd) { 11062306a36Sopenharmony_ci case SNDRV_RAWMIDI_IOCTL_PVERSION: 11162306a36Sopenharmony_ci case SNDRV_RAWMIDI_IOCTL_INFO: 11262306a36Sopenharmony_ci case SNDRV_RAWMIDI_IOCTL_DROP: 11362306a36Sopenharmony_ci case SNDRV_RAWMIDI_IOCTL_DRAIN: 11462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_UMP) 11562306a36Sopenharmony_ci case SNDRV_UMP_IOCTL_ENDPOINT_INFO: 11662306a36Sopenharmony_ci case SNDRV_UMP_IOCTL_BLOCK_INFO: 11762306a36Sopenharmony_ci#endif 11862306a36Sopenharmony_ci return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp); 11962306a36Sopenharmony_ci case SNDRV_RAWMIDI_IOCTL_PARAMS32: 12062306a36Sopenharmony_ci return snd_rawmidi_ioctl_params_compat(rfile, argp); 12162306a36Sopenharmony_ci case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32: 12262306a36Sopenharmony_ci return snd_rawmidi_ioctl_status32(rfile, argp); 12362306a36Sopenharmony_ci case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64: 12462306a36Sopenharmony_ci return snd_rawmidi_ioctl_status_compat64(rfile, argp); 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci return -ENOIOCTLCMD; 12762306a36Sopenharmony_ci} 128