From 10bd065facb2594bd508597ef464d401b212f379 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 22 Nov 2007 15:18:18 +0100 Subject: HID: refactor mapping to input subsystem for quirky devices Currently, the handling of mapping between hid and input for devices that don't conform to HUT 1.12 specification is very messy -- no per-device handling, no blacklists, conditions on idVendor and idProduct placed all over the code. This patch moves all the device-specific input mapping to a separate file, and introduces a blacklist-style handling for non-standard device-specific mappings. Signed-off-by: Jiri Kosina --- drivers/hid/hid-input-quirks.c | 326 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 drivers/hid/hid-input-quirks.c (limited to 'drivers/hid/hid-input-quirks.c') diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c new file mode 100644 index 000000000000..e05e9ad5522e --- /dev/null +++ b/drivers/hid/hid-input-quirks.c @@ -0,0 +1,326 @@ +/* + * HID-input usage mapping quirks + * + * This is used to handle HID-input mappings for devices violating + * HUT 1.12 specification. + * + * Copyright (c) 2007 Jiri Kosina + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License + */ + +#include +#include + +#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; *max = ABS_MAX; } while (0) +#define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; *max = REL_MAX; } while (0) +#define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; *max = KEY_MAX; } while (0) +#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; *max = LED_MAX; } 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) + +static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) + return 0; + + switch (usage->hid & HID_USAGE) { + case 0x03a: map_key_clear(KEY_SOUND); break; + case 0x03b: map_key_clear(KEY_CAMERA); break; + case 0x03c: map_key_clear(KEY_DOCUMENTS); break; + default: + return 0; + } + return 1; +} + +static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) + return 0; + + switch (usage->hid & HID_USAGE) { + case 0x301: map_key_clear(KEY_PROG1); break; + case 0x302: map_key_clear(KEY_PROG2); break; + case 0x303: map_key_clear(KEY_PROG3); break; + default: + return 0; + } + return 1; +} + +static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) + return 0; + + set_bit(EV_REP, input->evbit); + switch(usage->hid & HID_USAGE) { + /* Reported on Logitech Ultra X Media Remote */ + case 0x004: map_key_clear(KEY_AGAIN); break; + case 0x00d: map_key_clear(KEY_HOME); break; + case 0x024: map_key_clear(KEY_SHUFFLE); break; + case 0x025: map_key_clear(KEY_TV); break; + case 0x026: map_key_clear(KEY_MENU); break; + case 0x031: map_key_clear(KEY_AUDIO); break; + case 0x032: map_key_clear(KEY_TEXT); break; + case 0x033: map_key_clear(KEY_LAST); break; + case 0x047: map_key_clear(KEY_MP3); break; + case 0x048: map_key_clear(KEY_DVD); break; + case 0x049: map_key_clear(KEY_MEDIA); break; + case 0x04a: map_key_clear(KEY_VIDEO); break; + case 0x04b: map_key_clear(KEY_ANGLE); break; + case 0x04c: map_key_clear(KEY_LANGUAGE); break; + case 0x04d: map_key_clear(KEY_SUBTITLE); break; + case 0x051: map_key_clear(KEY_RED); break; + case 0x052: map_key_clear(KEY_CLOSE); break; + + default: + return 0; + } + return 1; +} + +static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) + return 0; + + set_bit(EV_REP, input->evbit); + switch (usage->hid & HID_USAGE) { + case 0xff01: map_key_clear(BTN_1); break; + case 0xff02: map_key_clear(BTN_2); break; + case 0xff03: map_key_clear(BTN_3); break; + case 0xff04: map_key_clear(BTN_4); break; + case 0xff05: map_key_clear(BTN_5); break; + case 0xff06: map_key_clear(BTN_6); break; + case 0xff07: map_key_clear(BTN_7); break; + case 0xff08: map_key_clear(BTN_8); break; + case 0xff09: map_key_clear(BTN_9); break; + case 0xff0a: map_key_clear(BTN_A); break; + case 0xff0b: map_key_clear(BTN_B); break; + default: + return 0; + } + return 1; +} + +static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) + return 0; + + switch(usage->hid & HID_USAGE) { + case 0xfd06: map_key_clear(KEY_CHAT); break; + case 0xfd07: map_key_clear(KEY_PHONE); break; + case 0xff05: + set_bit(EV_REP, input->evbit); + map_key_clear(KEY_F13); + set_bit(KEY_F14, input->keybit); + set_bit(KEY_F15, input->keybit); + set_bit(KEY_F16, input->keybit); + set_bit(KEY_F17, input->keybit); + set_bit(KEY_F18, input->keybit); + default: + return 0; + } + return 1; +} + +static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) + return 0; + + set_bit(EV_REP, input->evbit); + switch(usage->hid & HID_USAGE) { + case 0xfd08: map_key_clear(KEY_RIGHT); break; + case 0xfd09: map_key_clear(KEY_LEFT); break; + case 0xfd0b: map_key_clear(KEY_PAUSE); break; + case 0xfd0f: map_key_clear(KEY_F5); break; + default: + return 0; + } + return 1; +} + +static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) && + ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)) + return 0; + + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR) + switch(usage->hid & HID_USAGE) { + case 0x05a: map_key_clear(KEY_TEXT); break; + case 0x05b: map_key_clear(KEY_RED); break; + case 0x05c: map_key_clear(KEY_GREEN); break; + case 0x05d: map_key_clear(KEY_YELLOW); break; + case 0x05e: map_key_clear(KEY_BLUE); break; + default: + return 0; + } + + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) + switch(usage->hid & HID_USAGE) { + case 0x0f6: map_key_clear(KEY_NEXT); break; + case 0x0fa: map_key_clear(KEY_BACK); break; + default: + return 0; + } + return 1; +} + +static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) + return 0; + + switch (usage->hid & HID_USAGE) { + case 0x1001: map_key_clear(KEY_MESSENGER); break; + case 0x1003: map_key_clear(KEY_SOUND); break; + case 0x1004: map_key_clear(KEY_VIDEO); break; + case 0x1005: map_key_clear(KEY_AUDIO); break; + case 0x100a: map_key_clear(KEY_DOCUMENTS); break; + case 0x1011: map_key_clear(KEY_PREVIOUSSONG); break; + case 0x1012: map_key_clear(KEY_NEXTSONG); break; + case 0x1013: map_key_clear(KEY_CAMERA); break; + case 0x1014: map_key_clear(KEY_MESSENGER); break; + case 0x1015: map_key_clear(KEY_RECORD); break; + case 0x1016: map_key_clear(KEY_PLAYER); break; + case 0x1017: map_key_clear(KEY_EJECTCD); break; + case 0x1018: map_key_clear(KEY_MEDIA); break; + case 0x1019: map_key_clear(KEY_PROG1); break; + case 0x101a: map_key_clear(KEY_PROG2); break; + case 0x101b: map_key_clear(KEY_PROG3); break; + case 0x101f: map_key_clear(KEY_ZOOMIN); break; + case 0x1020: map_key_clear(KEY_ZOOMOUT); break; + case 0x1021: map_key_clear(KEY_ZOOMRESET); break; + case 0x1023: map_key_clear(KEY_CLOSE); break; + case 0x1027: map_key_clear(KEY_MENU); break; + /* this one is marked as 'Rotate' */ + case 0x1028: map_key_clear(KEY_ANGLE); break; + case 0x1029: map_key_clear(KEY_SHUFFLE); break; + case 0x102a: map_key_clear(KEY_BACK); break; + case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break; + case 0x1041: map_key_clear(KEY_BATTERY); break; + case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break; + case 0x1043: map_key_clear(KEY_SPREADSHEET); break; + case 0x1044: map_key_clear(KEY_PRESENTATION); break; + case 0x1045: map_key_clear(KEY_UNDO); break; + case 0x1046: map_key_clear(KEY_REDO); break; + case 0x1047: map_key_clear(KEY_PRINT); break; + case 0x1048: map_key_clear(KEY_SAVE); break; + case 0x1049: map_key_clear(KEY_PROG1); break; + case 0x104a: map_key_clear(KEY_PROG2); break; + case 0x104b: map_key_clear(KEY_PROG3); break; + case 0x104c: map_key_clear(KEY_PROG4); break; + + default: + return 0; + } + return 1; +} + +static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) + return 0; + + switch (usage->hid & HID_USAGE) { + case 0x156: map_key_clear(KEY_WORDPROCESSOR); break; + case 0x157: map_key_clear(KEY_SPREADSHEET); break; + case 0x158: map_key_clear(KEY_PRESENTATION); break; + case 0x15c: map_key_clear(KEY_STOP); break; + + default: + return 0; + } + return 1; +} + + +#define VENDOR_ID_BELKIN 0x1020 +#define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD 0x0006 + +#define VENDOR_ID_CHERRY 0x046a +#define DEVICE_ID_CHERRY_CYMOTION 0x0023 + +#define VENDOR_ID_CHICONY 0x04f2 +#define DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 + +#define VENDOR_ID_LOGITECH 0x046d +#define DEVICE_ID_LOGITECH_RECEIVER 0xc101 +#define DEVICE_ID_S510_RECEIVER 0xc50c +#define DEVICE_ID_S510_RECEIVER_2 0xc517 +#define DEVICE_ID_MX3000_RECEIVER 0xc513 + +#define VENDOR_ID_MICROSOFT 0x045e +#define DEVICE_ID_MS4K 0x00db +#define DEVICE_ID_MS6K 0x00f9 +#define DEVICE_ID_MS_PRESENTER_8K 0x0713 + +#define VENDOR_ID_MONTEREY 0x0566 +#define DEVICE_ID_GENIUS_KB29E 0x3004 + +#define VENDOR_ID_PETALYNX 0x18b1 +#define DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 + +static const struct hid_input_blacklist { + __u16 idVendor; + __u16 idProduct; + int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long *, int *); +} hid_input_blacklist[] = { + { VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd }, + + { VENDOR_ID_CHERRY, DEVICE_ID_CHERRY_CYMOTION, quirk_cherry_cymotion }, + + { VENDOR_ID_CHICONY, DEVICE_ID_CHICONY_TACTICAL_PAD, quirk_chicony_tactical_pad }, + + { VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote }, + { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless }, + { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless }, + { VENDOR_ID_LOGITECH, DEVICE_ID_MX3000_RECEIVER, quirk_logitech_wireless }, + + { VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb }, + { VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb }, + { VENDOR_ID_MICROSOFT, DEVICE_ID_MS_PRESENTER_8K, quirk_microsoft_presenter_8k }, + + { VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e }, + + { VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote }, + + { 0, 0, 0 } +}; + +int hidinput_mapping_quirks(struct hid_usage *usage, + struct input_dev *input, + unsigned long *bit, int *max) +{ + struct hid_device *device = input_get_drvdata(input); + int i = 0; + + while (hid_input_blacklist[i].quirk) { + if (hid_input_blacklist[i].idVendor == device->vendor && + hid_input_blacklist[i].idProduct == device->product) + return hid_input_blacklist[i].quirk(usage, input, bit, max); + i++; + } + return 0; +} +EXPORT_SYMBOL_GPL(hidinput_mapping_quirks); + -- cgit v1.2.3 From 87bc2aa9933afc032a93490e1642918121e7470b Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 23 Nov 2007 13:16:02 +0100 Subject: HID: separate hid-input event quirks from generic code This patch separates also the hid-input quirks that have to be applied at the time the event occurs, so that the generic code handling HUT-compliant devices is not messed up by them too much. Signed-off-by: Jiri Kosina --- drivers/hid/hid-input-quirks.c | 65 +++++++++++++++++++++++++++++++++++++++++- drivers/hid/hid-input.c | 63 ++++------------------------------------ include/linux/hid.h | 2 ++ 3 files changed, 71 insertions(+), 59 deletions(-) (limited to 'drivers/hid/hid-input-quirks.c') diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index e05e9ad5522e..7f2f80b00d74 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c @@ -322,5 +322,68 @@ int hidinput_mapping_quirks(struct hid_usage *usage, } return 0; } -EXPORT_SYMBOL_GPL(hidinput_mapping_quirks); + +#define IS_MS_KB(x) (x->vendor == 0x045e && (x->product == 0x00db || x->product == 0x00f9)) + +void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) +{ + struct input_dev *input; + unsigned *quirks = &hid->quirks; + + input = field->hidinput->input; + + if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) + || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) { + if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; + else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; + return; + } + + if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) && + (usage->type == EV_REL) && + (usage->code == REL_WHEEL)) { + hid->delayed_value = value; + return; + } + + if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) && + (usage->hid == 0x000100b8)) { + input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value); + return; + } + + if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) { + input_event(input, usage->type, usage->code, -value); + return; + } + + if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { + input_event(input, usage->type, REL_HWHEEL, value); + return; + } + + if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value)) + return; + + /* Handling MS keyboards special buttons */ + if (IS_MS_KB(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) { + int key = 0; + static int last_key = 0; + switch (value) { + case 0x01: key = KEY_F14; break; + case 0x02: key = KEY_F15; break; + case 0x04: key = KEY_F16; break; + case 0x08: key = KEY_F17; break; + case 0x10: key = KEY_F18; break; + default: break; + } + if (key) { + input_event(input, usage->type, key, 1); + last_key = key; + } else { + input_event(input, usage->type, last_key, 0); + } + } +} + diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 3d448037c82f..aeb018e31bfc 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -86,11 +86,6 @@ static const struct { #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) -/* 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_KB(x) (x->vendor == 0x045e && (x->product == 0x00db || x->product == 0x00f9)) -#define IS_MS_PRESENTER_8000(x) (x->vendor == 0x045e && x->product == 0x0713) - #ifdef CONFIG_USB_HIDINPUT_POWERBOOK struct hidinput_key_translation { @@ -177,7 +172,7 @@ static struct hidinput_key_translation *find_translation(struct hidinput_key_tra return NULL; } -static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, +int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, struct hid_usage *usage, __s32 value) { struct hidinput_key_translation *trans; @@ -269,7 +264,7 @@ static void hidinput_apple_setup(struct input_dev *input) } #else -static inline int hidinput_apple_event(struct hid_device *hid, +inline int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, struct hid_usage *usage, __s32 value) { @@ -386,6 +381,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel goto ignore; } + /* handle input mappings for quirky devices */ ret = hidinput_mapping_quirks(usage, input, bit, &max); if (ret) goto mapped; @@ -857,38 +853,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct if (!usage->type) return; - if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) - || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) { - if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; - else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; - return; - } - - if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) && - (usage->type == EV_REL) && - (usage->code == REL_WHEEL)) { - hid->delayed_value = value; - return; - } - - if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) && - (usage->hid == 0x000100b8)) { - input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value); - return; - } - - if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) { - input_event(input, usage->type, usage->code, -value); - return; - } - - if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { - input_event(input, usage->type, REL_HWHEEL, value); - return; - } - - if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value)) - return; + /* handle input events for quirky devices */ + hidinput_event_quirks(hid, field, usage, value); if (usage->hat_min < usage->hat_max || usage->hat_dir) { int hat_dir = usage->hat_dir; @@ -949,25 +915,6 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; } - /* Handling MS keyboards special buttons */ - if (IS_MS_KB(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) { - int key = 0; - static int last_key = 0; - switch (value) { - case 0x01: key = KEY_F14; break; - case 0x02: key = KEY_F15; break; - case 0x04: key = KEY_F16; break; - case 0x08: key = KEY_F17; break; - case 0x10: key = KEY_F18; break; - default: break; - } - if (key) { - input_event(input, usage->type, key, 1); - last_key = key; - } else { - input_event(input, usage->type, last_key, 0); - } - } /* report the usage code as scancode if the key status has changed */ if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) input_event(input, EV_MSC, MSC_SCAN, usage->hid); diff --git a/include/linux/hid.h b/include/linux/hid.h index cd5d562b1b7c..dca5804836f3 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -525,6 +525,8 @@ int hid_set_field(struct hid_field *, unsigned, __s32); int hid_input_report(struct hid_device *, int type, u8 *, int, int); int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long *, int *); +void hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); +int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32); void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt); void hid_output_report(struct hid_report *report, __u8 *data); void hid_free_device(struct hid_device *device); -- cgit v1.2.3 From 36ccaad640737899b069a9a93a82765f0e675a20 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 26 Nov 2007 13:18:00 +0100 Subject: HID: hid-input quirk for BTC 8193 BTC 8193 keyboard handles its scrollwheel in very non-standard way. It produces two non-standard usages for scrolling up and down, in both cases with postive value equaling to 1. We handle this by temporary mapping, which we then catch in quirk event handler, and remap to negative HWHEEL even in order to introduce correct behavior. Also the button requires special mapping, as it triggers standard-violating usage code. Reported in kernel.org bugzilla #9385 Reported-by: Kir Kolyshkin Signed-off-by: Jiri Kosina --- drivers/hid/hid-input-quirks.c | 34 ++++++++++++++++++++++++++++++++++ drivers/hid/usbhid/hid-quirks.c | 5 +++++ include/linux/hid.h | 1 + 3 files changed, 40 insertions(+) (limited to 'drivers/hid/hid-input-quirks.c') diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index 7f2f80b00d74..e378b4a5eeac 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c @@ -253,6 +253,27 @@ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *in return 1; } +static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input, + unsigned long *bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) + return 0; + + switch (usage->hid & HID_USAGE) { + case 0x230: map_key(BTN_MOUSE); break; + case 0x231: map_rel(REL_WHEEL); break; + /* + * this keyboard has a scrollwheel implemented in + * totally broken way. We map this usage temporarily + * to HWHEEL and handle it in the event quirk handler + */ + case 0x232: map_rel(REL_HWHEEL); break; + + default: + return 0; + } + return 1; +} #define VENDOR_ID_BELKIN 0x1020 #define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD 0x0006 @@ -263,6 +284,9 @@ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *in #define VENDOR_ID_CHICONY 0x04f2 #define DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 +#define VENDOR_ID_EZKEY 0x0518 +#define DEVICE_ID_BTC_8193 0x0002 + #define VENDOR_ID_LOGITECH 0x046d #define DEVICE_ID_LOGITECH_RECEIVER 0xc101 #define DEVICE_ID_S510_RECEIVER 0xc50c @@ -291,6 +315,8 @@ static const struct hid_input_blacklist { { VENDOR_ID_CHICONY, DEVICE_ID_CHICONY_TACTICAL_PAD, quirk_chicony_tactical_pad }, + { VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 }, + { VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote }, { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless }, { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless }, @@ -323,6 +349,7 @@ int hidinput_mapping_quirks(struct hid_usage *usage, return 0; } +#define IS_BTC8193(x) (x->vendor == 0x0518 && x->product == 0x0002) #define IS_MS_KB(x) (x->vendor == 0x045e && (x->product == 0x00db || x->product == 0x00f9)) void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) @@ -384,6 +411,13 @@ void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, stru input_event(input, usage->type, last_key, 0); } } + + /* handle the temporary quirky mapping to HWHEEL */ + if (hid->quirks & HID_QUIRK_HWHEEL_WHEEL_INVERT && + usage->type == EV_REL && usage->code == REL_HWHEEL) { + input_event(input, usage->type, REL_WHEEL, -value); + return; + } } diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index d844757ed8de..aa470f8c0103 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -118,6 +118,9 @@ #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 +#define USB_VENDOR_ID_EZKEY 0x0518 +#define USB_DEVICE_ID_BTC_8193 0x0002 + #define USB_VENDOR_ID_GAMERON 0x0810 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 @@ -400,6 +403,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT }, + { USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT }, + { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, diff --git a/include/linux/hid.h b/include/linux/hid.h index dca5804836f3..33ec33389b37 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -282,6 +282,7 @@ struct hid_item { #define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000 #define HID_QUIRK_IGNORE_HIDINPUT 0x01000000 #define HID_QUIRK_2WHEEL_MOUSE_HACK_B8 0x02000000 +#define HID_QUIRK_HWHEEL_WHEEL_INVERT 0x04000000 /* * Separate quirks for runtime report descriptor fixup -- cgit v1.2.3 From 9a15c99714ca229dd0b894e200fd96daf14f32fb Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 26 Nov 2007 11:32:51 +0100 Subject: HID: remove unused variable in quirk event handler Remove unused variable in quirk event handler. Signed-off-by: Jiri Kosina --- drivers/hid/hid-input-quirks.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/hid/hid-input-quirks.c') diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index e378b4a5eeac..7018be3a5a4c 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c @@ -355,7 +355,6 @@ int hidinput_mapping_quirks(struct hid_usage *usage, void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { struct input_dev *input; - unsigned *quirks = &hid->quirks; input = field->hidinput->input; -- cgit v1.2.3 From 628edcde87592a7ac6e72b555bb03ea265bcfbd2 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 26 Nov 2007 13:26:33 +0100 Subject: HID: proper handling of MS 4k and 6k devices This removes ugly macros IS_* to distinguish devices that need special handling in hid-input, and establish proper quirks for them. Signed-off-by: Jiri Kosina --- drivers/hid/hid-input-quirks.c | 6 ++---- drivers/hid/usbhid/hid-quirks.c | 5 +++++ include/linux/hid.h | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/hid/hid-input-quirks.c') diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index 7018be3a5a4c..fbe8b6de1a63 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c @@ -349,9 +349,6 @@ int hidinput_mapping_quirks(struct hid_usage *usage, return 0; } -#define IS_BTC8193(x) (x->vendor == 0x0518 && x->product == 0x0002) -#define IS_MS_KB(x) (x->vendor == 0x045e && (x->product == 0x00db || x->product == 0x00f9)) - void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { struct input_dev *input; @@ -392,7 +389,8 @@ void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, stru return; /* Handling MS keyboards special buttons */ - if (IS_MS_KB(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) { + if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS && + usage->hid == (HID_UP_MSVENDOR | 0xff05)) { int key = 0; static int last_key = 0; switch (value) { diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index aa470f8c0103..dcb102d87414 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -305,6 +305,8 @@ #define USB_VENDOR_ID_MICROSOFT 0x045e #define USB_DEVICE_ID_SIDEWINDER_GV 0x003b #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d +#define USB_DEVICE_ID_MS_NE4K 0x00db +#define USB_DEVICE_ID_MS_LK6K 0x00f9 #define USB_VENDOR_ID_MONTEREY 0x0566 #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 @@ -534,6 +536,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, diff --git a/include/linux/hid.h b/include/linux/hid.h index 33ec33389b37..24f04cd742de 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -283,6 +283,7 @@ struct hid_item { #define HID_QUIRK_IGNORE_HIDINPUT 0x01000000 #define HID_QUIRK_2WHEEL_MOUSE_HACK_B8 0x02000000 #define HID_QUIRK_HWHEEL_WHEEL_INVERT 0x04000000 +#define HID_QUIRK_MICROSOFT_KEYS 0x08000000 /* * Separate quirks for runtime report descriptor fixup -- cgit v1.2.3 From 70d215c4a7dfbddc138a2dd726d8f80f3e6d2622 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Fri, 7 Dec 2007 16:35:14 +0800 Subject: HID: the `bit' in hidinput_mapping_quirks() is an out parameter Fix a panic, by changing hidinput_mapping_quirks(,, unsigned long *bit,) to hidinput_mapping_quirks(,, unsigned long **bit,) The `bit' in this function is an out parameter. Signed-off-by: Fengguang Wu Signed-off-by: Andrew Morton Signed-off-by: Jiri Kosina --- drivers/hid/hid-input-quirks.c | 36 ++++++++++++++++++------------------ drivers/hid/hid-input.c | 2 +- include/linux/hid.h | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers/hid/hid-input-quirks.c') diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index fbe8b6de1a63..4bcdc9bb658e 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c @@ -16,16 +16,16 @@ #include #include -#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; *max = ABS_MAX; } while (0) -#define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; *max = REL_MAX; } while (0) -#define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; *max = KEY_MAX; } while (0) -#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; *max = LED_MAX; } while (0) +#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0) +#define map_rel(c) do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0) +#define map_key(c) do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0) +#define map_led(c) do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } 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_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) static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) return 0; @@ -41,7 +41,7 @@ static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input, } static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) return 0; @@ -57,7 +57,7 @@ static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *inpu } static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) return 0; @@ -90,7 +90,7 @@ static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_de } static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) return 0; @@ -115,7 +115,7 @@ static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev } static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) return 0; @@ -138,7 +138,7 @@ static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev } static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) return 0; @@ -156,7 +156,7 @@ static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_de } static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) && ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)) @@ -184,7 +184,7 @@ static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *inpu } static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) return 0; @@ -236,7 +236,7 @@ static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *in } static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) return 0; @@ -254,7 +254,7 @@ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *in } static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) return 0; @@ -307,7 +307,7 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input, static const struct hid_input_blacklist { __u16 idVendor; __u16 idProduct; - int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long *, int *); + int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *); } hid_input_blacklist[] = { { VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd }, @@ -335,7 +335,7 @@ static const struct hid_input_blacklist { int hidinput_mapping_quirks(struct hid_usage *usage, struct input_dev *input, - unsigned long *bit, int *max) + unsigned long **bit, int *max) { struct hid_device *device = input_get_drvdata(input); int i = 0; diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index aeb018e31bfc..5325d98b4328 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -382,7 +382,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } /* handle input mappings for quirky devices */ - ret = hidinput_mapping_quirks(usage, input, bit, &max); + ret = hidinput_mapping_quirks(usage, input, &bit, &max); if (ret) goto mapped; diff --git a/include/linux/hid.h b/include/linux/hid.h index 24f04cd742de..6a70b788ee9c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -526,7 +526,7 @@ extern void hidinput_disconnect(struct hid_device *); int hid_set_field(struct hid_field *, unsigned, __s32); int hid_input_report(struct hid_device *, int type, u8 *, int, int); int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); -int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long *, int *); +int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *); void hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32); void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt); -- cgit v1.2.3 From 85c985f46059107c4f4bf5f9e7807dbb646595db Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 10 Jan 2008 17:40:18 +0100 Subject: HID: MS Presenter mapping for PID 0x0701 0x045e/0x0701 also needs the hid-input mapping quirk established by quirk_microsoft_presenter_8k(). Reported-by: Jonas Delrue Signed-off-by: Jiri Kosina --- drivers/hid/hid-input-quirks.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/hid/hid-input-quirks.c') diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index 4bcdc9bb658e..9c4baf32dcfa 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c @@ -4,7 +4,7 @@ * This is used to handle HID-input mappings for devices violating * HUT 1.12 specification. * - * Copyright (c) 2007 Jiri Kosina + * Copyright (c) 2007-2008 Jiri Kosina */ /* @@ -296,7 +296,8 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input, #define VENDOR_ID_MICROSOFT 0x045e #define DEVICE_ID_MS4K 0x00db #define DEVICE_ID_MS6K 0x00f9 -#define DEVICE_ID_MS_PRESENTER_8K 0x0713 +#define DEVICE_IS_MS_PRESENTER_8K_BT 0x0701 +#define DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 #define VENDOR_ID_MONTEREY 0x0566 #define DEVICE_ID_GENIUS_KB29E 0x3004 @@ -324,7 +325,8 @@ static const struct hid_input_blacklist { { VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb }, { VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb }, - { VENDOR_ID_MICROSOFT, DEVICE_ID_MS_PRESENTER_8K, quirk_microsoft_presenter_8k }, + { VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k }, + { VENDOR_ID_MICROSOFT, DEVICE_ID_MS_PRESENTER_8K_USB, quirk_microsoft_presenter_8k }, { VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e }, -- cgit v1.2.3 From d7d32c815b938a8e98e93d881e6ec5da63bd0beb Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 14 Jan 2008 13:08:27 +0100 Subject: HID: Refactor MS Presenter 8K key mapping Following the suggestion of Jonas, this patch maps the special keys of the MS Presenter 8000 to targets that should allow for better re-mapping according to individual use cases (i.e. I avoided hard-wiring to standard keys). This time I also included the last missing key event (switching back from presentation mode). The optimal Xmodmap customization for using the Presenter with OpenOffice now looks like this for me: keycode 175 = Escape keycode 179 = F5 keysym XF86Forward = Right keysym XF86Back = Left Signed-off-by: Jan Kiszka Signed-off-by: Jiri Kosina --- drivers/hid/hid-input-quirks.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/hid/hid-input-quirks.c') diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index 9c4baf32dcfa..a870ba58faa3 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c @@ -145,10 +145,11 @@ static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_de set_bit(EV_REP, input->evbit); switch(usage->hid & HID_USAGE) { - case 0xfd08: map_key_clear(KEY_RIGHT); break; - case 0xfd09: map_key_clear(KEY_LEFT); break; - case 0xfd0b: map_key_clear(KEY_PAUSE); break; - case 0xfd0f: map_key_clear(KEY_F5); break; + case 0xfd08: map_key_clear(KEY_FORWARD); break; + case 0xfd09: map_key_clear(KEY_BACK); break; + case 0xfd0b: map_key_clear(KEY_PLAYPAUSE); break; + case 0xfd0e: map_key_clear(KEY_CLOSE); break; + case 0xfd0f: map_key_clear(KEY_PLAY); break; default: return 0; } -- cgit v1.2.3