diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-09-10 00:54:22 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-09-10 01:00:50 -0400 |
commit | 8613e4c2872a87cc309a42de2c7091744dc54d0e (patch) | |
tree | 75b6513268aca8b614f3b2a55421c7a07b4a9899 /drivers/input | |
parent | a4e6aad64735702256e4feaa4724eb776ca4e637 (diff) |
Input: add support for large scancodes
Several devices use a high number of bits for scancodes. One important
group is the Remote Controllers. Some new protocols like RC-6 define a
scancode space of 64 bits.
The current EVIO[CS]GKEYCODE ioctls allow replace the scancode/keycode
translation tables, but it is limited to up to 32 bits for scancode.
Also, if userspace wants to clean the existing table, replacing it by
a new one, it needs to run a loop calling the ioctls over the entire
sparse scancode space.
To solve those problems, this patch extends the ioctls to allow drivers
handle scancodes up to 32 bytes long (the length could be extended in
the future should such need arise) and allow userspace to query and set
scancode to keycode mappings not only by scancode but also by index.
Compatibility code were also added to handle the old format of
EVIO[CS]GKEYCODE ioctls.
Folded fixes by:
- Dan Carpenter: locking fixes for the original implementation
- Jarod Wilson: fix crash when setting keycode and wiring up get/set
handlers in original implementation.
- Dmitry Torokhov: rework to consolidate old and new scancode handling,
provide options to act either by index or scancode.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/evdev.c | 100 | ||||
-rw-r--r-- | drivers/input/input.c | 192 |
2 files changed, 224 insertions, 68 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 | ||
537 | static 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 | |||
578 | static 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 | |||
537 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, | 611 | static 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 */ |
diff --git a/drivers/input/input.c b/drivers/input/input.c index acb3c8095c65..832771e73663 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -634,78 +634,141 @@ static void input_disconnect_device(struct input_dev *dev) | |||
634 | spin_unlock_irq(&dev->event_lock); | 634 | spin_unlock_irq(&dev->event_lock); |
635 | } | 635 | } |
636 | 636 | ||
637 | static int input_fetch_keycode(struct input_dev *dev, int scancode) | 637 | /** |
638 | * input_scancode_to_scalar() - converts scancode in &struct input_keymap_entry | ||
639 | * @ke: keymap entry containing scancode to be converted. | ||
640 | * @scancode: pointer to the location where converted scancode should | ||
641 | * be stored. | ||
642 | * | ||
643 | * This function is used to convert scancode stored in &struct keymap_entry | ||
644 | * into scalar form understood by legacy keymap handling methods. These | ||
645 | * methods expect scancodes to be represented as 'unsigned int'. | ||
646 | */ | ||
647 | int input_scancode_to_scalar(const struct input_keymap_entry *ke, | ||
648 | unsigned int *scancode) | ||
649 | { | ||
650 | switch (ke->len) { | ||
651 | case 1: | ||
652 | *scancode = *((u8 *)ke->scancode); | ||
653 | break; | ||
654 | |||
655 | case 2: | ||
656 | *scancode = *((u16 *)ke->scancode); | ||
657 | break; | ||
658 | |||
659 | case 4: | ||
660 | *scancode = *((u32 *)ke->scancode); | ||
661 | break; | ||
662 | |||
663 | default: | ||
664 | return -EINVAL; | ||
665 | } | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | EXPORT_SYMBOL(input_scancode_to_scalar); | ||
670 | |||
671 | /* | ||
672 | * Those routines handle the default case where no [gs]etkeycode() is | ||
673 | * defined. In this case, an array indexed by the scancode is used. | ||
674 | */ | ||
675 | |||
676 | static unsigned int input_fetch_keycode(struct input_dev *dev, | ||
677 | unsigned int index) | ||
638 | { | 678 | { |
639 | switch (dev->keycodesize) { | 679 | switch (dev->keycodesize) { |
640 | case 1: | 680 | case 1: |
641 | return ((u8 *)dev->keycode)[scancode]; | 681 | return ((u8 *)dev->keycode)[index]; |
642 | 682 | ||
643 | case 2: | 683 | case 2: |
644 | return ((u16 *)dev->keycode)[scancode]; | 684 | return ((u16 *)dev->keycode)[index]; |
645 | 685 | ||
646 | default: | 686 | default: |
647 | return ((u32 *)dev->keycode)[scancode]; | 687 | return ((u32 *)dev->keycode)[index]; |
648 | } | 688 | } |
649 | } | 689 | } |
650 | 690 | ||
651 | static int input_default_getkeycode(struct input_dev *dev, | 691 | static int input_default_getkeycode(struct input_dev *dev, |
652 | unsigned int scancode, | 692 | struct input_keymap_entry *ke) |
653 | unsigned int *keycode) | ||
654 | { | 693 | { |
694 | unsigned int index; | ||
695 | int error; | ||
696 | |||
655 | if (!dev->keycodesize) | 697 | if (!dev->keycodesize) |
656 | return -EINVAL; | 698 | return -EINVAL; |
657 | 699 | ||
658 | if (scancode >= dev->keycodemax) | 700 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) |
701 | index = ke->index; | ||
702 | else { | ||
703 | error = input_scancode_to_scalar(ke, &index); | ||
704 | if (error) | ||
705 | return error; | ||
706 | } | ||
707 | |||
708 | if (index >= dev->keycodemax) | ||
659 | return -EINVAL; | 709 | return -EINVAL; |
660 | 710 | ||
661 | *keycode = input_fetch_keycode(dev, scancode); | 711 | ke->keycode = input_fetch_keycode(dev, index); |
712 | ke->index = index; | ||
713 | ke->len = sizeof(index); | ||
714 | memcpy(ke->scancode, &index, sizeof(index)); | ||
662 | 715 | ||
663 | return 0; | 716 | return 0; |
664 | } | 717 | } |
665 | 718 | ||
666 | static int input_default_setkeycode(struct input_dev *dev, | 719 | static int input_default_setkeycode(struct input_dev *dev, |
667 | unsigned int scancode, | 720 | const struct input_keymap_entry *ke, |
668 | unsigned int keycode) | 721 | unsigned int *old_keycode) |
669 | { | 722 | { |
670 | int old_keycode; | 723 | unsigned int index; |
724 | int error; | ||
671 | int i; | 725 | int i; |
672 | 726 | ||
673 | if (scancode >= dev->keycodemax) | 727 | if (!dev->keycodesize) |
674 | return -EINVAL; | 728 | return -EINVAL; |
675 | 729 | ||
676 | if (!dev->keycodesize) | 730 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) { |
731 | index = ke->index; | ||
732 | } else { | ||
733 | error = input_scancode_to_scalar(ke, &index); | ||
734 | if (error) | ||
735 | return error; | ||
736 | } | ||
737 | |||
738 | if (index >= dev->keycodemax) | ||
677 | return -EINVAL; | 739 | return -EINVAL; |
678 | 740 | ||
679 | if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8))) | 741 | if (dev->keycodesize < sizeof(dev->keycode) && |
742 | (ke->keycode >> (dev->keycodesize * 8))) | ||
680 | return -EINVAL; | 743 | return -EINVAL; |
681 | 744 | ||
682 | switch (dev->keycodesize) { | 745 | switch (dev->keycodesize) { |
683 | case 1: { | 746 | case 1: { |
684 | u8 *k = (u8 *)dev->keycode; | 747 | u8 *k = (u8 *)dev->keycode; |
685 | old_keycode = k[scancode]; | 748 | *old_keycode = k[index]; |
686 | k[scancode] = keycode; | 749 | k[index] = ke->keycode; |
687 | break; | 750 | break; |
688 | } | 751 | } |
689 | case 2: { | 752 | case 2: { |
690 | u16 *k = (u16 *)dev->keycode; | 753 | u16 *k = (u16 *)dev->keycode; |
691 | old_keycode = k[scancode]; | 754 | *old_keycode = k[index]; |
692 | k[scancode] = keycode; | 755 | k[index] = ke->keycode; |
693 | break; | 756 | break; |
694 | } | 757 | } |
695 | default: { | 758 | default: { |
696 | u32 *k = (u32 *)dev->keycode; | 759 | u32 *k = (u32 *)dev->keycode; |
697 | old_keycode = k[scancode]; | 760 | *old_keycode = k[index]; |
698 | k[scancode] = keycode; | 761 | k[index] = ke->keycode; |
699 | break; | 762 | break; |
700 | } | 763 | } |
701 | } | 764 | } |
702 | 765 | ||
703 | __clear_bit(old_keycode, dev->keybit); | 766 | __clear_bit(*old_keycode, dev->keybit); |
704 | __set_bit(keycode, dev->keybit); | 767 | __set_bit(ke->keycode, dev->keybit); |
705 | 768 | ||
706 | for (i = 0; i < dev->keycodemax; i++) { | 769 | for (i = 0; i < dev->keycodemax; i++) { |
707 | if (input_fetch_keycode(dev, i) == old_keycode) { | 770 | if (input_fetch_keycode(dev, i) == *old_keycode) { |
708 | __set_bit(old_keycode, dev->keybit); | 771 | __set_bit(*old_keycode, dev->keybit); |
709 | break; /* Setting the bit twice is useless, so break */ | 772 | break; /* Setting the bit twice is useless, so break */ |
710 | } | 773 | } |
711 | } | 774 | } |
@@ -716,53 +779,86 @@ static int input_default_setkeycode(struct input_dev *dev, | |||
716 | /** | 779 | /** |
717 | * input_get_keycode - retrieve keycode currently mapped to a given scancode | 780 | * input_get_keycode - retrieve keycode currently mapped to a given scancode |
718 | * @dev: input device which keymap is being queried | 781 | * @dev: input device which keymap is being queried |
719 | * @scancode: scancode (or its equivalent for device in question) for which | 782 | * @ke: keymap entry |
720 | * keycode is needed | ||
721 | * @keycode: result | ||
722 | * | 783 | * |
723 | * This function should be called by anyone interested in retrieving current | 784 | * This function should be called by anyone interested in retrieving current |
724 | * keymap. Presently keyboard and evdev handlers use it. | 785 | * keymap. Presently evdev handlers use it. |
725 | */ | 786 | */ |
726 | int input_get_keycode(struct input_dev *dev, | 787 | int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke) |
727 | unsigned int scancode, unsigned int *keycode) | ||
728 | { | 788 | { |
729 | unsigned long flags; | 789 | unsigned long flags; |
730 | int retval; | 790 | int retval; |
731 | 791 | ||
732 | spin_lock_irqsave(&dev->event_lock, flags); | 792 | spin_lock_irqsave(&dev->event_lock, flags); |
733 | retval = dev->getkeycode(dev, scancode, keycode); | ||
734 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
735 | 793 | ||
794 | if (dev->getkeycode) { | ||
795 | /* | ||
796 | * Support for legacy drivers, that don't implement the new | ||
797 | * ioctls | ||
798 | */ | ||
799 | u32 scancode = ke->index; | ||
800 | |||
801 | memcpy(ke->scancode, &scancode, sizeof(scancode)); | ||
802 | ke->len = sizeof(scancode); | ||
803 | retval = dev->getkeycode(dev, scancode, &ke->keycode); | ||
804 | } else { | ||
805 | retval = dev->getkeycode_new(dev, ke); | ||
806 | } | ||
807 | |||
808 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
736 | return retval; | 809 | return retval; |
737 | } | 810 | } |
738 | EXPORT_SYMBOL(input_get_keycode); | 811 | EXPORT_SYMBOL(input_get_keycode); |
739 | 812 | ||
740 | /** | 813 | /** |
741 | * input_get_keycode - assign new keycode to a given scancode | 814 | * input_set_keycode - attribute a keycode to a given scancode |
742 | * @dev: input device which keymap is being updated | 815 | * @dev: input device which keymap is being updated |
743 | * @scancode: scancode (or its equivalent for device in question) | 816 | * @ke: new keymap entry |
744 | * @keycode: new keycode to be assigned to the scancode | ||
745 | * | 817 | * |
746 | * This function should be called by anyone needing to update current | 818 | * This function should be called by anyone needing to update current |
747 | * keymap. Presently keyboard and evdev handlers use it. | 819 | * keymap. Presently keyboard and evdev handlers use it. |
748 | */ | 820 | */ |
749 | int input_set_keycode(struct input_dev *dev, | 821 | int input_set_keycode(struct input_dev *dev, |
750 | unsigned int scancode, unsigned int keycode) | 822 | const struct input_keymap_entry *ke) |
751 | { | 823 | { |
752 | unsigned long flags; | 824 | unsigned long flags; |
753 | unsigned int old_keycode; | 825 | unsigned int old_keycode; |
754 | int retval; | 826 | int retval; |
755 | 827 | ||
756 | if (keycode > KEY_MAX) | 828 | if (ke->keycode > KEY_MAX) |
757 | return -EINVAL; | 829 | return -EINVAL; |
758 | 830 | ||
759 | spin_lock_irqsave(&dev->event_lock, flags); | 831 | spin_lock_irqsave(&dev->event_lock, flags); |
760 | 832 | ||
761 | retval = dev->getkeycode(dev, scancode, &old_keycode); | 833 | if (dev->setkeycode) { |
762 | if (retval) | 834 | /* |
763 | goto out; | 835 | * Support for legacy drivers, that don't implement the new |
836 | * ioctls | ||
837 | */ | ||
838 | unsigned int scancode; | ||
839 | |||
840 | retval = input_scancode_to_scalar(ke, &scancode); | ||
841 | if (retval) | ||
842 | goto out; | ||
843 | |||
844 | /* | ||
845 | * We need to know the old scancode, in order to generate a | ||
846 | * keyup effect, if the set operation happens successfully | ||
847 | */ | ||
848 | if (!dev->getkeycode) { | ||
849 | retval = -EINVAL; | ||
850 | goto out; | ||
851 | } | ||
852 | |||
853 | retval = dev->getkeycode(dev, scancode, &old_keycode); | ||
854 | if (retval) | ||
855 | goto out; | ||
856 | |||
857 | retval = dev->setkeycode(dev, scancode, ke->keycode); | ||
858 | } else { | ||
859 | retval = dev->setkeycode_new(dev, ke, &old_keycode); | ||
860 | } | ||
764 | 861 | ||
765 | retval = dev->setkeycode(dev, scancode, keycode); | ||
766 | if (retval) | 862 | if (retval) |
767 | goto out; | 863 | goto out; |
768 | 864 | ||
@@ -1759,11 +1855,11 @@ int input_register_device(struct input_dev *dev) | |||
1759 | dev->rep[REP_PERIOD] = 33; | 1855 | dev->rep[REP_PERIOD] = 33; |
1760 | } | 1856 | } |
1761 | 1857 | ||
1762 | if (!dev->getkeycode) | 1858 | if (!dev->getkeycode && !dev->getkeycode_new) |
1763 | dev->getkeycode = input_default_getkeycode; | 1859 | dev->getkeycode_new = input_default_getkeycode; |
1764 | 1860 | ||
1765 | if (!dev->setkeycode) | 1861 | if (!dev->setkeycode && !dev->setkeycode_new) |
1766 | dev->setkeycode = input_default_setkeycode; | 1862 | dev->setkeycode_new = input_default_setkeycode; |
1767 | 1863 | ||
1768 | dev_set_name(&dev->dev, "input%ld", | 1864 | dev_set_name(&dev->dev, "input%ld", |
1769 | (unsigned long) atomic_inc_return(&input_no) - 1); | 1865 | (unsigned long) atomic_inc_return(&input_no) - 1); |