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: Jeremy Fitzhardinge <jeremy@goop.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Vojtech Pavlik <vojtech@suse.cz> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
parent
f23488b2ab
commit
024ac44c70
2 changed files with 116 additions and 33 deletions
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue