aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/evdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r--drivers/input/evdev.c100
1 files changed, 80 insertions, 20 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c908c5f83645..1ce9bf663206 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -534,6 +534,80 @@ static int handle_eviocgbit(struct input_dev *dev,
534} 534}
535#undef OLD_KEY_MAX 535#undef OLD_KEY_MAX
536 536
537static int evdev_handle_get_keycode(struct input_dev *dev,
538 void __user *p, size_t size)
539{
540 struct input_keymap_entry ke;
541 int error;
542
543 memset(&ke, 0, sizeof(ke));
544
545 if (size == sizeof(unsigned int[2])) {
546 /* legacy case */
547 int __user *ip = (int __user *)p;
548
549 if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
550 return -EFAULT;
551
552 ke.len = sizeof(unsigned int);
553 ke.flags = 0;
554
555 error = input_get_keycode(dev, &ke);
556 if (error)
557 return error;
558
559 if (put_user(ke.keycode, ip + 1))
560 return -EFAULT;
561
562 } else {
563 size = min(size, sizeof(ke));
564
565 if (copy_from_user(&ke, p, size))
566 return -EFAULT;
567
568 error = input_get_keycode(dev, &ke);
569 if (error)
570 return error;
571
572 if (copy_to_user(p, &ke, size))
573 return -EFAULT;
574 }
575 return 0;
576}
577
578static int evdev_handle_set_keycode(struct input_dev *dev,
579 void __user *p, size_t size)
580{
581 struct input_keymap_entry ke;
582
583 memset(&ke, 0, sizeof(ke));
584
585 if (size == sizeof(unsigned int[2])) {
586 /* legacy case */
587 int __user *ip = (int __user *)p;
588
589 if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
590 return -EFAULT;
591
592 if (get_user(ke.keycode, ip + 1))
593 return -EFAULT;
594
595 ke.len = sizeof(unsigned int);
596 ke.flags = 0;
597
598 } else {
599 size = min(size, sizeof(ke));
600
601 if (copy_from_user(&ke, p, size))
602 return -EFAULT;
603
604 if (ke.len > sizeof(ke.scancode))
605 return -EINVAL;
606 }
607
608 return input_set_keycode(dev, &ke);
609}
610
537static long evdev_do_ioctl(struct file *file, unsigned int cmd, 611static long evdev_do_ioctl(struct file *file, unsigned int cmd,
538 void __user *p, int compat_mode) 612 void __user *p, int compat_mode)
539{ 613{
@@ -580,25 +654,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
580 654
581 return 0; 655 return 0;
582 656
583 case EVIOCGKEYCODE:
584 if (get_user(t, ip))
585 return -EFAULT;
586
587 error = input_get_keycode(dev, t, &v);
588 if (error)
589 return error;
590
591 if (put_user(v, ip + 1))
592 return -EFAULT;
593
594 return 0;
595
596 case EVIOCSKEYCODE:
597 if (get_user(t, ip) || get_user(v, ip + 1))
598 return -EFAULT;
599
600 return input_set_keycode(dev, t, v);
601
602 case EVIOCRMFF: 657 case EVIOCRMFF:
603 return input_ff_erase(dev, (int)(unsigned long) p, file); 658 return input_ff_erase(dev, (int)(unsigned long) p, file);
604 659
@@ -620,7 +675,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
620 675
621 /* Now check variable-length commands */ 676 /* Now check variable-length commands */
622#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) 677#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
623
624 switch (EVIOC_MASK_SIZE(cmd)) { 678 switch (EVIOC_MASK_SIZE(cmd)) {
625 679
626 case EVIOCGKEY(0): 680 case EVIOCGKEY(0):
@@ -654,6 +708,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
654 return -EFAULT; 708 return -EFAULT;
655 709
656 return error; 710 return error;
711
712 case EVIOC_MASK_SIZE(EVIOCGKEYCODE):
713 return evdev_handle_get_keycode(dev, p, size);
714
715 case EVIOC_MASK_SIZE(EVIOCSKEYCODE):
716 return evdev_handle_set_keycode(dev, p, size);
657 } 717 }
658 718
659 /* Multi-number variable-length handlers */ 719 /* Multi-number variable-length handlers */