aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joydev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/joydev.c')
-rw-r--r--drivers/input/joydev.c106
1 files changed, 74 insertions, 32 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 9a1d55b74d7a..901b2525993e 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -452,6 +452,76 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
452 (joydev->exist ? 0 : (POLLHUP | POLLERR)); 452 (joydev->exist ? 0 : (POLLHUP | POLLERR));
453} 453}
454 454
455static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
456 void __user *argp, size_t len)
457{
458 __u8 *abspam;
459 int i;
460 int retval = 0;
461
462 len = min(len, sizeof(joydev->abspam));
463
464 /* Validate the map. */
465 abspam = kmalloc(len, GFP_KERNEL);
466 if (!abspam)
467 return -ENOMEM;
468
469 if (copy_from_user(abspam, argp, len)) {
470 retval = -EFAULT;
471 goto out;
472 }
473
474 for (i = 0; i < joydev->nabs; i++) {
475 if (abspam[i] > ABS_MAX) {
476 retval = -EINVAL;
477 goto out;
478 }
479 }
480
481 memcpy(joydev->abspam, abspam, len);
482
483 out:
484 kfree(abspam);
485 return retval;
486}
487
488static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
489 void __user *argp, size_t len)
490{
491 __u16 *keypam;
492 int i;
493 int retval = 0;
494
495 len = min(len, sizeof(joydev->keypam));
496
497 /* Validate the map. */
498 keypam = kmalloc(len, GFP_KERNEL);
499 if (!keypam)
500 return -ENOMEM;
501
502 if (copy_from_user(keypam, argp, len)) {
503 retval = -EFAULT;
504 goto out;
505 }
506
507 for (i = 0; i < joydev->nkey; i++) {
508 if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) {
509 retval = -EINVAL;
510 goto out;
511 }
512 }
513
514 memcpy(joydev->keypam, keypam, len);
515
516 for (i = 0; i < joydev->nkey; i++)
517 joydev->keymap[keypam[i] - BTN_MISC] = i;
518
519 out:
520 kfree(keypam);
521 return retval;
522}
523
524
455static int joydev_ioctl_common(struct joydev *joydev, 525static int joydev_ioctl_common(struct joydev *joydev,
456 unsigned int cmd, void __user *argp) 526 unsigned int cmd, void __user *argp)
457{ 527{
@@ -512,46 +582,18 @@ static int joydev_ioctl_common(struct joydev *joydev,
512 switch (cmd & ~IOCSIZE_MASK) { 582 switch (cmd & ~IOCSIZE_MASK) {
513 583
514 case (JSIOCSAXMAP & ~IOCSIZE_MASK): 584 case (JSIOCSAXMAP & ~IOCSIZE_MASK):
515 len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); 585 return joydev_handle_JSIOCSAXMAP(joydev, argp, _IOC_SIZE(cmd));
516 /*
517 * FIXME: we should not copy into our axis map before
518 * validating the data.
519 */
520 if (copy_from_user(joydev->abspam, argp, len))
521 return -EFAULT;
522
523 for (i = 0; i < joydev->nabs; i++) {
524 if (joydev->abspam[i] > ABS_MAX)
525 return -EINVAL;
526 joydev->absmap[joydev->abspam[i]] = i;
527 }
528 return 0;
529 586
530 case (JSIOCGAXMAP & ~IOCSIZE_MASK): 587 case (JSIOCGAXMAP & ~IOCSIZE_MASK):
531 len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); 588 len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
532 return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0; 589 return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : len;
533 590
534 case (JSIOCSBTNMAP & ~IOCSIZE_MASK): 591 case (JSIOCSBTNMAP & ~IOCSIZE_MASK):
535 len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); 592 return joydev_handle_JSIOCSBTNMAP(joydev, argp, _IOC_SIZE(cmd));
536 /*
537 * FIXME: we should not copy into our keymap before
538 * validating the data.
539 */
540 if (copy_from_user(joydev->keypam, argp, len))
541 return -EFAULT;
542
543 for (i = 0; i < joydev->nkey; i++) {
544 if (joydev->keypam[i] > KEY_MAX ||
545 joydev->keypam[i] < BTN_MISC)
546 return -EINVAL;
547 joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
548 }
549
550 return 0;
551 593
552 case (JSIOCGBTNMAP & ~IOCSIZE_MASK): 594 case (JSIOCGBTNMAP & ~IOCSIZE_MASK):
553 len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); 595 len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
554 return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0; 596 return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : len;
555 597
556 case JSIOCGNAME(0): 598 case JSIOCGNAME(0):
557 name = dev->name; 599 name = dev->name;