Merge branch 'uc-logic' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Sat, 23 Oct 2010 20:49:32 +0000 (22:49 +0200)
committerJiri Kosina <jkosina@suse.cz>
Sat, 23 Oct 2010 20:49:32 +0000 (22:49 +0200)
Conflicts:
drivers/hid/hid-ids.h
drivers/hid/hid-lg.c
drivers/hid/usbhid/hid-quirks.c

23 files changed:
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-apple.c
drivers/hid/hid-cherry.c
drivers/hid/hid-core.c
drivers/hid/hid-cypress.c
drivers/hid/hid-elecom.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-kye.c
drivers/hid/hid-lg.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-monterey.c
drivers/hid/hid-ortek.c
drivers/hid/hid-petalynx.c
drivers/hid/hid-prodikeys.c
drivers/hid/hid-samsung.c
drivers/hid/hid-sony.c
drivers/hid/hid-sunplus.c
drivers/hid/hid-uclogic.c [new file with mode: 0644]
drivers/hid/hid-zydacron.c
drivers/hid/usbhid/hid-quirks.c
include/linux/hid.h

index 68a7e862068ea90936c56571cd317a242c504690..2685beebc8dc5e211c9f86f8485931b03f1fff98 100644 (file)
@@ -176,6 +176,12 @@ config HID_KYE
        ---help---
        Support for Kye/Genius Ergo Mouse.
 
+config HID_UCLOGIC
+       tristate "UC-Logic"
+       depends on USB_HID
+       ---help---
+       Support for UC-Logic tablets.
+
 config HID_GYRATION
        tristate "Gyration remote control"
        depends on USB_HID
index ad74abcc73d5cb40f9befc94868cb4c276fe8b4c..62ab1383a99b156edd345feee7f7bca899f2c14e 100644 (file)
@@ -65,6 +65,7 @@ obj-$(CONFIG_HID_GREENASIA)   += hid-gaff.o
 obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
 obj-$(CONFIG_HID_TOPSEED)      += hid-topseed.o
 obj-$(CONFIG_HID_TWINHAN)      += hid-twinhan.o
+obj-$(CONFIG_HID_UCLOGIC)      += hid-uclogic.o
 obj-$(CONFIG_HID_ZEROPLUS)     += hid-zpff.o
 obj-$(CONFIG_HID_ZYDACRON)     += hid-zydacron.o
 obj-$(CONFIG_HID_WACOM)                += hid-wacom.o
index bba05d0a8980e1b43aa8ec6548400b7cf8d174b8..eaeca564a8d3e6643f1222f9be032740a158ee0a 100644 (file)
@@ -246,17 +246,18 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field,
 /*
  * MacBook JIS keyboard has wrong logical maximum
  */
-static void apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
        struct apple_sc *asc = hid_get_drvdata(hdev);
 
-       if ((asc->quirks & APPLE_RDESC_JIS) && rsize >= 60 &&
+       if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 &&
                        rdesc[53] == 0x65 && rdesc[59] == 0x65) {
                dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report "
                                "descriptor\n");
                rdesc[53] = rdesc[59] = 0xe7;
        }
+       return rdesc;
 }
 
 static void apple_setup_input(struct input_dev *input)
index 24663a8717b13bbc4e39657c082bf84b07a506bc..e880086c2311224d7d7ea9fc1ba7d0592bbaf29d 100644 (file)
  * Cherry Cymotion keyboard have an invalid HID report descriptor,
  * that needs fixing before we can parse it.
  */
-static void ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+       if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
                dev_info(&hdev->dev, "fixing up Cherry Cymotion report "
                                "descriptor\n");
                rdesc[11] = rdesc[16] = 0xff;
                rdesc[12] = rdesc[17] = 0x03;
        }
+       return rdesc;
 }
 
 #define ch_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
index cb7dc99d8b290d6526520330500c48c99672dc1f..9eb5c0226ea4fd48fc2017eb5274762f057bb05e 100644 (file)
@@ -651,7 +651,7 @@ int hid_parse_report(struct hid_device *device, __u8 *start,
        };
 
        if (device->driver->report_fixup)
-               device->driver->report_fixup(device, start, size);
+               start = device->driver->report_fixup(device, start, &size);
 
        device->rdesc = kmemdup(start, size, GFP_KERNEL);
        if (device->rdesc == NULL)
@@ -1395,6 +1395,10 @@ static const struct hid_device_id hid_blacklist[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
index 998b6f443d7dc062fff6263030209850d0c43221..4cd0e2345991bd6faf5055286b23a8c093c66ac5 100644 (file)
  * Some USB barcode readers from cypress have usage min and usage max in
  * the wrong order
  */
-static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
        unsigned int i;
 
        if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
-               return;
+               return rdesc;
 
-       for (i = 0; i < rsize - 4; i++)
+       for (i = 0; i < *rsize - 4; i++)
                if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
                        __u8 tmp;
 
@@ -50,6 +50,7 @@ static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        rdesc[i + 3] = rdesc[i + 1];
                        rdesc[i + 1] = tmp;
                }
+       return rdesc;
 }
 
 static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
index 7a40878f46b4920d23619d4ee1fc3ea7c691c235..6e31f305397d1b60bb750efd1f81f17724e175a8 100644 (file)
 
 #include "hid-ids.h"
 
-static void elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
+       if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
                dev_info(&hdev->dev, "Fixing up Elecom BM084 "
                                "report descriptor.\n");
                rdesc[47] = 0x00;
        }
+    return rdesc;
 }
 
 static const struct hid_device_id elecom_devices[] = {
index ae8f74431d92376c4d92aba27545747e83a74c54..afbd82075f96e5a06d3701b32d06b49ded6a3997 100644 (file)
 
 #define USB_VENDOR_ID_UCLOGIC          0x5543
 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209    0x0042
-#define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U   0x0003
 #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5      0x6001
+#define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U   0x0003
+#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U   0x0004
+#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U   0x0005
 
 #define USB_VENDOR_ID_VERNIER          0x08f7
 #define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
index b9877a86eca784e9744f2b5a787b4a102b4a0eff..834ef47b76d6f456184dff1adc9663160bebfa28 100644 (file)
@@ -413,6 +413,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        map_key_clear(BTN_STYLUS);
                        break;
 
+               case 0x46: /* TabletPick */
+                       map_key_clear(BTN_STYLUS2);
+                       break;
+
                default:  goto unknown;
                }
                break;
index f8871712b7b53cbbe4e5dac5c7b651691a38c99d..817247ee006c88119405e0df8c48413f68c2b1eb 100644 (file)
  *   - report size 8 count 1 must be size 1 count 8 for button bitfield
  *   - change the button usage range to 4-7 for the extra buttons
  */
-static void kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize >= 74 &&
+       if (*rsize >= 74 &&
                rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
                rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
                rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
@@ -40,6 +40,7 @@ static void kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc[72] = 0x01;
                rdesc[74] = 0x08;
        }
+       return rdesc;
 }
 
 static const struct hid_device_id kye_devices[] = {
index 9e92c27002ca9a91939e3602863024bfde1edf7b..6d3cd7e5fa91c40e41461e892cc98f28e1c027b1 100644 (file)
  * above the logical maximum described in descriptor. This extends
  * the original value of 0x28c of logical maximum to 0x104d
  */
-static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 
-       if ((quirks & LG_RDESC) && rsize >= 90 && rdesc[83] == 0x26 &&
+       if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
                        rdesc[84] == 0x8c && rdesc[85] == 0x02) {
                dev_info(&hdev->dev, "fixing up Logitech keyboard report "
                                "descriptor\n");
                rdesc[84] = rdesc[89] = 0x4d;
                rdesc[85] = rdesc[90] = 0x10;
        }
-       if ((quirks & LG_RDESC_REL_ABS) && rsize >= 50 &&
+       if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
                        rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
                        rdesc[49] == 0x81 && rdesc[50] == 0x06) {
                dev_info(&hdev->dev, "fixing up rel/abs in Logitech "
                                "report descriptor\n");
                rdesc[33] = rdesc[50] = 0x02;
        }
-
        if ((quirks & LG_FF4) && rsize >= 101 &&
                        rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
                        rdesc[47] == 0x05 && rdesc[48] == 0x09) {
@@ -76,6 +75,7 @@ static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc[47] = 0x95;
                rdesc[48] = 0x0B;
        }
+       return rdesc;
 }
 
 #define lg_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
index 359cc447c6c600d61387e5b8cc6679dc1d4d6b75..dc618c33d0a2631cb9bb0085a06f6504cf6b2513 100644 (file)
  * Microsoft Wireless Desktop Receiver (Model 1028) has
  * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
  */
-static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 
-       if ((quirks & MS_RDESC) && rsize == 571 && rdesc[557] == 0x19 &&
+       if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
                        rdesc[559] == 0x29) {
                dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver "
                                "Model 1028 report descriptor\n");
                rdesc[557] = 0x35;
                rdesc[559] = 0x45;
        }
+       return rdesc;
 }
 
 #define ms_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
index 2cd05aa244b9cfb78739bb1c0f7c5da71f43f0ff..c95c31e2d86923bfc2b5fd4374f4f406a005d860 100644 (file)
 
 #include "hid-ids.h"
 
-static void mr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
+       if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
                dev_info(&hdev->dev, "fixing up button/consumer in HID report "
                                "descriptor\n");
                rdesc[30] = 0x0c;
        }
+       return rdesc;
 }
 
 #define mr_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
index aa9a960f73a413f59ded643eadbd5a1d77d81601..2e79716dca31e424243e6d6ca4d7dba78e4e0702 100644 (file)
 
 #include "hid-ids.h"
 
-static void ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) {
+       if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) {
                dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 "
                                "report descriptor.\n");
                rdesc[55] = 0x92;
        }
+       return rdesc;
 }
 
 static const struct hid_device_id ortek_devices[] = {
index 500fbd0652dc4be5354743dab0961aef43cf6989..308d6ae48a3e4b5baa10a402eae47d00acfd7cfb 100644 (file)
 #include "hid-ids.h"
 
 /* Petalynx Maxter Remote has maximum for consumer page set too low */
-static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
+       if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
                        rdesc[41] == 0x00 && rdesc[59] == 0x26 &&
                        rdesc[60] == 0xf9 && rdesc[61] == 0x00) {
                dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report "
@@ -34,6 +34,7 @@ static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc[60] = 0xfa;
                rdesc[40] = 0xfa;
        }
+       return rdesc;
 }
 
 #define pl_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
index 845f428b8090191aa3ab75952feb010fb1e8ab79..48eab84f53b5467acac72ad1ff57b2f3c79f4c9d 100644 (file)
@@ -740,10 +740,10 @@ int pcmidi_snd_terminate(struct pcmidi_snd *pm)
 /*
  * PC-MIDI report descriptor for report id is wrong.
  */
-static void pk_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize == 178 &&
+       if (*rsize == 178 &&
              rdesc[111] == 0x06 && rdesc[112] == 0x00 &&
              rdesc[113] == 0xff) {
                dev_info(&hdev->dev, "fixing up pc-midi keyboard report "
@@ -751,6 +751,7 @@ static void pk_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 
                rdesc[144] = 0x18; /* report 4: was 0x10 report count */
        }
+       return rdesc;
 }
 
 static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi,
index bda0fd60c98d28014258768d7711c3db25b391e5..35894444e00067640532c17f2cc5468c1f9cef14 100644 (file)
@@ -61,10 +61,10 @@ static inline void samsung_irda_dev_trace(struct hid_device *hdev,
                        "descriptor\n", rsize);
 }
 
-static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 &&
+       if (*rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 &&
                        rdesc[177] == 0x75 && rdesc[178] == 0x30 &&
                        rdesc[179] == 0x95 && rdesc[180] == 0x01 &&
                        rdesc[182] == 0x40) {
@@ -74,24 +74,25 @@ static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc[180] = 0x06;
                rdesc[182] = 0x42;
        } else
-       if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 &&
+       if (*rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 &&
                        rdesc[194] == 0x25 && rdesc[195] == 0x12) {
                samsung_irda_dev_trace(hdev, 203);
                rdesc[193] = 0x1;
                rdesc[195] = 0xf;
        } else
-       if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 &&
+       if (*rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 &&
                        rdesc[126] == 0x25 && rdesc[127] == 0x11) {
                samsung_irda_dev_trace(hdev, 135);
                rdesc[125] = 0x1;
                rdesc[127] = 0xe;
        } else
-       if (rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 &&
+       if (*rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 &&
                        rdesc[162] == 0x25 && rdesc[163] == 0x01) {
                samsung_irda_dev_trace(hdev, 171);
                rdesc[161] = 0x1;
                rdesc[163] = 0x3;
        }
+       return rdesc;
 }
 
 #define samsung_kbd_mouse_map_key_clear(c) \
@@ -130,11 +131,12 @@ static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev,
        return 1;
 }
 
-static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-       unsigned int rsize)
+static __u8 *samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+       unsigned int *rsize)
 {
        if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product)
-               samsung_irda_report_fixup(hdev, rdesc, rsize);
+               rdesc = samsung_irda_report_fixup(hdev, rdesc, rsize);
+       return rdesc;
 }
 
 static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi,
index 0c164b3dce3a33a060795cfc4d9d0fe2ac6eb1cf..677bb3da10e8d4149d5d6583f943f6a767c9d3c1 100644 (file)
@@ -33,17 +33,18 @@ struct sony_sc {
 };
 
 /* Sony Vaio VGX has wrongly mouse pointer declared as constant */
-static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
        struct sony_sc *sc = hid_get_drvdata(hdev);
 
        if ((sc->quirks & VAIO_RDESC_CONSTANT) &&
-                       rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
+                       *rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
                dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report "
                                "descriptor\n");
                rdesc[55] = 0x06;
        }
+       return rdesc;
 }
 
 static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
index 438107d9f1b2a3b5d11be27c2f9e1deca5690108..164ed568f6cf73bf4640b6f4080d99dde37d6d91 100644 (file)
 
 #include "hid-ids.h"
 
-static void sp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-               unsigned int rsize)
+static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
 {
-       if (rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
+       if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
                        rdesc[106] == 0x03) {
                dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop "
                                "report descriptor\n");
                rdesc[105] = rdesc[110] = 0x03;
                rdesc[106] = rdesc[111] = 0x21;
        }
+       return rdesc;
 }
 
 #define sp_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
new file mode 100644 (file)
index 0000000..05fdc85
--- /dev/null
@@ -0,0 +1,623 @@
+/*
+ *  HID driver for UC-Logic devices not fully compliant with HID standard
+ *
+ *  Copyright (c) 2010 Nikolai Kondrashov
+ */
+
+/*
+ * 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, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * The original descriptors of WPXXXXU tablets have three report IDs, of
+ * which only two are used (8 and 9), and the remaining (7) seems to have
+ * the originally intended pen description which was abandoned for some
+ * reason.  From this unused description it is possible to extract the
+ * actual physical extents and resolution. All the models use the same
+ * descriptor with different extents for the unused report ID.
+ *
+ * Here it is:
+ *
+ *  Usage Page (Digitizer),         ; Digitizer (0Dh)
+ *  Usage (Pen),                    ; Pen (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (7),
+ *    Usage (Stylus),               ; Stylus (20h, logical collection)
+ *    Collection (Physical),
+ *      Usage (Tip Switch),         ; Tip switch (42h, momentary control)
+ *      Usage (Barrel Switch),      ; Barrel switch (44h, momentary control)
+ *      Usage (Eraser),             ; Eraser (45h, momentary control)
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Size (1),
+ *      Report Count (3),
+ *      Input (Variable),
+ *      Report Count (3),
+ *      Input (Constant, Variable),
+ *      Usage (In Range),           ; In range (32h, momentary control)
+ *      Report Count (1),
+ *      Input (Variable),
+ *      Report Count (1),
+ *      Input (Constant, Variable),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Report Size (16),
+ *      Report Count (1),
+ *      Push,
+ *      Unit Exponent (13),
+ *      Unit (Inch^3),
+ *      Physical Minimum (0),
+ *      Physical Maximum (Xpm),
+ *      Logical Maximum (Xlm),
+ *      Input (Variable),
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Physical Maximum (Ypm),
+ *      Logical Maximum (Ylm),
+ *      Input (Variable),
+ *      Pop,
+ *      Usage Page (Digitizer),     ; Digitizer (0Dh)
+ *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
+ *      Logical Maximum (1023),
+ *      Input (Variable),
+ *      Report Size (16),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),           ; Generic desktop controls (01h)
+ *  Usage (Mouse),                  ; Mouse (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (8),
+ *    Usage (Pointer),              ; Pointer (01h, physical collection)
+ *    Collection (Physical),
+ *      Usage Page (Button),        ; Button (09h)
+ *      Usage Minimum (01h),
+ *      Usage Maximum (03h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Count (3),
+ *      Report Size (1),
+ *      Input (Variable),
+ *      Report Count (5),
+ *      Input (Constant),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Usage (Wheel),              ; Wheel (38h, dynamic value)
+ *      Usage (00h),
+ *      Logical Minimum (-127),
+ *      Logical Maximum (127),
+ *      Report Size (8),
+ *      Report Count (4),
+ *      Input (Variable, Relative),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),           ; Generic desktop controls (01h)
+ *  Usage (Mouse),                  ; Mouse (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (9),
+ *    Usage (Pointer),              ; Pointer (01h, physical collection)
+ *    Collection (Physical),
+ *      Usage Page (Button),        ; Button (09h)
+ *      Usage Minimum (01h),
+ *      Usage Maximum (03h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Count (3),
+ *      Report Size (1),
+ *      Input (Variable),
+ *      Report Count (5),
+ *      Input (Constant),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Logical Minimum (0),
+ *      Logical Maximum (32767),
+ *      Physical Minimum (0),
+ *      Physical Maximum (32767),
+ *      Report Count (2),
+ *      Report Size (16),
+ *      Input (Variable),
+ *      Usage Page (Digitizer),     ; Digitizer (0Dh)
+ *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
+ *      Logical Maximum (1023),
+ *      Report Count (1),
+ *      Report Size (16),
+ *      Input (Variable),
+ *    End Collection,
+ *  End Collection
+ *
+ * Here are the extents values for the WPXXXXU models:
+ *
+ *              Xpm     Xlm     Ypm     Ylm
+ *  WP4030U     4000    8000    3000    6000
+ *  WP5540U     5500    11000   4000    8000
+ *  WP8060U     8000    16000   6000    12000
+ *
+ * This suggests that all of them have 2000 LPI resolution, as advertised.
+ */
+
+/* Size of the original descriptor of WPXXXXU tablets */
+#define WPXXXXU_RDESC_ORIG_SIZE        212
+
+/*
+ * Fixed WP4030U report descriptor.
+ * Although the hardware might actually support it, the mouse description
+ * has been removed, since there seems to be no devices having one and it
+ * wouldn't make much sense because of the working area size.
+ */
+static __u8 wp4030u_rdesc_fixed[] = {
+       0x05, 0x0D,         /*  Usage Page (Digitizer),             */
+       0x09, 0x02,         /*  Usage (Pen),                        */
+       0xA1, 0x01,         /*  Collection (Application),           */
+       0x85, 0x09,         /*      Report ID (9),                  */
+       0x09, 0x20,         /*      Usage (Stylus),                 */
+       0xA0,               /*      Collection (Physical),          */
+       0x75, 0x01,         /*          Report Size (1),            */
+       0x09, 0x42,         /*          Usage (Tip Switch),         */
+       0x09, 0x44,         /*          Usage (Barrel Switch),      */
+       0x09, 0x46,         /*          Usage (Tablet Pick),        */
+       0x14,               /*          Logical Minimum (0),        */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x05,         /*          Report Count (5),           */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0x75, 0x10,         /*          Report Size (16),           */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x14,               /*          Logical Minimum (0),        */
+       0xA4,               /*          Push,                       */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x55, 0xFD,         /*          Unit Exponent (-3),         */
+       0x65, 0x13,         /*          Unit (Inch),                */
+       0x34,               /*          Physical Minimum (0),       */
+       0x09, 0x30,         /*          Usage (X),                  */
+       0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
+       0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x09, 0x31,         /*          Usage (Y),                  */
+       0x46, 0xB8, 0x0B,   /*          Physical Maximum (3000),    */
+       0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xB4,               /*          Pop,                        */
+       0x09, 0x30,         /*          Usage (Tip Pressure),       */
+       0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xC0,               /*      End Collection,                 */
+       0xC0                /*  End Collection                      */
+};
+
+/* Fixed WP5540U report descriptor */
+static __u8 wp5540u_rdesc_fixed[] = {
+       0x05, 0x0D,         /*  Usage Page (Digitizer),             */
+       0x09, 0x02,         /*  Usage (Pen),                        */
+       0xA1, 0x01,         /*  Collection (Application),           */
+       0x85, 0x09,         /*      Report ID (9),                  */
+       0x09, 0x20,         /*      Usage (Stylus),                 */
+       0xA0,               /*      Collection (Physical),          */
+       0x75, 0x01,         /*          Report Size (1),            */
+       0x09, 0x42,         /*          Usage (Tip Switch),         */
+       0x09, 0x44,         /*          Usage (Barrel Switch),      */
+       0x09, 0x46,         /*          Usage (Tablet Pick),        */
+       0x14,               /*          Logical Minimum (0),        */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x05,         /*          Report Count (5),           */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0x75, 0x10,         /*          Report Size (16),           */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x14,               /*          Logical Minimum (0),        */
+       0xA4,               /*          Push,                       */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x55, 0xFD,         /*          Unit Exponent (-3),         */
+       0x65, 0x13,         /*          Unit (Inch),                */
+       0x34,               /*          Physical Minimum (0),       */
+       0x09, 0x30,         /*          Usage (X),                  */
+       0x46, 0x7C, 0x15,   /*          Physical Maximum (5500),    */
+       0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x09, 0x31,         /*          Usage (Y),                  */
+       0x46, 0xA0, 0x0F,   /*          Physical Maximum (4000),    */
+       0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xB4,               /*          Pop,                        */
+       0x09, 0x30,         /*          Usage (Tip Pressure),       */
+       0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xC0,               /*      End Collection,                 */
+       0xC0,               /*  End Collection,                     */
+       0x05, 0x01,         /*  Usage Page (Desktop),               */
+       0x09, 0x02,         /*  Usage (Mouse),                      */
+       0xA1, 0x01,         /*  Collection (Application),           */
+       0x85, 0x08,         /*      Report ID (8),                  */
+       0x09, 0x01,         /*      Usage (Pointer),                */
+       0xA0,               /*      Collection (Physical),          */
+       0x75, 0x01,         /*          Report Size (1),            */
+       0x05, 0x09,         /*          Usage Page (Button),        */
+       0x19, 0x01,         /*          Usage Minimum (01h),        */
+       0x29, 0x03,         /*          Usage Maximum (03h),        */
+       0x14,               /*          Logical Minimum (0),        */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x05,         /*          Report Count (5),           */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x75, 0x08,         /*          Report Size (8),            */
+       0x09, 0x30,         /*          Usage (X),                  */
+       0x09, 0x31,         /*          Usage (Y),                  */
+       0x15, 0x81,         /*          Logical Minimum (-127),     */
+       0x25, 0x7F,         /*          Logical Maximum (127),      */
+       0x95, 0x02,         /*          Report Count (2),           */
+       0x81, 0x06,         /*          Input (Variable, Relative), */
+       0x09, 0x38,         /*          Usage (Wheel),              */
+       0x15, 0xFF,         /*          Logical Minimum (-1),       */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x81, 0x06,         /*          Input (Variable, Relative), */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0xC0,               /*      End Collection,                 */
+       0xC0                /*  End Collection                      */
+};
+
+/* Fixed WP8060U report descriptor */
+static __u8 wp8060u_rdesc_fixed[] = {
+       0x05, 0x0D,         /*  Usage Page (Digitizer),             */
+       0x09, 0x02,         /*  Usage (Pen),                        */
+       0xA1, 0x01,         /*  Collection (Application),           */
+       0x85, 0x09,         /*      Report ID (9),                  */
+       0x09, 0x20,         /*      Usage (Stylus),                 */
+       0xA0,               /*      Collection (Physical),          */
+       0x75, 0x01,         /*          Report Size (1),            */
+       0x09, 0x42,         /*          Usage (Tip Switch),         */
+       0x09, 0x44,         /*          Usage (Barrel Switch),      */
+       0x09, 0x46,         /*          Usage (Tablet Pick),        */
+       0x14,               /*          Logical Minimum (0),        */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x05,         /*          Report Count (5),           */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0x75, 0x10,         /*          Report Size (16),           */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x14,               /*          Logical Minimum (0),        */
+       0xA4,               /*          Push,                       */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x55, 0xFD,         /*          Unit Exponent (-3),         */
+       0x65, 0x13,         /*          Unit (Inch),                */
+       0x34,               /*          Physical Minimum (0),       */
+       0x09, 0x30,         /*          Usage (X),                  */
+       0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
+       0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x09, 0x31,         /*          Usage (Y),                  */
+       0x46, 0x70, 0x17,   /*          Physical Maximum (6000),    */
+       0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xB4,               /*          Pop,                        */
+       0x09, 0x30,         /*          Usage (Tip Pressure),       */
+       0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xC0,               /*      End Collection,                 */
+       0xC0,               /*  End Collection,                     */
+       0x05, 0x01,         /*  Usage Page (Desktop),               */
+       0x09, 0x02,         /*  Usage (Mouse),                      */
+       0xA1, 0x01,         /*  Collection (Application),           */
+       0x85, 0x08,         /*      Report ID (8),                  */
+       0x09, 0x01,         /*      Usage (Pointer),                */
+       0xA0,               /*      Collection (Physical),          */
+       0x75, 0x01,         /*          Report Size (1),            */
+       0x05, 0x09,         /*          Usage Page (Button),        */
+       0x19, 0x01,         /*          Usage Minimum (01h),        */
+       0x29, 0x03,         /*          Usage Maximum (03h),        */
+       0x14,               /*          Logical Minimum (0),        */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x05,         /*          Report Count (5),           */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x75, 0x08,         /*          Report Size (8),            */
+       0x09, 0x30,         /*          Usage (X),                  */
+       0x09, 0x31,         /*          Usage (Y),                  */
+       0x15, 0x81,         /*          Logical Minimum (-127),     */
+       0x25, 0x7F,         /*          Logical Maximum (127),      */
+       0x95, 0x02,         /*          Report Count (2),           */
+       0x81, 0x06,         /*          Input (Variable, Relative), */
+       0x09, 0x38,         /*          Usage (Wheel),              */
+       0x15, 0xFF,         /*          Logical Minimum (-1),       */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x81, 0x06,         /*          Input (Variable, Relative), */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0xC0,               /*      End Collection,                 */
+       0xC0                /*  End Collection                      */
+};
+
+/*
+ * Original PF1209 report descriptor.
+ *
+ * The descriptor is similar to WPXXXXU descriptors, with an addition of a
+ * feature report (ID 4) of unknown purpose.
+ *
+ * Although the advertised resolution is 4000 LPI the unused report ID
+ * (taken from WPXXXXU, it seems) states 2000 LPI, but it is probably
+ * incorrect and is a result of blind copying without understanding. Anyway
+ * the real logical extents are always scaled to 0..32767, which IMHO spoils
+ * the precision.
+ *
+ *  Usage Page (Digitizer),         ; Digitizer (0Dh)
+ *  Usage (Pen),                    ; Pen (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (7),
+ *    Usage (Stylus),               ; Stylus (20h, logical collection)
+ *    Collection (Physical),
+ *      Usage (Tip Switch),         ; Tip switch (42h, momentary control)
+ *      Usage (Barrel Switch),      ; Barrel switch (44h, momentary control)
+ *      Usage (Eraser),             ; Eraser (45h, momentary control)
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Size (1),
+ *      Report Count (3),
+ *      Input (Variable),
+ *      Report Count (3),
+ *      Input (Constant, Variable),
+ *      Usage (In Range),           ; In range (32h, momentary control)
+ *      Report Count (1),
+ *      Input (Variable),
+ *      Report Count (1),
+ *      Input (Constant, Variable),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Report Size (16),
+ *      Report Count (1),
+ *      Push,
+ *      Unit Exponent (13),
+ *      Unit (Inch^3),
+ *      Physical Minimum (0),
+ *      Physical Maximum (12000),
+ *      Logical Maximum (24000),
+ *      Input (Variable),
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Physical Maximum (9000),
+ *      Logical Maximum (18000),
+ *      Input (Variable),
+ *      Pop,
+ *      Usage Page (Digitizer),     ; Digitizer (0Dh)
+ *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
+ *      Logical Maximum (1023),
+ *      Input (Variable),
+ *      Report Size (16),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),           ; Generic desktop controls (01h)
+ *  Usage (Mouse),                  ; Mouse (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (8),
+ *    Usage (Pointer),              ; Pointer (01h, physical collection)
+ *    Collection (Physical),
+ *      Usage Page (Button),        ; Button (09h)
+ *      Usage Minimum (01h),
+ *      Usage Maximum (03h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Count (3),
+ *      Report Size (1),
+ *      Input (Variable),
+ *      Report Count (5),
+ *      Input (Constant),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Usage (Wheel),              ; Wheel (38h, dynamic value)
+ *      Usage (00h),
+ *      Logical Minimum (-127),
+ *      Logical Maximum (127),
+ *      Report Size (8),
+ *      Report Count (4),
+ *      Input (Variable, Relative),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),           ; Generic desktop controls (01h)
+ *  Usage (Mouse),                  ; Mouse (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (9),
+ *    Usage (Pointer),              ; Pointer (01h, physical collection)
+ *    Collection (Physical),
+ *      Usage Page (Button),        ; Button (09h)
+ *      Usage Minimum (01h),
+ *      Usage Maximum (03h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Count (3),
+ *      Report Size (1),
+ *      Input (Variable),
+ *      Report Count (5),
+ *      Input (Constant),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Logical Minimum (0),
+ *      Logical Maximum (32767),
+ *      Physical Minimum (0),
+ *      Physical Maximum (32767),
+ *      Report Count (2),
+ *      Report Size (16),
+ *      Input (Variable),
+ *      Usage Page (Digitizer),     ; Digitizer (0Dh)
+ *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
+ *      Logical Maximum (1023),
+ *      Report Count (1),
+ *      Report Size (16),
+ *      Input (Variable),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),           ; Generic desktop controls (01h)
+ *  Usage (00h),
+ *  Collection (Application),
+ *    Report ID (4),
+ *    Logical Minimum (0),
+ *    Logical Maximum (255),
+ *    Usage (00h),
+ *    Report Size (8),
+ *    Report Count (3),
+ *    Feature (Variable),
+ *  End Collection
+ */
+
+/* Size of the original descriptor of PF1209 tablet */
+#define PF1209_RDESC_ORIG_SIZE 234
+
+/*
+ * Fixed PF1209 report descriptor
+ *
+ * The descriptor is fixed similarly to WP5540U and WP8060U, plus the
+ * feature report is removed, because its purpose is unknown and it is of no
+ * use to the generic HID driver anyway for now.
+ */
+static __u8 pf1209_rdesc_fixed[] = {
+       0x05, 0x0D,         /*  Usage Page (Digitizer),             */
+       0x09, 0x02,         /*  Usage (Pen),                        */
+       0xA1, 0x01,         /*  Collection (Application),           */
+       0x85, 0x09,         /*      Report ID (9),                  */
+       0x09, 0x20,         /*      Usage (Stylus),                 */
+       0xA0,               /*      Collection (Physical),          */
+       0x75, 0x01,         /*          Report Size (1),            */
+       0x09, 0x42,         /*          Usage (Tip Switch),         */
+       0x09, 0x44,         /*          Usage (Barrel Switch),      */
+       0x09, 0x46,         /*          Usage (Tablet Pick),        */
+       0x14,               /*          Logical Minimum (0),        */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x05,         /*          Report Count (5),           */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0x75, 0x10,         /*          Report Size (16),           */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x14,               /*          Logical Minimum (0),        */
+       0xA4,               /*          Push,                       */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x55, 0xFD,         /*          Unit Exponent (-3),         */
+       0x65, 0x13,         /*          Unit (Inch),                */
+       0x34,               /*          Physical Minimum (0),       */
+       0x09, 0x30,         /*          Usage (X),                  */
+       0x46, 0xE0, 0x2E,   /*          Physical Maximum (12000),   */
+       0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x09, 0x31,         /*          Usage (Y),                  */
+       0x46, 0x28, 0x23,   /*          Physical Maximum (9000),    */
+       0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xB4,               /*          Pop,                        */
+       0x09, 0x30,         /*          Usage (Tip Pressure),       */
+       0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xC0,               /*      End Collection,                 */
+       0xC0,               /*  End Collection,                     */
+       0x05, 0x01,         /*  Usage Page (Desktop),               */
+       0x09, 0x02,         /*  Usage (Mouse),                      */
+       0xA1, 0x01,         /*  Collection (Application),           */
+       0x85, 0x08,         /*      Report ID (8),                  */
+       0x09, 0x01,         /*      Usage (Pointer),                */
+       0xA0,               /*      Collection (Physical),          */
+       0x75, 0x01,         /*          Report Size (1),            */
+       0x05, 0x09,         /*          Usage Page (Button),        */
+       0x19, 0x01,         /*          Usage Minimum (01h),        */
+       0x29, 0x03,         /*          Usage Maximum (03h),        */
+       0x14,               /*          Logical Minimum (0),        */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x05,         /*          Report Count (5),           */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x75, 0x08,         /*          Report Size (8),            */
+       0x09, 0x30,         /*          Usage (X),                  */
+       0x09, 0x31,         /*          Usage (Y),                  */
+       0x15, 0x81,         /*          Logical Minimum (-127),     */
+       0x25, 0x7F,         /*          Logical Maximum (127),      */
+       0x95, 0x02,         /*          Report Count (2),           */
+       0x81, 0x06,         /*          Input (Variable, Relative), */
+       0x09, 0x38,         /*          Usage (Wheel),              */
+       0x15, 0xFF,         /*          Logical Minimum (-1),       */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x81, 0x06,         /*          Input (Variable, Relative), */
+       0x81, 0x01,         /*          Input (Constant),           */
+       0xC0,               /*      End Collection,                 */
+       0xC0                /*  End Collection                      */
+};
+
+static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+                                       unsigned int *rsize)
+{
+       switch (hdev->product) {
+       case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
+               if (*rsize == PF1209_RDESC_ORIG_SIZE) {
+                       rdesc = pf1209_rdesc_fixed;
+                       *rsize = sizeof(pf1209_rdesc_fixed);
+               }
+               break;
+       case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U:
+               if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
+                       rdesc = wp4030u_rdesc_fixed;
+                       *rsize = sizeof(wp4030u_rdesc_fixed);
+               }
+               break;
+       case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U:
+               if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
+                       rdesc = wp5540u_rdesc_fixed;
+                       *rsize = sizeof(wp5540u_rdesc_fixed);
+               }
+               break;
+       case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U:
+               if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) {
+                       rdesc = wp8060u_rdesc_fixed;
+                       *rsize = sizeof(wp8060u_rdesc_fixed);
+               }
+               break;
+       }
+
+       return rdesc;
+}
+
+static const struct hid_device_id uclogic_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
+                               USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
+                               USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
+                               USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
+                               USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, uclogic_devices);
+
+static struct hid_driver uclogic_driver = {
+       .name = "uclogic",
+       .id_table = uclogic_devices,
+       .report_fixup = uclogic_report_fixup,
+};
+
+static int __init uclogic_init(void)
+{
+       return hid_register_driver(&uclogic_driver);
+}
+
+static void __exit uclogic_exit(void)
+{
+       hid_unregister_driver(&uclogic_driver);
+}
+
+module_init(uclogic_init);
+module_exit(uclogic_exit);
+MODULE_LICENSE("GPL");
index 9e8d35a203e4adefc2c9d8370bc5b74efeb7d73a..aac1f92731491083db68e0c212dd1292aed67b74 100644 (file)
@@ -27,10 +27,10 @@ struct zc_device {
 * Zydacron remote control has an invalid HID report descriptor,
 * that needs fixing before we can parse it.
 */
-static void zc_report_fixup(struct hid_device *hdev, __u8 *rdesc,
-       unsigned int rsize)
+static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+       unsigned int *rsize)
 {
-       if (rsize >= 253 &&
+       if (*rsize >= 253 &&
                rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff &&
                rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff &&
                rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) {
@@ -40,6 +40,7 @@ static void zc_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c;
                        rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00;
                }
+       return rdesc;
 }
 
 #define zc_map_key_clear(c) \
index 836a87473c5851e29ae32081aacc63f290ec24af..5457135d8ae3d5710f0acf9a56a1683931d78ce4 100644 (file)
@@ -72,6 +72,8 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
index 4cfe02c3fa4e2c40932493cf73501ce0d5c5f440..bb0f56f5c01ef81c51808e7cd97fe9543567ae1e 100644 (file)
@@ -627,8 +627,8 @@ struct hid_driver {
        int (*event)(struct hid_device *hdev, struct hid_field *field,
                        struct hid_usage *usage, __s32 value);
 
-       void (*report_fixup)(struct hid_device *hdev, __u8 *buf,
-                       unsigned int size);
+       __u8 *(*report_fixup)(struct hid_device *hdev, __u8 *buf,
+                       unsigned int *size);
 
        int (*input_mapping)(struct hid_device *hdev,
                        struct hid_input *hidinput, struct hid_field *field,