Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 024ac44c authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Dmitry Torokhov
Browse files

Input: This patch implements compat_ioctl for joydev.



       I've tested it with a Logitech WingMan Rumblepad on an x86-64
       machine, and on an ia32 machine to make sure I didn't break
       anything.

Signed-off-by: default avatarJeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarVojtech Pavlik <vojtech@suse.cz>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent f23488b2
Loading
Loading
Loading
Loading
+91 −25
Original line number Diff line number Diff line
@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
		(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
}

static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
{
	struct joydev_list *list = file->private_data;
	struct joydev *joydev = list->joydev;
	struct input_dev *dev = joydev->handle.dev;
	void __user *argp = (void __user *)arg;
	int i, j;

	if (!joydev->exist) return -ENODEV;

	switch (cmd) {

		case JS_SET_CAL:
			return copy_from_user(&joydev->glue.JS_CORR, argp,
				sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
				sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
		case JS_GET_CAL:
			return copy_to_user(argp, &joydev->glue.JS_CORR,
				sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
				sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
		case JS_SET_TIMEOUT:
			return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
			return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
		case JS_GET_TIMEOUT:
			return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg);
		case JS_SET_TIMELIMIT:
			return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
		case JS_GET_TIMELIMIT:
			return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
		case JS_SET_ALL:
			return copy_from_user(&joydev->glue, argp,
						sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
		case JS_GET_ALL:
			return copy_to_user(argp, &joydev->glue,
						sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
			return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);

		case JSIOCGVERSION:
			return put_user(JS_VERSION, (__u32 __user *) arg);
			return put_user(JS_VERSION, (__u32 __user *) argp);
		case JSIOCGAXES:
			return put_user(joydev->nabs, (__u8 __user *) arg);
			return put_user(joydev->nabs, (__u8 __user *) argp);
		case JSIOCGBUTTONS:
			return put_user(joydev->nkey, (__u8 __user *) arg);
			return put_user(joydev->nkey, (__u8 __user *) argp);
		case JSIOCSCORR:
			if (copy_from_user(joydev->corr, argp,
				      sizeof(struct js_corr) * joydev->nabs))
				      sizeof(joydev->corr[0]) * joydev->nabs))
			    return -EFAULT;
			for (i = 0; i < joydev->nabs; i++) {
				j = joydev->abspam[i];
@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
			return 0;
		case JSIOCGCORR:
			return copy_to_user(argp, joydev->corr,
						sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
						sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
		case JSIOCSAXMAP:
			if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
				return -EFAULT;
@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
	return -EINVAL;
}

#ifdef CONFIG_COMPAT
static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct joydev_list *list = file->private_data;
	struct joydev *joydev = list->joydev;
	void __user *argp = (void __user *)arg;
	s32 tmp32;
	struct JS_DATA_SAVE_TYPE_32 ds32;
	int err;

	if (!joydev->exist) return -ENODEV;
	switch(cmd) {
	case JS_SET_TIMELIMIT:
		err = get_user(tmp32, (s32 __user *) arg);
		if (err == 0)
			joydev->glue.JS_TIMELIMIT = tmp32;
		break;
	case JS_GET_TIMELIMIT:
		tmp32 = joydev->glue.JS_TIMELIMIT;
		err = put_user(tmp32, (s32 __user *) arg);
		break;

	case JS_SET_ALL:
		err = copy_from_user(&ds32, argp,
				     sizeof(ds32)) ? -EFAULT : 0;
		if (err == 0) {
			joydev->glue.JS_TIMEOUT    = ds32.JS_TIMEOUT;
			joydev->glue.BUSY          = ds32.BUSY;
			joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME;
			joydev->glue.JS_TIMELIMIT  = ds32.JS_TIMELIMIT;
			joydev->glue.JS_SAVE       = ds32.JS_SAVE;
			joydev->glue.JS_CORR       = ds32.JS_CORR;
		}
		break;

	case JS_GET_ALL:
		ds32.JS_TIMEOUT    = joydev->glue.JS_TIMEOUT;
		ds32.BUSY          = joydev->glue.BUSY;
		ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME;
		ds32.JS_TIMELIMIT  = joydev->glue.JS_TIMELIMIT;
		ds32.JS_SAVE       = joydev->glue.JS_SAVE;
		ds32.JS_CORR       = joydev->glue.JS_CORR;

		err = copy_to_user(argp, &ds32,
					  sizeof(ds32)) ? -EFAULT : 0;
		break;

	default:
		err = joydev_ioctl_common(joydev, cmd, argp);
	}
	return err;
}
#endif /* CONFIG_COMPAT */

static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	struct joydev_list *list = file->private_data;
	struct joydev *joydev = list->joydev;
	void __user *argp = (void __user *)arg;

	if (!joydev->exist) return -ENODEV;

	switch(cmd) {
		case JS_SET_TIMELIMIT:
			return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
		case JS_GET_TIMELIMIT:
			return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg);
		case JS_SET_ALL:
			return copy_from_user(&joydev->glue, argp,
						sizeof(joydev->glue)) ? -EFAULT : 0;
		case JS_GET_ALL:
			return copy_to_user(argp, &joydev->glue,
						sizeof(joydev->glue)) ? -EFAULT : 0;
		default:
			return joydev_ioctl_common(joydev, cmd, argp);
	}
}

static struct file_operations joydev_fops = {
	.owner =	THIS_MODULE,
	.read =		joydev_read,
@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = {
	.open =		joydev_open,
	.release =	joydev_release,
	.ioctl =	joydev_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl =	joydev_compat_ioctl,
#endif
	.fasync =	joydev_fasync,
};

+25 −8
Original line number Diff line number Diff line
@@ -111,18 +111,35 @@ struct js_corr {
#define JS_SET_ALL		8

struct JS_DATA_TYPE {
	int buttons;
	int x;
	int y;
	__s32 buttons;
	__s32 x;
	__s32 y;
};

struct JS_DATA_SAVE_TYPE {
	int JS_TIMEOUT;
	int BUSY;
	long JS_EXPIRETIME;
	long JS_TIMELIMIT;
struct JS_DATA_SAVE_TYPE_32 {
	__s32 JS_TIMEOUT;
	__s32 BUSY;
	__s32 JS_EXPIRETIME;
	__s32 JS_TIMELIMIT;
	struct JS_DATA_TYPE JS_SAVE;
	struct JS_DATA_TYPE JS_CORR;
};

struct JS_DATA_SAVE_TYPE_64 {
	__s32 JS_TIMEOUT;
	__s32 BUSY;
	__s64 JS_EXPIRETIME;
	__s64 JS_TIMELIMIT;
	struct JS_DATA_TYPE JS_SAVE;
	struct JS_DATA_TYPE JS_CORR;
};

#if BITS_PER_LONG == 64
#define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64
#elif BITS_PER_LONG == 32
#define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_32
#else
#error Unexpected BITS_PER_LONG
#endif

#endif /* _LINUX_JOYSTICK_H */