Skip to content

Commit

Permalink
Input: joydev - decouple axis and button map ioctls from input constants
Browse files Browse the repository at this point in the history
The KEY_MAX change in 2.6.28 changed the values of the JSIOCSBTNMAP and
JSIOCGBTNMAP constants; software compiled with the old values no longer
works with kernels following 2.6.28, because the ioctl switch statement
no longer matches the values given by the software. This patch handles
these ioctls independently of the length of data specified, and applies the
same treatment to JSIOCSAXMAP and JSIOCGAXMAP which currently depend on
ABS_MAX.

Signed-off-by: Stephen Kitt <steve@sk2.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
  • Loading branch information
Stephen Kitt authored and Dmitry Torokhov committed Aug 12, 2009
1 parent d82f1c3 commit ec8b4b7
Showing 1 changed file with 41 additions and 27 deletions.
68 changes: 41 additions & 27 deletions drivers/input/joydev.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,11 @@ static int joydev_ioctl_common(struct joydev *joydev,
unsigned int cmd, void __user *argp)
{
struct input_dev *dev = joydev->handle.dev;
size_t len;
int i, j;
const char *name;

/* Process fixed-sized commands. */
switch (cmd) {

case JS_SET_CAL:
Expand Down Expand Up @@ -499,9 +502,22 @@ static int joydev_ioctl_common(struct joydev *joydev,
return copy_to_user(argp, joydev->corr,
sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;

case JSIOCSAXMAP:
if (copy_from_user(joydev->abspam, argp,
sizeof(__u8) * (ABS_MAX + 1)))
}

/*
* Process variable-sized commands (the axis and button map commands
* are considered variable-sized to decouple them from the values of
* ABS_MAX and KEY_MAX).
*/
switch (cmd & ~IOCSIZE_MASK) {

case (JSIOCSAXMAP & ~IOCSIZE_MASK):
len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
/*
* FIXME: we should not copy into our axis map before
* validating the data.
*/
if (copy_from_user(joydev->abspam, argp, len))
return -EFAULT;

for (i = 0; i < joydev->nabs; i++) {
Expand All @@ -511,13 +527,17 @@ static int joydev_ioctl_common(struct joydev *joydev,
}
return 0;

case JSIOCGAXMAP:
return copy_to_user(argp, joydev->abspam,
sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;

case JSIOCSBTNMAP:
if (copy_from_user(joydev->keypam, argp,
sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
case (JSIOCGAXMAP & ~IOCSIZE_MASK):
len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0;

case (JSIOCSBTNMAP & ~IOCSIZE_MASK):
len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
/*
* FIXME: we should not copy into our keymap before
* validating the data.
*/
if (copy_from_user(joydev->keypam, argp, len))
return -EFAULT;

for (i = 0; i < joydev->nkey; i++) {
Expand All @@ -529,25 +549,19 @@ static int joydev_ioctl_common(struct joydev *joydev,

return 0;

case JSIOCGBTNMAP:
return copy_to_user(argp, joydev->keypam,
sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
case (JSIOCGBTNMAP & ~IOCSIZE_MASK):
len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0;

default:
if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
int len;
const char *name = dev->name;

if (!name)
return 0;
len = strlen(name) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
if (copy_to_user(argp, name, len))
return -EFAULT;
return len;
}
case JSIOCGNAME(0):
name = dev->name;
if (!name)
return 0;

len = min_t(size_t, _IOC_SIZE(cmd), strlen(name) + 1);
return copy_to_user(argp, name, len) ? -EFAULT : len;
}

return -EINVAL;
}

Expand Down

0 comments on commit ec8b4b7

Please sign in to comment.