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

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
...@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) ...@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); (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; struct input_dev *dev = joydev->handle.dev;
void __user *argp = (void __user *)arg;
int i, j; int i, j;
if (!joydev->exist) return -ENODEV;
switch (cmd) { switch (cmd) {
case JS_SET_CAL: case JS_SET_CAL:
return copy_from_user(&joydev->glue.JS_CORR, argp, 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: case JS_GET_CAL:
return copy_to_user(argp, &joydev->glue.JS_CORR, 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: 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: case JS_GET_TIMEOUT:
return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
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;
case JSIOCGVERSION: case JSIOCGVERSION:
return put_user(JS_VERSION, (__u32 __user *) arg); return put_user(JS_VERSION, (__u32 __user *) argp);
case JSIOCGAXES: case JSIOCGAXES:
return put_user(joydev->nabs, (__u8 __user *) arg); return put_user(joydev->nabs, (__u8 __user *) argp);
case JSIOCGBUTTONS: case JSIOCGBUTTONS:
return put_user(joydev->nkey, (__u8 __user *) arg); return put_user(joydev->nkey, (__u8 __user *) argp);
case JSIOCSCORR: case JSIOCSCORR:
if (copy_from_user(joydev->corr, argp, if (copy_from_user(joydev->corr, argp,
sizeof(struct js_corr) * joydev->nabs)) sizeof(joydev->corr[0]) * joydev->nabs))
return -EFAULT; return -EFAULT;
for (i = 0; i < joydev->nabs; i++) { for (i = 0; i < joydev->nabs; i++) {
j = joydev->abspam[i]; j = joydev->abspam[i];
...@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return 0; return 0;
case JSIOCGCORR: case JSIOCGCORR:
return copy_to_user(argp, joydev->corr, 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: case JSIOCSAXMAP:
if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
return -EFAULT; return -EFAULT;
...@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return -EINVAL; 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 = { static struct file_operations joydev_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = joydev_read, .read = joydev_read,
...@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = { ...@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = {
.open = joydev_open, .open = joydev_open,
.release = joydev_release, .release = joydev_release,
.ioctl = joydev_ioctl, .ioctl = joydev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = joydev_compat_ioctl,
#endif
.fasync = joydev_fasync, .fasync = joydev_fasync,
}; };
......
...@@ -111,18 +111,35 @@ struct js_corr { ...@@ -111,18 +111,35 @@ struct js_corr {
#define JS_SET_ALL 8 #define JS_SET_ALL 8
struct JS_DATA_TYPE { struct JS_DATA_TYPE {
int buttons; __s32 buttons;
int x; __s32 x;
int y; __s32 y;
}; };
struct JS_DATA_SAVE_TYPE { struct JS_DATA_SAVE_TYPE_32 {
int JS_TIMEOUT; __s32 JS_TIMEOUT;
int BUSY; __s32 BUSY;
long JS_EXPIRETIME; __s32 JS_EXPIRETIME;
long JS_TIMELIMIT; __s32 JS_TIMELIMIT;
struct JS_DATA_TYPE JS_SAVE; struct JS_DATA_TYPE JS_SAVE;
struct JS_DATA_TYPE JS_CORR; 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 */ #endif /* _LINUX_JOYSTICK_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment