diff options
author | Jiri Kosina <jkosina@suse.cz> | 2007-08-09 07:24:11 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2007-10-14 07:40:00 -0400 |
commit | 1fe8736da695c2b14961438c73d5600538bd92d9 (patch) | |
tree | b3c920eacd9a017a63abf74973a6be331ab4271f | |
parent | 4dc21a8005216ee3784df545f028775242c6f499 (diff) |
HID: add support for Microsoft Natural Ergonomic Keyboard 4000
This keyboard emits a few usages that are not handled properly by
hid-input.
The usages from MSVENDOR page are colliding with Chicony Tactical
Pad device, so we have to distinguish in runtime. Ugly ...
Also, the buttons 1-5 have to be handled in a non-standard way,
as they are emitted by the keyboard in a bitfield-like fashion, but
the field is not presented as bit-field by the keyboard. The keys can't
be pressed simultaneously, so the handling we have is correct.
This patch also extends hid_keyboard[] with KPLeftParenthesis and
KPRightParenthesis as defined by Keyboard page in HUT 1.12. The
corresponding usages are also emitted by this keyboard.
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-debug.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 52 |
2 files changed, 50 insertions, 4 deletions
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index a13757b78980..27e4cf003834 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
@@ -697,7 +697,7 @@ static char *keys[KEY_MAX + 1] = { | |||
697 | [KEY_DEL_LINE] = "DeleteLine", | 697 | [KEY_DEL_LINE] = "DeleteLine", |
698 | [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", | 698 | [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", |
699 | [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", | 699 | [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", |
700 | [KEY_DOCUMENTS] = "Documents", | 700 | [KEY_DOCUMENTS] = "Documents", [KEY_SPELLCHECK] = "SpellCheck", |
701 | [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", | 701 | [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", |
702 | [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", | 702 | [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", |
703 | [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", | 703 | [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 8edbd30cf795..00f326012a31 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -53,7 +53,7 @@ static const unsigned char hid_keyboard[256] = { | |||
53 | 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, | 53 | 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, |
54 | 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 54 | 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, |
55 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 55 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, |
56 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 56 | unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk, |
57 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 57 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, |
58 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 58 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, |
59 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, | 59 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, |
@@ -86,6 +86,10 @@ static const struct { | |||
86 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) | 86 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) |
87 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | 87 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) |
88 | 88 | ||
89 | /* hardware needing special handling due to colliding MSVENDOR page usages */ | ||
90 | #define IS_CHICONY_TACTICAL_PAD(x) (x->vendor == 0x04f2 && device->product == 0x0418) | ||
91 | #define IS_MS_NEK4K(x) (x->vendor == 0x045e && x->product == 0x00db) | ||
92 | |||
89 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | 93 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK |
90 | 94 | ||
91 | struct hidinput_key_translation { | 95 | struct hidinput_key_translation { |
@@ -614,6 +618,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
614 | case 0x19e: map_key_clear(KEY_COFFEE); break; | 618 | case 0x19e: map_key_clear(KEY_COFFEE); break; |
615 | case 0x1a6: map_key_clear(KEY_HELP); break; | 619 | case 0x1a6: map_key_clear(KEY_HELP); break; |
616 | case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; | 620 | case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; |
621 | case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; | ||
617 | case 0x1bc: map_key_clear(KEY_MESSENGER); break; | 622 | case 0x1bc: map_key_clear(KEY_MESSENGER); break; |
618 | case 0x1bd: map_key_clear(KEY_INFO); break; | 623 | case 0x1bd: map_key_clear(KEY_INFO); break; |
619 | case 0x201: map_key_clear(KEY_NEW); break; | 624 | case 0x201: map_key_clear(KEY_NEW); break; |
@@ -720,8 +725,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
720 | 725 | ||
721 | case HID_UP_MSVENDOR: | 726 | case HID_UP_MSVENDOR: |
722 | 727 | ||
723 | /* special case - Chicony Chicony KU-0418 tactical pad */ | 728 | /* Unfortunately, there are multiple devices which |
724 | if (device->vendor == 0x04f2 && device->product == 0x0418) { | 729 | * emit usages from MSVENDOR page that require different |
730 | * handling. If this list grows too much in the future, | ||
731 | * more general handling will have to be introduced here | ||
732 | * (i.e. another blacklist). | ||
733 | */ | ||
734 | |||
735 | /* Chicony Chicony KU-0418 tactical pad */ | ||
736 | if (IS_CHICONY_TACTICAL_PAD(device)) { | ||
725 | set_bit(EV_REP, input->evbit); | 737 | set_bit(EV_REP, input->evbit); |
726 | switch(usage->hid & HID_USAGE) { | 738 | switch(usage->hid & HID_USAGE) { |
727 | case 0xff01: map_key_clear(BTN_1); break; | 739 | case 0xff01: map_key_clear(BTN_1); break; |
@@ -737,6 +749,20 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
737 | case 0xff0b: map_key_clear(BTN_B); break; | 749 | case 0xff0b: map_key_clear(BTN_B); break; |
738 | default: goto ignore; | 750 | default: goto ignore; |
739 | } | 751 | } |
752 | |||
753 | /* Microsoft Natural Ergonomic Keyboard 4000 */ | ||
754 | } else if (IS_MS_NEK4K(device)) { | ||
755 | switch(usage->hid & HID_USAGE) { | ||
756 | case 0xff05: | ||
757 | set_bit(EV_REP, input->evbit); | ||
758 | map_key_clear(BTN_0); | ||
759 | set_bit(BTN_1, input->keybit); | ||
760 | set_bit(BTN_2, input->keybit); | ||
761 | set_bit(BTN_3, input->keybit); | ||
762 | set_bit(BTN_4, input->keybit); | ||
763 | set_bit(BTN_5, input->keybit); | ||
764 | default: goto ignore; | ||
765 | } | ||
740 | } else { | 766 | } else { |
741 | goto ignore; | 767 | goto ignore; |
742 | } | 768 | } |
@@ -991,6 +1017,26 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
991 | return; | 1017 | return; |
992 | } | 1018 | } |
993 | 1019 | ||
1020 | /* Handling MS NEK4K special buttons */ | ||
1021 | if (IS_MS_NEK4K(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) { | ||
1022 | int key = 0; | ||
1023 | static int last_key = 0; | ||
1024 | switch (value) { | ||
1025 | case 0x01: key = BTN_1; break; | ||
1026 | case 0x02: key = BTN_2; break; | ||
1027 | case 0x04: key = BTN_3; break; | ||
1028 | case 0x08: key = BTN_4; break; | ||
1029 | case 0x10: key = BTN_5; break; | ||
1030 | default: break; | ||
1031 | } | ||
1032 | if (key) { | ||
1033 | input_event(input, usage->type, key, 1); | ||
1034 | last_key = key; | ||
1035 | } else { | ||
1036 | input_event(input, usage->type, last_key, 0); | ||
1037 | } | ||
1038 | } | ||
1039 | |||
994 | input_event(input, usage->type, usage->code, value); | 1040 | input_event(input, usage->type, usage->code, value); |
995 | 1041 | ||
996 | if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) | 1042 | if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) |