From: Jeremy Fitzhardinge 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: Jeremy Fitzhardinge Signed-off-by: Andrew Morton --- 25-akpm/drivers/input/joydev.c | 116 ++++++++++++++++++++++++++++++--------- 25-akpm/include/linux/joystick.h | 33 ++++++++--- 2 files changed, 116 insertions(+), 33 deletions(-) diff -puN drivers/input/joydev.c~implement-compat_ioctl-for-joydev drivers/input/joydev.c --- 25/drivers/input/joydev.c~implement-compat_ioctl-for-joydev Sun Mar 6 17:33:24 2005 +++ 25-akpm/drivers/input/joydev.c Sun Mar 6 17:33:24 2005 @@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct f (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 *in 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 *in return -EINVAL; } +#ifdef CONFIG_COMPAT +static long joydev_compat_ioctl(struct file *file, unsigned 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_fop .open = joydev_open, .release = joydev_release, .ioctl = joydev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = joydev_compat_ioctl, +#endif .fasync = joydev_fasync, }; diff -puN include/linux/joystick.h~implement-compat_ioctl-for-joydev include/linux/joystick.h --- 25/include/linux/joystick.h~implement-compat_ioctl-for-joydev Sun Mar 6 17:33:24 2005 +++ 25-akpm/include/linux/joystick.h Sun Mar 6 17:33:24 2005 @@ -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 */ _