|
@@ -452,6 +452,76 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
|
|
|
(joydev->exist ? 0 : (POLLHUP | POLLERR));
|
|
|
}
|
|
|
|
|
|
+static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
|
|
|
+ void __user *argp, size_t len)
|
|
|
+{
|
|
|
+ __u8 *abspam;
|
|
|
+ int i;
|
|
|
+ int retval = 0;
|
|
|
+
|
|
|
+ len = min(len, sizeof(joydev->abspam));
|
|
|
+
|
|
|
+ /* Validate the map. */
|
|
|
+ abspam = kmalloc(len, GFP_KERNEL);
|
|
|
+ if (!abspam)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (copy_from_user(abspam, argp, len)) {
|
|
|
+ retval = -EFAULT;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < joydev->nabs; i++) {
|
|
|
+ if (abspam[i] > ABS_MAX) {
|
|
|
+ retval = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(joydev->abspam, abspam, len);
|
|
|
+
|
|
|
+ out:
|
|
|
+ kfree(abspam);
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
+static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
|
|
|
+ void __user *argp, size_t len)
|
|
|
+{
|
|
|
+ __u16 *keypam;
|
|
|
+ int i;
|
|
|
+ int retval = 0;
|
|
|
+
|
|
|
+ len = min(len, sizeof(joydev->keypam));
|
|
|
+
|
|
|
+ /* Validate the map. */
|
|
|
+ keypam = kmalloc(len, GFP_KERNEL);
|
|
|
+ if (!keypam)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (copy_from_user(keypam, argp, len)) {
|
|
|
+ retval = -EFAULT;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < joydev->nkey; i++) {
|
|
|
+ if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) {
|
|
|
+ retval = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(joydev->keypam, keypam, len);
|
|
|
+
|
|
|
+ for (i = 0; i < joydev->nkey; i++)
|
|
|
+ joydev->keymap[keypam[i] - BTN_MISC] = i;
|
|
|
+
|
|
|
+ out:
|
|
|
+ kfree(keypam);
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static int joydev_ioctl_common(struct joydev *joydev,
|
|
|
unsigned int cmd, void __user *argp)
|
|
|
{
|
|
@@ -512,46 +582,18 @@ static int joydev_ioctl_common(struct joydev *joydev,
|
|
|
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++) {
|
|
|
- if (joydev->abspam[i] > ABS_MAX)
|
|
|
- return -EINVAL;
|
|
|
- joydev->absmap[joydev->abspam[i]] = i;
|
|
|
- }
|
|
|
- return 0;
|
|
|
+ return joydev_handle_JSIOCSAXMAP(joydev, argp, _IOC_SIZE(cmd));
|
|
|
|
|
|
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;
|
|
|
+ return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : len;
|
|
|
|
|
|
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++) {
|
|
|
- if (joydev->keypam[i] > KEY_MAX ||
|
|
|
- joydev->keypam[i] < BTN_MISC)
|
|
|
- return -EINVAL;
|
|
|
- joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
+ return joydev_handle_JSIOCSBTNMAP(joydev, argp, _IOC_SIZE(cmd));
|
|
|
|
|
|
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;
|
|
|
+ return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : len;
|
|
|
|
|
|
case JSIOCGNAME(0):
|
|
|
name = dev->name;
|