Commit 1fe8736d authored by Jiri Kosina's avatar Jiri Kosina

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: default avatarJiri Kosina <jkosina@suse.cz>
parent 4dc21a80
...@@ -697,7 +697,7 @@ static char *keys[KEY_MAX + 1] = { ...@@ -697,7 +697,7 @@ static char *keys[KEY_MAX + 1] = {
[KEY_DEL_LINE] = "DeleteLine", [KEY_DEL_LINE] = "DeleteLine",
[KEY_SEND] = "Send", [KEY_REPLY] = "Reply", [KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
[KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
[KEY_DOCUMENTS] = "Documents", [KEY_DOCUMENTS] = "Documents", [KEY_SPELLCHECK] = "SpellCheck",
[KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC",
[KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2",
[KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D",
......
...@@ -53,7 +53,7 @@ static const unsigned char hid_keyboard[256] = { ...@@ -53,7 +53,7 @@ static const unsigned char hid_keyboard[256] = {
115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
...@@ -86,6 +86,10 @@ static const struct { ...@@ -86,6 +86,10 @@ static const struct {
#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
/* hardware needing special handling due to colliding MSVENDOR page usages */
#define IS_CHICONY_TACTICAL_PAD(x) (x->vendor == 0x04f2 && device->product == 0x0418)
#define IS_MS_NEK4K(x) (x->vendor == 0x045e && x->product == 0x00db)
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
struct hidinput_key_translation { struct hidinput_key_translation {
...@@ -614,6 +618,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -614,6 +618,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x19e: map_key_clear(KEY_COFFEE); break; case 0x19e: map_key_clear(KEY_COFFEE); break;
case 0x1a6: map_key_clear(KEY_HELP); break; case 0x1a6: map_key_clear(KEY_HELP); break;
case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
case 0x1ab: map_key_clear(KEY_SPELLCHECK); break;
case 0x1bc: map_key_clear(KEY_MESSENGER); break; case 0x1bc: map_key_clear(KEY_MESSENGER); break;
case 0x1bd: map_key_clear(KEY_INFO); break; case 0x1bd: map_key_clear(KEY_INFO); break;
case 0x201: map_key_clear(KEY_NEW); break; 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,8 +725,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case HID_UP_MSVENDOR: case HID_UP_MSVENDOR:
/* special case - Chicony Chicony KU-0418 tactical pad */ /* Unfortunately, there are multiple devices which
if (device->vendor == 0x04f2 && device->product == 0x0418) { * emit usages from MSVENDOR page that require different
* handling. If this list grows too much in the future,
* more general handling will have to be introduced here
* (i.e. another blacklist).
*/
/* Chicony Chicony KU-0418 tactical pad */
if (IS_CHICONY_TACTICAL_PAD(device)) {
set_bit(EV_REP, input->evbit); set_bit(EV_REP, input->evbit);
switch(usage->hid & HID_USAGE) { switch(usage->hid & HID_USAGE) {
case 0xff01: map_key_clear(BTN_1); break; 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,6 +749,20 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0xff0b: map_key_clear(BTN_B); break; case 0xff0b: map_key_clear(BTN_B); break;
default: goto ignore; default: goto ignore;
} }
/* Microsoft Natural Ergonomic Keyboard 4000 */
} else if (IS_MS_NEK4K(device)) {
switch(usage->hid & HID_USAGE) {
case 0xff05:
set_bit(EV_REP, input->evbit);
map_key_clear(BTN_0);
set_bit(BTN_1, input->keybit);
set_bit(BTN_2, input->keybit);
set_bit(BTN_3, input->keybit);
set_bit(BTN_4, input->keybit);
set_bit(BTN_5, input->keybit);
default: goto ignore;
}
} else { } else {
goto ignore; goto ignore;
} }
...@@ -991,6 +1017,26 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct ...@@ -991,6 +1017,26 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return; return;
} }
/* Handling MS NEK4K special buttons */
if (IS_MS_NEK4K(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
int key = 0;
static int last_key = 0;
switch (value) {
case 0x01: key = BTN_1; break;
case 0x02: key = BTN_2; break;
case 0x04: key = BTN_3; break;
case 0x08: key = BTN_4; break;
case 0x10: key = BTN_5; break;
default: break;
}
if (key) {
input_event(input, usage->type, key, 1);
last_key = key;
} else {
input_event(input, usage->type, last_key, 0);
}
}
input_event(input, usage->type, usage->code, value); input_event(input, usage->type, usage->code, value);
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment