/*
 *   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 sndrv_seq_port_info32 {
	struct sndrv_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(client_t *client, unsigned int cmd,
					struct sndrv_seq_port_info32 __user *data32)
{
	int err = -EFAULT;
	snd_seq_port_info_t *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 sndrv_seq_port_info32),
	SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32),
	SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32),
	SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32),
	SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32),
};

static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
	client_t *client = (client_t *) 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;
}
