/*
- * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
- *
* Copyright (c) 2000-2001 Vojtech Pavlik
* Copyright (c) 2006-2007 Jiri Kosina
*
#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 {
#define APPLE_FLAG_FKEY 0x01
static struct hidinput_key_translation apple_fn_keys[] = {
- { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
- { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
- { KEY_F3, KEY_CYCLEWINDOWS, APPLE_FLAG_FKEY }, /* Exposé */
- { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
- { KEY_F5, KEY_FN_F5 },
- { KEY_F6, KEY_FN_F6 },
- { KEY_F7, KEY_BACK, APPLE_FLAG_FKEY },
- { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
- { KEY_F9, KEY_FORWARD, APPLE_FLAG_FKEY },
- { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
- { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
- { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
+ { KEY_BACKSPACE, KEY_DELETE },
+ { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
+ { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
+ { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */
+ { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
+ { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
+ { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
+ { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
+ { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
+ { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
+ { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
+ { KEY_UP, KEY_PAGEUP },
+ { KEY_DOWN, KEY_PAGEDOWN },
+ { KEY_LEFT, KEY_HOME },
+ { KEY_RIGHT, KEY_END },
{ }
};
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;
}
}
- if (test_bit(usage->code, hid->pb_pressed_numlock) ||
- test_bit(LED_NUML, input->led)) {
+ if (hid->quirks & HID_QUIRK_APPLE_NUMLOCK_EMULATION && (
+ test_bit(usage->code, hid->pb_pressed_numlock) ||
+ test_bit(LED_NUML, input->led))) {
trans = find_translation(powerbook_numlock_keys, usage->code);
if (trans) {
}
#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)
{
{
struct input_dev *input = hidinput->input;
struct hid_device *device = input_get_drvdata(input);
- int max = 0, code;
+ int max = 0, code, ret;
unsigned long *bit = NULL;
field->hidinput = hidinput;
goto ignore;
}
+ /* handle input mappings for quirky devices */
+ ret = hidinput_mapping_quirks(usage, input, &bit, &max);
+ if (ret)
+ goto mapped;
+
switch (usage->hid & HID_USAGE_PAGE) {
case HID_UP_UNDEFINED:
case 0x000: goto ignore;
case 0x034: map_key_clear(KEY_SLEEP); break;
case 0x036: map_key_clear(BTN_MISC); break;
- /*
- * The next three are reported by Belkin wireless
- * keyboard (1020:0006). These values are "reserved"
- * in HUT 1.12.
- */
- case 0x03a: map_key_clear(KEY_SOUND); break;
- case 0x03b: map_key_clear(KEY_CAMERA); break;
- case 0x03c: map_key_clear(KEY_DOCUMENTS); break;
case 0x040: map_key_clear(KEY_MENU); break;
case 0x045: map_key_clear(KEY_RADIO); break;
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
- /* reserved in HUT 1.12. Reported on Petalynx remote */
- case 0x0f6: map_key_clear(KEY_NEXT); break;
- case 0x0fa: map_key_clear(KEY_BACK); break;
-
- /* reserved in HUT 1.12. Reported on Genius KB29E */
- 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;
-
case 0x182: map_key_clear(KEY_BOOKMARKS); break;
case 0x183: map_key_clear(KEY_CONFIG); break;
case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
case 0x28c: map_key_clear(KEY_SEND); break;
- /* Reported on a Cherry Cymotion keyboard */
- case 0x301: map_key_clear(KEY_PROG1); break;
- case 0x302: map_key_clear(KEY_PROG2); break;
- case 0x303: map_key_clear(KEY_PROG3); break;
-
- /* Reported on certain Logitech wireless keyboards */
- 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: goto ignore;
}
break;
case HID_UP_MSVENDOR:
- /* Unfortunately, there are multiple devices which
- * 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);
- 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: goto ignore;
- }
-
- /* Microsoft Natural Ergonomic Keyboard 4000 */
- } else if (IS_MS_KB(device)) {
- 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: goto ignore;
- }
-
- /* Microsoft Wireless Notebook Presenter Mouse 8000 */
- } else if (IS_MS_PRESENTER_8000(device)) {
- set_bit(EV_REP, input->evbit);
- switch(usage->hid & HID_USAGE) {
- /* Useful mappings of bottom-side keys for presentations */
- 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: goto ignore;
- }
- } else
- goto ignore;
- break;
+ goto ignore;
case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
break;
case HID_UP_LOGIVENDOR:
- 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;
-
- /* Reported on Petalynx Maxter remote */
- 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: goto ignore;
- }
- break;
+ goto ignore;
+
case HID_UP_PID:
switch(usage->hid & HID_USAGE) {
break;
}
+mapped:
if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
if (usage->hid == HID_GD_Z)
map_rel(REL_HWHEEL);
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))
+ /* handle input events for quirky devices */
+ if (hidinput_event_quirks(hid, field, usage, value))
return;
if (usage->hat_min < usage->hat_max || usage->hat_dir) {
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);