]> err.no Git - linux-2.6/blobdiff - drivers/hid/hid-input-quirks.c
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / drivers / hid / hid-input-quirks.c
index e05e9ad5522ebcea26146c34bd41225340549f3f..4c2052c658f1465f6a8d89494b03a8783a7ba6e3 100644 (file)
@@ -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
  */
 
 /*
 #include <linux/input.h>
 #include <linux/hid.h>
 
-#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,17 +138,18 @@ 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;
 
        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;
        }
@@ -156,7 +157,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 +185,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 +237,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;
@@ -253,6 +254,42 @@ 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;
+}
+
+static int quirk_sunplus_wdesktop(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 0x2003: map_key_clear(KEY_ZOOMIN);         break;
+               case 0x2103: map_key_clear(KEY_ZOOMOUT);        break;
+               default:
+                       return 0;
+       }
+       return 1;
+}
 
 #define VENDOR_ID_BELKIN                       0x1020
 #define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD     0x0006
@@ -263,6 +300,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
@@ -272,7 +312,8 @@ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *in
 #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
@@ -280,10 +321,13 @@ static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *in
 #define VENDOR_ID_PETALYNX                     0x18b1
 #define DEVICE_ID_PETALYNX_MAXTER_REMOTE       0x0037
 
+#define VENDOR_ID_SUNPLUS                      0x04fc
+#define DEVICE_ID_SUNPLUS_WDESKTOP             0x05d8
+
 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 },
 
@@ -291,6 +335,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 },
@@ -298,18 +344,21 @@ 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 },
 
        { VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote },
-       
-       { 0, 0, 0 }
+
+       { VENDOR_ID_SUNPLUS, DEVICE_ID_SUNPLUS_WDESKTOP, quirk_sunplus_wdesktop },
+
+       { 0, 0, NULL }
 };
 
 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;
@@ -322,5 +371,74 @@ int hidinput_mapping_quirks(struct hid_usage *usage,
        }
        return 0;
 }
-EXPORT_SYMBOL_GPL(hidinput_mapping_quirks);
+
+int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
+{
+       struct input_dev *input;
+
+       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 1;
+       }
+
+       if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
+                       (usage->type == EV_REL) &&
+                       (usage->code == REL_WHEEL)) {
+               hid->delayed_value = value;
+               return 1;
+       }
+
+       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 1;
+       }
+
+       if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
+               input_event(input, usage->type, usage->code, -value);
+               return 1;
+       }
+
+       if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
+               input_event(input, usage->type, REL_HWHEEL, value);
+               return 1;
+       }
+
+       if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value))
+               return 1;
+
+       /* Handling MS keyboards special buttons */
+       if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS && 
+                       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);
+               }
+       }
+
+       /* 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 1;
+       }
+       return 0;
+}
+