| /* |
| * 32bit -> 64bit ioctl wrapper for sequencer API |
| * Copyright (c) by Takashi Iwai <tiwai@suse.de> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| */ |
| |
| /* This file included from seq.c */ |
| |
| #include <linux/compat.h> |
| |
| struct snd_seq_port_info32 { |
| struct snd_seq_addr addr; /* client/port numbers */ |
| char name[64]; /* port name */ |
| |
| u32 capability; /* port capability bits */ |
| u32 type; /* port type bits */ |
| s32 midi_channels; /* channels per MIDI port */ |
| s32 midi_voices; /* voices per MIDI port */ |
| s32 synth_voices; /* voices per SYNTH port */ |
| |
| s32 read_use; /* R/O: subscribers for output (from this port) */ |
| s32 write_use; /* R/O: subscribers for input (to this port) */ |
| |
| u32 kernel; /* reserved for kernel use (must be NULL) */ |
| u32 flags; /* misc. conditioning */ |
| unsigned char time_queue; /* queue # for timestamping */ |
| char reserved[59]; /* for future use */ |
| }; |
| |
| static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd, |
| struct snd_seq_port_info32 __user *data32) |
| { |
| int err = -EFAULT; |
| struct snd_seq_port_info *data; |
| mm_segment_t fs; |
| |
| data = kmalloc(sizeof(*data), GFP_KERNEL); |
| if (! data) |
| return -ENOMEM; |
| |
| if (copy_from_user(data, data32, sizeof(*data32)) || |
| get_user(data->flags, &data32->flags) || |
| get_user(data->time_queue, &data32->time_queue)) |
| goto error; |
| data->kernel = NULL; |
| |
| fs = snd_enter_user(); |
| err = snd_seq_do_ioctl(client, cmd, data); |
| snd_leave_user(fs); |
| if (err < 0) |
| goto error; |
| |
| if (copy_to_user(data32, data, sizeof(*data32)) || |
| put_user(data->flags, &data32->flags) || |
| put_user(data->time_queue, &data32->time_queue)) |
| err = -EFAULT; |
| |
| error: |
| kfree(data); |
| return err; |
| } |
| |
| |
| |
| /* |
| */ |
| |
| enum { |
| SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct snd_seq_port_info32), |
| SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct snd_seq_port_info32), |
| SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct snd_seq_port_info32), |
| SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct snd_seq_port_info32), |
| SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct snd_seq_port_info32), |
| }; |
| |
| static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
| { |
| struct snd_seq_client *client = file->private_data; |
| void __user *argp = compat_ptr(arg); |
| |
| snd_assert(client != NULL, return -ENXIO); |
| |
| switch (cmd) { |
| case SNDRV_SEQ_IOCTL_PVERSION: |
| case SNDRV_SEQ_IOCTL_CLIENT_ID: |
| case SNDRV_SEQ_IOCTL_SYSTEM_INFO: |
| case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO: |
| case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO: |
| case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT: |
| case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT: |
| case SNDRV_SEQ_IOCTL_CREATE_QUEUE: |
| case SNDRV_SEQ_IOCTL_DELETE_QUEUE: |
| case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO: |
| case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO: |
| case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE: |
| case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS: |
| case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO: |
| case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO: |
| case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER: |
| case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER: |
| case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT: |
| case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT: |
| case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL: |
| case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL: |
| case SNDRV_SEQ_IOCTL_REMOVE_EVENTS: |
| case SNDRV_SEQ_IOCTL_QUERY_SUBS: |
| case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: |
| case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: |
| case SNDRV_SEQ_IOCTL_RUNNING_MODE: |
| return snd_seq_do_ioctl(client, cmd, argp); |
| case SNDRV_SEQ_IOCTL_CREATE_PORT32: |
| return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); |
| case SNDRV_SEQ_IOCTL_DELETE_PORT32: |
| return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp); |
| case SNDRV_SEQ_IOCTL_GET_PORT_INFO32: |
| return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp); |
| case SNDRV_SEQ_IOCTL_SET_PORT_INFO32: |
| return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp); |
| case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32: |
| return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp); |
| } |
| return -ENOIOCTLCMD; |
| } |