Merge branches 'upstream', 'upstream-fixes' and 'debugfs' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Sun, 13 Sep 2009 18:09:41 +0000 (20:09 +0200)
committerJiri Kosina <jkosina@suse.cz>
Sun, 13 Sep 2009 18:09:41 +0000 (20:09 +0200)
1  2  3 
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/usbhid/hid-core.c
include/linux/hid.h

diff --combined drivers/hid/Kconfig
index aba8facecce83cf4467c8ab0a18b326b6779ffe4,7831a0318d3ca5bad508d0a74d884c5013eabced,05950a783560b19475fd74de0c34e15005ed9075..111afbe8de038e949cab63cdf936c63bc4002381
@@@@ -31,21 -31,21 -31,6 +31,6 @@@@ config HI
   
          If unsure, say Y.
   
-- config HID_DEBUG
--      bool "HID debugging support"
--      default y
--      depends on HID
--      ---help---
--      This option lets the HID layer output diagnostics about its internal
--      state, resolve HID usages, dump HID fields, etc. Individual HID drivers
--      use this debugging facility to output information about individual HID
--      devices, etc.
-- 
--      This feature is useful for those who are either debugging the HID parser
--      or any HID hardware device.
-- 
--      If unsure, say Y.
-- 
   config HIDRAW
        bool "/dev/hidraw raw HID device support"
        depends on HID
@@@@ -116,16 -116,16 -101,9 +101,16 @@@@ config HID_CYPRES
        ---help---
        Support for cypress mouse and barcode readers.
   
  -config DRAGONRISE_FF
  -     tristate "DragonRise Inc. force feedback support"
  +config HID_DRAGONRISE
  +     tristate "DragonRise Inc. support" if EMBEDDED
        depends on USB_HID
  +     default !EMBEDDED
  +     ---help---
  +     Say Y here if you have DragonRise Inc.game controllers.
  +
  +config DRAGONRISE_FF
  +     bool "DragonRise Inc. force feedback support"
  +     depends on HID_DRAGONRISE
        select INPUT_FF_MEMLESS
        ---help---
        Say Y here if you want to enable force feedback support for DragonRise Inc.
@@@@ -152,13 -152,6 -130,6 +137,13 @@@@ config HID_GYRATIO
        ---help---
        Support for Gyration remote control.
   
 ++config HID_TWINHAN
 ++     tristate "Twinhan" if EMBEDDED
 ++     depends on USB_HID
 ++     default !EMBEDDED
 ++     ---help---
 ++     Support for Twinhan IR remote control.
 ++
   config HID_KENSINGTON
        tristate "Kensington" if EMBEDDED
        depends on USB_HID
@@@@ -174,7 -167,7 -145,7 +159,7 @@@@ config HID_LOGITEC
        Support for Logitech devices that are not fully compliant with HID standard.
   
   config LOGITECH_FF
  -     bool "Logitech force feedback"
  +     bool "Logitech force feedback support"
        depends on HID_LOGITECH
        select INPUT_FF_MEMLESS
        help
          - Logitech WingMan Cordless RumblePad 2
          - Logitech WingMan Force 3D
          - Logitech Formula Force EX
 ++       - Logitech WingMan Formula Force GP
          - Logitech MOMO Force wheel
   
          and if you want to enable force feedback for them.
          force feedback.
   
   config LOGIRUMBLEPAD2_FF
  -     bool "Logitech Rumblepad 2 force feedback"
  +     bool "Logitech Rumblepad 2 force feedback support"
        depends on HID_LOGITECH
        select INPUT_FF_MEMLESS
        help
@@@@ -226,19 -218,19 -196,11 +211,19 @@@@ config HID_PANTHERLOR
        ---help---
        Support for PantherLord/GreenAsia based device support.
   
  +config HID_PANTHERLORD
  +     tristate "Pantherlord support" if EMBEDDED
  +     depends on USB_HID
  +     default !EMBEDDED
  +     ---help---
  +       Say Y here if you have a PantherLord/GreenAsia based game controller
  +       or adapter.
  +
   config PANTHERLORD_FF
        bool "Pantherlord force feedback support"
        depends on HID_PANTHERLORD
        select INPUT_FF_MEMLESS
  -     help
  +     ---help---
          Say Y here if you have a PantherLord/GreenAsia based game controller
          or adapter and want to enable force feedback support for it.
   
@@@@ -270,38 -262,38 -232,15 +255,38 @@@@ config HID_SUNPLU
        ---help---
        Support for Sunplus wireless desktop.
   
  -config GREENASIA_FF
  -     tristate "GreenAsia (Product ID 0x12) force feedback support"
  +config HID_GREENASIA
  +     tristate "GreenAsia (Product ID 0x12) support" if EMBEDDED
        depends on USB_HID
  +     default !EMBEDDED
  +     ---help---
  +       Say Y here if you have a GreenAsia (Product ID 0x12) based game
  +       controller or adapter.
  +
  +config GREENASIA_FF
  +     bool "GreenAsia (Product ID 0x12) force feedback support"
  +     depends on HID_GREENASIA
        select INPUT_FF_MEMLESS
        ---help---
        Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
        (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter
        and want to enable force feedback support for it.
   
  +config HID_SMARTJOYPLUS
  +     tristate "SmartJoy PLUS PS2/USB adapter support" if EMBEDDED
  +     depends on USB_HID
  +     default !EMBEDDED
  +     ---help---
  +     Support for SmartJoy PLUS PS2/USB adapter.
  +
  +config SMARTJOYPLUS_FF
  +     bool "SmartJoy PLUS PS2/USB adapter force feedback support"
  +     depends on HID_SMARTJOYPLUS
  +     select INPUT_FF_MEMLESS
  +     ---help---
  +     Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to
  +     enable force feedback support for it.
  +
   config HID_TOPSEED
        tristate "TopSeed Cyberlink remote control support" if EMBEDDED
        depends on USB_HID
        ---help---
        Say Y if you have a TopSeed Cyberlink remote control.
   
  -config THRUSTMASTER_FF
  -     tristate "ThrustMaster devices support"
  +config HID_THRUSTMASTER
  +     tristate "ThrustMaster devices support" if EMBEDDED
        depends on USB_HID
  -     select INPUT_FF_MEMLESS
  -     help
  +     default !EMBEDDED
  +     ---help---
          Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
  -       a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel.
  +       a THRUSTMASTER Ferrari GT Rumble Wheel.
   
  -config ZEROPLUS_FF
  -     tristate "Zeroplus based game controller support"
  -     depends on USB_HID
  +config THRUSTMASTER_FF
  +     bool "ThrustMaster devices force feedback support"
  +     depends on HID_THRUSTMASTER
        select INPUT_FF_MEMLESS
  -     help
  +     ---help---
 -        Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
 -        a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel and
 -        want to enable force feedback support for it.
 ++       Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or 3,
 ++       a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT
 ++       Rumble Force or Force Feedback Wheel.
  +
  +config HID_WACOM
  +     tristate "Wacom Bluetooth devices support" if EMBEDDED
  +     depends on BT_HIDP
  +     default !EMBEDDED
  +     ---help---
  +     Support for Wacom Graphire Bluetooth tablet.
  +
  +config HID_ZEROPLUS
  +     tristate "Zeroplus based game controller support" if EMBEDDED
  +     depends on USB_HID
  +     default !EMBEDDED
  +     ---help---
          Say Y here if you have a Zeroplus based game controller.
   
  +config ZEROPLUS_FF
  +     bool "Zeroplus based game controller force feedback support"
  +     depends on HID_ZEROPLUS
  +     select INPUT_FF_MEMLESS
  +     ---help---
  +       Say Y here if you have a Zeroplus based game controller and want
  +       to have force feedback support for it.
  +
   endmenu
   
   endif # HID_SUPPORT
diff --combined drivers/hid/Makefile
index 9b9271d6527a64d5b0f1d2ad43c4b38f8453948c,db35151673b17f25f453bb7cf2b7018eb580b4dd,cf3687d1ed6390a5406b1d8fe49cd1b1e2076def..0de2dff5542c9c59255f546fa8b2b512d9312c9e
@@@@ -3,9 -3,9 -3,12 +3,12 @@@@
   #
   hid-objs                     := hid-core.o hid-input.o
   
++ ifdef CONFIG_DEBUG_FS
++      hid-objs                += hid-debug.o
++ endif
++ 
   obj-$(CONFIG_HID)            += hid.o
   
-- hid-$(CONFIG_HID_DEBUG)              += hid-debug.o
   hid-$(CONFIG_HIDRAW)         += hidraw.o
   
   hid-logitech-objs            := hid-lg.o
@@@@ -22,7 -22,7 -25,7 +25,7 @@@@ obj-$(CONFIG_HID_BELKIN)      += hid-belkin.
   obj-$(CONFIG_HID_CHERRY)     += hid-cherry.o
   obj-$(CONFIG_HID_CHICONY)    += hid-chicony.o
   obj-$(CONFIG_HID_CYPRESS)    += hid-cypress.o
  -obj-$(CONFIG_DRAGONRISE_FF)  += hid-drff.o
  +obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o
   obj-$(CONFIG_HID_EZKEY)              += hid-ezkey.o
   obj-$(CONFIG_HID_GYRATION)   += hid-gyration.o
   obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
@@@@ -34,15 -34,14 -37,12 +37,15 @@@@ obj-$(CONFIG_HID_NTRIG)           += hid-ntrig.
   obj-$(CONFIG_HID_PANTHERLORD)        += hid-pl.o
   obj-$(CONFIG_HID_PETALYNX)   += hid-petalynx.o
   obj-$(CONFIG_HID_SAMSUNG)    += hid-samsung.o
  +obj-$(CONFIG_HID_SMARTJOYPLUS)       += hid-sjoy.o
   obj-$(CONFIG_HID_SONY)               += hid-sony.o
   obj-$(CONFIG_HID_SUNPLUS)    += hid-sunplus.o
  -obj-$(CONFIG_GREENASIA_FF)   += hid-gaff.o
  -obj-$(CONFIG_THRUSTMASTER_FF)        += hid-tmff.o
  +obj-$(CONFIG_HID_GREENASIA)  += hid-gaff.o
  +obj-$(CONFIG_HID_THRUSTMASTER)       += hid-tmff.o
   obj-$(CONFIG_HID_TOPSEED)    += hid-topseed.o
  -obj-$(CONFIG_ZEROPLUS_FF)    += hid-zpff.o
 ++obj-$(CONFIG_HID_TWINHAN)    += hid-twinhan.o
  +obj-$(CONFIG_HID_ZEROPLUS)   += hid-zpff.o
  +obj-$(CONFIG_HID_WACOM)              += hid-wacom.o
   
   obj-$(CONFIG_USB_HID)                += usbhid/
   obj-$(CONFIG_USB_MOUSE)              += usbhid/
diff --combined drivers/hid/hid-core.c
index 48567d8fe3580bb82fd7f76b08e7cccc6f7d09cd,047844df992a91ac997bf092048e1a12ede9a40e,86c2ff2429d828db35df240329bcdfb7dc1331ee..342b7d36d7bbb91d57f33d04f7c00f61dca2ca0b
   #define DRIVER_DESC "HID core driver"
   #define DRIVER_LICENSE "GPL"
   
-- #ifdef CONFIG_HID_DEBUG
   int hid_debug = 0;
   module_param_named(debug, hid_debug, int, 0600);
-- MODULE_PARM_DESC(debug, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)");
++ MODULE_PARM_DESC(debug, "toggle HID debugging messages");
   EXPORT_SYMBOL_GPL(hid_debug);
-- #endif
   
   /*
    * Register a new report for a device.
@@@@ -861,7 -861,7 -859,7 +859,7 @@@@ static void hid_process_event(struct hi
        struct hid_driver *hdrv = hid->driver;
        int ret;
   
--      hid_dump_input(usage, value);
++      hid_dump_input(hid, usage, value);
   
        if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
                ret = hdrv->event(hid, field, usage, value);
@@@@ -983,11 -983,11 -981,10 +981,10 @@@@ int hid_set_field(struct hid_field *fie
   {
        unsigned size = field->report_size;
   
--      hid_dump_input(field->usage + offset, value);
++      hid_dump_input(field->report->device, field->usage + offset, value);
   
        if (offset >= field->report_count) {
                dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count);
--              hid_dump_field(field, 8);
                return -1;
        }
        if (field->logical_minimum < 0) {
@@@@ -1075,34 -1075,34 -1072,53 +1072,55 @@@@ EXPORT_SYMBOL_GPL(hid_report_raw_event)
    */
   int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
   {
  -     struct hid_report_enum *report_enum = hid->report_enum + type;
  -     struct hid_driver *hdrv = hid->driver;
  +     struct hid_report_enum *report_enum;
  +     struct hid_driver *hdrv;
        struct hid_report *report;
++      char *buf;
        unsigned int i;
        int ret;
   
        if (!hid || !hid->driver)
                return -ENODEV;
  +     report_enum = hid->report_enum + type;
  +     hdrv = hid->driver;
   
        if (!size) {
                dbg_hid("empty report\n");
                return -1;
        }
   
--      dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
++      buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE,
++                      interrupt ? GFP_ATOMIC : GFP_KERNEL);
++ 
++      if (!buf) {
++              report = hid_get_report(report_enum, data);
++              goto nomem;
++      }
++ 
++      snprintf(buf, HID_DEBUG_BUFSIZE - 1,
++                      "\nreport (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
++      hid_debug_event(hid, buf);
   
        report = hid_get_report(report_enum, data);
--      if (!report)
++      if (!report) {
++              kfree(buf);
                return -1;
++      }
   
        /* dump the report */
--      dbg_hid("report %d (size %u) = ", report->id, size);
--      for (i = 0; i < size; i++)
--              dbg_hid_line(" %02x", data[i]);
--      dbg_hid_line("\n");
++      snprintf(buf, HID_DEBUG_BUFSIZE - 1,
++                      "report %d (size %u) = ", report->id, size);
++      hid_debug_event(hid, buf);
++      for (i = 0; i < size; i++) {
++              snprintf(buf, HID_DEBUG_BUFSIZE - 1,
++                              " %02x", data[i]);
++              hid_debug_event(hid, buf);
++      }
++      hid_debug_event(hid, "\n");
 + 
++      kfree(buf);
+  
++ nomem:
        if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
                ret = hdrv->raw_event(hid, report, data, size);
                if (ret != 0)
@@@@ -1292,7 -1292,6 -1308,6 +1310,7 @@@@ static const struct hid_device_id hid_b
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
 ++     { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
 ++     { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
 ++     { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
 ++     { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
  +     { 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) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
   
- -     { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
        { }
   };
@@@@ -1626,8 -1621,12 -1636,12 +1643,8 @@@@ static const struct hid_device_id hid_i
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
 ++     { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
 --     { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
 --     { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) },
 --     { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) },
 --     { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD4) },
 --     { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
@@@@ -1694,11 -1693,6 -1708,6 +1711,11 @@@@ static bool hid_ignore(struct hid_devic
                                hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST)
                        return true;
                break;
 ++     case USB_VENDOR_ID_SOUNDGRAPH:
 ++             if (hdev->product >= USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST &&
 ++                 hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST)
 ++                     return true;
 ++             break;
        }
   
        if (hdev->type == HID_TYPE_USBMOUSE &&
@@@@ -1730,6 -1724,6 -1739,8 +1747,8 @@@@ int hid_add_device(struct hid_device *h
        if (!ret)
                hdev->status |= HID_STAT_ADDED;
   
++      hid_debug_register(hdev, dev_name(&hdev->dev));
++ 
        return ret;
   }
   EXPORT_SYMBOL_GPL(hid_add_device);
@@@@ -1766,6 -1760,6 -1777,9 +1785,9 @@@@ struct hid_device *hid_allocate_device(
        for (i = 0; i < HID_REPORT_TYPES; i++)
                INIT_LIST_HEAD(&hdev->report_enum[i].report_list);
   
++      init_waitqueue_head(&hdev->debug_wait);
++      INIT_LIST_HEAD(&hdev->debug_list);
++ 
        return hdev;
   err:
        put_device(&hdev->dev);
@@@@ -1777,6 -1771,6 -1791,7 +1799,7 @@@@ static void hid_remove_device(struct hi
   {
        if (hdev->status & HID_STAT_ADDED) {
                device_del(&hdev->dev);
++              hid_debug_unregister(hdev);
                hdev->status &= ~HID_STAT_ADDED;
        }
   }
@@@@ -1852,6 -1846,6 -1867,10 +1875,10 @@@@ static int __init hid_init(void
   {
        int ret;
   
++      if (hid_debug)
++              printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n"
++                              "HID: debugfs is now used for inspecting the device (report descriptor, reports)\n");
++ 
        ret = bus_register(&hid_bus_type);
        if (ret) {
                printk(KERN_ERR "HID: can't register hid bus\n");
        if (ret)
                goto err_bus;
   
++      hid_debug_init();
++ 
        return 0;
   err_bus:
        bus_unregister(&hid_bus_type);
   
   static void __exit hid_exit(void)
   {
++      hid_debug_exit();
        hidraw_exit();
        bus_unregister(&hid_bus_type);
   }
diff --combined drivers/hid/hid-debug.c
index 04359ed64b8763b70553d052d9386c907329c193,04359ed64b8763b70553d052d9386c907329c193,06e87dc7779600510ce3b08722b778a5ae6c16d4..6abd0369aedba0125f935dc357f292d5e6850017
@@@@ -1,9 -1,9 -1,9 +1,9 @@@@
   /*
    *  (c) 1999 Andreas Gal             <gal@cs.uni-magdeburg.de>
    *  (c) 2000-2001 Vojtech Pavlik     <vojtech@ucw.cz>
--  *  (c) 2007 Jiri Kosina
++  *  (c) 2007-2009 Jiri Kosina
    *
--  *  Some debug stuff for the HID parser.
++  *  HID debugging support
    */
   
   /*
    * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
    */
   
++ #include <linux/debugfs.h>
++ #include <linux/seq_file.h>
++ #include <linux/sched.h>
++ #include <linux/uaccess.h>
++ #include <linux/poll.h>
++ 
   #include <linux/hid.h>
   #include <linux/hid-debug.h>
   
++ static struct dentry *hid_debug_root;
++ 
   struct hid_usage_entry {
        unsigned  page;
        unsigned  usage;
@@@@ -137,14 -137,14 -145,6 +145,14 @@@@ static const struct hid_usage_entry hid
       {0, 0x44, "BarrelSwitch"},
       {0, 0x45, "Eraser"},
       {0, 0x46, "TabletPick"},
  +    {0, 0x47, "Confidence"},
  +    {0, 0x48, "Width"},
  +    {0, 0x49, "Height"},
  +    {0, 0x51, "ContactID"},
  +    {0, 0x52, "InputMode"},
  +    {0, 0x53, "DeviceIndex"},
  +    {0, 0x54, "ContactCount"},
  +    {0, 0x55, "ContactMaximumNumber"},
     { 15, 0, "PhysicalInterfaceDevice" },
       {0, 0x00, "Undefined"},
       {0, 0x01, "Physical_Interface_Device"},
     { 0, 0, NULL }
   };
   
-- static void resolv_usage_page(unsigned page) {
++ /* Either output directly into simple seq_file, or (if f == NULL)
++  * allocate a separate buffer that will then be passed to the 'events'
++  * ringbuffer.
++  *
++  * This is because these functions can be called both for "one-shot"
++  * "rdesc" while resolving, or for blocking "events".
++  *
++  * This holds both for resolv_usage_page() and hid_resolv_usage().
++  */
++ static char *resolv_usage_page(unsigned page, struct seq_file *f) {
        const struct hid_usage_entry *p;
++      char *buf = NULL;
++ 
++      if (!f) {
++              buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
++              if (!buf)
++                      return ERR_PTR(-ENOMEM);
++      }
   
        for (p = hid_usage_table; p->description; p++)
                if (p->page == page) {
--                      printk("%s", p->description);
--                      return;
++                      if (!f) {
++                              snprintf(buf, HID_DEBUG_BUFSIZE, "%s",
++                                              p->description);
++                              return buf;
++                      }
++                      else {
++                              seq_printf(f, "%s", p->description);
++                              return NULL;
++                      }
                }
--      printk("%04x", page);
++      if (!f)
++              snprintf(buf, HID_DEBUG_BUFSIZE, "%04x", page);
++      else
++              seq_printf(f, "%04x", page);
++      return buf;
   }
   
-- void hid_resolv_usage(unsigned usage) {
++ char *hid_resolv_usage(unsigned usage, struct seq_file *f) {
        const struct hid_usage_entry *p;
++      char *buf = NULL;
++      int len = 0;
++ 
++      buf = resolv_usage_page(usage >> 16, f);
++      if (IS_ERR(buf)) {
++              printk(KERN_ERR "error allocating HID debug buffer\n");
++              return NULL;
++      }
   
--      if (!hid_debug)
--              return;
   
--      resolv_usage_page(usage >> 16);
--      printk(".");
++      if (!f) {
++              len = strlen(buf);
++              snprintf(buf+len, max(0, HID_DEBUG_BUFSIZE - len), ".");
++              len++;
++      }
++      else {
++              seq_printf(f, ".");
++      }
        for (p = hid_usage_table; p->description; p++)
                if (p->page == (usage >> 16)) {
                        for(++p; p->description && p->usage != 0; p++)
                                if (p->usage == (usage & 0xffff)) {
--                                      printk("%s", p->description);
--                                      return;
++                                      if (!f)
++                                              snprintf(buf + len,
++                                                      max(0,HID_DEBUG_BUFSIZE - len - 1),
++                                                      "%s", p->description);
++                                      else
++                                              seq_printf(f,
++                                                      "%s",
++                                                      p->description);
++                                      return buf;
                                }
                        break;
                }
--      printk("%04x", usage & 0xffff);
++      if (!f)
++              snprintf(buf + len, max(0, HID_DEBUG_BUFSIZE - len - 1),
++                              "%04x", usage & 0xffff);
++      else
++              seq_printf(f, "%04x", usage & 0xffff);
++      return buf;
   }
   EXPORT_SYMBOL_GPL(hid_resolv_usage);
   
-- static void tab(int n) {
--      printk(KERN_DEBUG "%*s", n, "");
++ static void tab(int n, struct seq_file *f) {
++      seq_printf(f, "%*s", n, "");
   }
   
-- void hid_dump_field(struct hid_field *field, int n) {
++ void hid_dump_field(struct hid_field *field, int n, struct seq_file *f) {
        int j;
   
--      if (!hid_debug)
--              return;
-- 
        if (field->physical) {
--              tab(n);
--              printk("Physical(");
--              hid_resolv_usage(field->physical); printk(")\n");
++              tab(n, f);
++              seq_printf(f, "Physical(");
++              hid_resolv_usage(field->physical, f); seq_printf(f, ")\n");
        }
        if (field->logical) {
--              tab(n);
--              printk("Logical(");
--              hid_resolv_usage(field->logical); printk(")\n");
++              tab(n, f);
++              seq_printf(f, "Logical(");
++              hid_resolv_usage(field->logical, f); seq_printf(f, ")\n");
        }
--      tab(n); printk("Usage(%d)\n", field->maxusage);
++      tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage);
        for (j = 0; j < field->maxusage; j++) {
--              tab(n+2); hid_resolv_usage(field->usage[j].hid); printk("\n");
++              tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n");
        }
        if (field->logical_minimum != field->logical_maximum) {
--              tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
--              tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
++              tab(n, f); seq_printf(f, "Logical Minimum(%d)\n", field->logical_minimum);
++              tab(n, f); seq_printf(f, "Logical Maximum(%d)\n", field->logical_maximum);
        }
        if (field->physical_minimum != field->physical_maximum) {
--              tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
--              tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
++              tab(n, f); seq_printf(f, "Physical Minimum(%d)\n", field->physical_minimum);
++              tab(n, f); seq_printf(f, "Physical Maximum(%d)\n", field->physical_maximum);
        }
        if (field->unit_exponent) {
--              tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
++              tab(n, f); seq_printf(f, "Unit Exponent(%d)\n", field->unit_exponent);
        }
        if (field->unit) {
                static const char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
                data >>= 4;
   
                if(sys > 4) {
--                      tab(n); printk("Unit(Invalid)\n");
++                      tab(n, f); seq_printf(f, "Unit(Invalid)\n");
                }
                else {
                        int earlier_unit = 0;
   
--                      tab(n); printk("Unit(%s : ", systems[sys]);
++                      tab(n, f); seq_printf(f, "Unit(%s : ", systems[sys]);
   
                        for (i=1 ; i<sizeof(__u32)*2 ; i++) {
                                char nibble = data & 0xf;
                                data >>= 4;
                                if (nibble != 0) {
                                        if(earlier_unit++ > 0)
--                                              printk("*");
--                                      printk("%s", units[sys][i]);
++                                              seq_printf(f, "*");
++                                      seq_printf(f, "%s", units[sys][i]);
                                        if(nibble != 1) {
                                                /* This is a _signed_ nibble(!) */
   
                                                int val = nibble & 0x7;
                                                if(nibble & 0x08)
                                                        val = -((0x7 & ~val) +1);
--                                              printk("^%d", val);
++                                              seq_printf(f, "^%d", val);
                                        }
                                }
                        }
--                      printk(")\n");
++                      seq_printf(f, ")\n");
                }
        }
--      tab(n); printk("Report Size(%u)\n", field->report_size);
--      tab(n); printk("Report Count(%u)\n", field->report_count);
--      tab(n); printk("Report Offset(%u)\n", field->report_offset);
++      tab(n, f); seq_printf(f, "Report Size(%u)\n", field->report_size);
++      tab(n, f); seq_printf(f, "Report Count(%u)\n", field->report_count);
++      tab(n, f); seq_printf(f, "Report Offset(%u)\n", field->report_offset);
   
--      tab(n); printk("Flags( ");
++      tab(n, f); seq_printf(f, "Flags( ");
        j = field->flags;
--      printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
--      printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
--      printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
--      printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
--      printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
--      printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : "");
--      printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
--      printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
--      printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
--      printk(")\n");
++      seq_printf(f, "%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
++      seq_printf(f, "%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
++      seq_printf(f, "%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
++      seq_printf(f, "%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
++      seq_printf(f, "%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
++      seq_printf(f, "%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : "");
++      seq_printf(f, "%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
++      seq_printf(f, "%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
++      seq_printf(f, "%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
++      seq_printf(f, ")\n");
   }
   EXPORT_SYMBOL_GPL(hid_dump_field);
   
-- void hid_dump_device(struct hid_device *device) {
++ void hid_dump_device(struct hid_device *device, struct seq_file *f)
++ {
        struct hid_report_enum *report_enum;
        struct hid_report *report;
        struct list_head *list;
        unsigned i,k;
        static const char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
   
--      if (!hid_debug)
--              return;
-- 
        for (i = 0; i < HID_REPORT_TYPES; i++) {
                report_enum = device->report_enum + i;
                list = report_enum->report_list.next;
                while (list != &report_enum->report_list) {
                        report = (struct hid_report *) list;
--                      tab(2);
--                      printk("%s", table[i]);
++                      tab(2, f);
++                      seq_printf(f, "%s", table[i]);
                        if (report->id)
--                              printk("(%d)", report->id);
--                      printk("[%s]", table[report->type]);
--                      printk("\n");
++                              seq_printf(f, "(%d)", report->id);
++                      seq_printf(f, "[%s]", table[report->type]);
++                      seq_printf(f, "\n");
                        for (k = 0; k < report->maxfield; k++) {
--                              tab(4);
--                              printk("Field(%d)\n", k);
--                              hid_dump_field(report->field[k], 6);
++                              tab(4, f);
++                              seq_printf(f, "Field(%d)\n", k);
++                              hid_dump_field(report->field[k], 6, f);
                        }
                        list = list->next;
                }
   }
   EXPORT_SYMBOL_GPL(hid_dump_device);
   
-- void hid_dump_input(struct hid_usage *usage, __s32 value) {
--      if (hid_debug < 2)
++ /* enqueue string to 'events' ring buffer */
++ void hid_debug_event(struct hid_device *hdev, char *buf)
++ {
++      int i;
++      struct hid_debug_list *list;
++ 
++      list_for_each_entry(list, &hdev->debug_list, node) {
++              for (i = 0; i <= strlen(buf); i++)
++                      list->hid_debug_buf[(list->tail + i) % (HID_DEBUG_BUFSIZE - 1)] =
++                              buf[i];
++              list->tail = (list->tail + i) % (HID_DEBUG_BUFSIZE - 1);
++         }
++ }
++ EXPORT_SYMBOL_GPL(hid_debug_event);
++ 
++ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value)
++ {
++      char *buf;
++      int len;
++ 
++      buf = hid_resolv_usage(usage->hid, NULL);
++      if (!buf)
                return;
++      len = strlen(buf);
++      snprintf(buf + len, HID_DEBUG_BUFSIZE - len - 1, " = %d\n", value);
++ 
++      hid_debug_event(hdev, buf);
++ 
++      kfree(buf);
++         wake_up_interruptible(&hdev->debug_wait);
   
--      printk(KERN_DEBUG "hid-debug: input ");
--      hid_resolv_usage(usage->hid);
--      printk(" = %d\n", value);
   }
   EXPORT_SYMBOL_GPL(hid_dump_input);
   
@@@@ -522,11 -522,11 -592,9 +600,11 @@@@ static const char *events[EV_MAX + 1] 
        [EV_FF_STATUS] = "ForceFeedbackStatus",
   };
   
  -static const char *syncs[2] = {
  +static const char *syncs[3] = {
        [SYN_REPORT] = "Report",                [SYN_CONFIG] = "Config",
  +     [SYN_MT_REPORT] = "MT Report",
   };
  +
   static const char *keys[KEY_MAX + 1] = {
        [KEY_RESERVED] = "Reserved",            [KEY_ESC] = "Esc",
        [KEY_1] = "1",                          [KEY_2] = "2",
@@@@ -744,17 -744,17 -812,8 +822,17 @@@@ static const char *absolutes[ABS_MAX + 
        [ABS_HAT2Y] = "Hat2Y",          [ABS_HAT3X] = "Hat3X",
        [ABS_HAT3Y] = "Hat 3Y",         [ABS_PRESSURE] = "Pressure",
        [ABS_DISTANCE] = "Distance",    [ABS_TILT_X] = "XTilt",
  -     [ABS_TILT_Y] = "YTilt",         [ABS_TOOL_WIDTH] = "Tool Width",
  +     [ABS_TILT_Y] = "YTilt",         [ABS_TOOL_WIDTH] = "ToolWidth",
        [ABS_VOLUME] = "Volume",        [ABS_MISC] = "Misc",
  +     [ABS_MT_TOUCH_MAJOR] = "MTMajor",
  +     [ABS_MT_TOUCH_MINOR] = "MTMinor",
  +     [ABS_MT_WIDTH_MAJOR] = "MTMajorW",
  +     [ABS_MT_WIDTH_MINOR] = "MTMinorW",
  +     [ABS_MT_ORIENTATION] = "MTOrientation",
  +     [ABS_MT_POSITION_X] = "MTPositionX",
  +     [ABS_MT_POSITION_Y] = "MTPositionY",
  +     [ABS_MT_TOOL_TYPE] = "MTToolType",
  +     [ABS_MT_BLOB_ID] = "MTBlobID",
   };
   
   static const char *misc[MSC_MAX + 1] = {
@@@@ -786,12 -786,12 -845,221 +864,221 @@@@ static const char **names[EV_MAX + 1] 
        [EV_SND] = sounds,                      [EV_REP] = repeats,
   };
   
-- void hid_resolv_event(__u8 type, __u16 code) {
++ void hid_resolv_event(__u8 type, __u16 code, struct seq_file *f) {
   
--      if (!hid_debug)
--              return;
-- 
--      printk("%s.%s", events[type] ? events[type] : "?",
++      seq_printf(f, "%s.%s", events[type] ? events[type] : "?",
                names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
   }
-- EXPORT_SYMBOL_GPL(hid_resolv_event);
++ 
++ void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f)
++ {
++      int i, j, k;
++      struct hid_report *report;
++      struct hid_usage *usage;
++ 
++      for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
++              list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
++                      for (i = 0; i < report->maxfield; i++) {
++                              for ( j = 0; j < report->field[i]->maxusage; j++) {
++                                      usage = report->field[i]->usage + j;
++                                      hid_resolv_usage(usage->hid, f);
++                                      seq_printf(f, " ---> ");
++                                      hid_resolv_event(usage->type, usage->code, f);
++                                      seq_printf(f, "\n");
++                              }
++                      }
++              }
++      }
++ 
++ }
++ 
++ 
++ static int hid_debug_rdesc_show(struct seq_file *f, void *p)
++ {
++      struct hid_device *hdev = f->private;
++      int i;
++ 
++      /* dump HID report descriptor */
++      for (i = 0; i < hdev->rsize; i++)
++              seq_printf(f, "%02x ", hdev->rdesc[i]);
++      seq_printf(f, "\n\n");
++ 
++      /* dump parsed data and input mappings */
++      hid_dump_device(hdev, f);
++      seq_printf(f, "\n");
++      hid_dump_input_mapping(hdev, f);
++ 
++      return 0;
++ }
++ 
++ static int hid_debug_rdesc_open(struct inode *inode, struct file *file)
++ {
++      return single_open(file, hid_debug_rdesc_show, inode->i_private);
++ }
++ 
++ static int hid_debug_events_open(struct inode *inode, struct file *file)
++ {
++      int err = 0;
++      struct hid_debug_list *list;
++ 
++      if (!(list = kzalloc(sizeof(struct hid_debug_list), GFP_KERNEL))) {
++              err = -ENOMEM;
++              goto out;
++      }
++ 
++      if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
++              err = -ENOMEM;
++              kfree(list);
++              goto out;
++      }
++      list->hdev = (struct hid_device *) inode->i_private;
++      file->private_data = list;
++      mutex_init(&list->read_mutex);
++ 
++      list_add_tail(&list->node, &list->hdev->debug_list);
++ 
++ out:
++      return err;
++ }
++ 
++ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
++              size_t count, loff_t *ppos)
++ {
++      struct hid_debug_list *list = file->private_data;
++      int ret = 0, len;
++      DECLARE_WAITQUEUE(wait, current);
++ 
++      while (ret == 0) {
++              mutex_lock(&list->read_mutex);
++              if (list->head == list->tail) {
++                      add_wait_queue(&list->hdev->debug_wait, &wait);
++                      set_current_state(TASK_INTERRUPTIBLE);
++ 
++                      while (list->head == list->tail) {
++                              if (file->f_flags & O_NONBLOCK) {
++                                      ret = -EAGAIN;
++                                      break;
++                              }
++                              if (signal_pending(current)) {
++                                      ret = -ERESTARTSYS;
++                                      break;
++                              }
++ 
++                              if (!list->hdev || !list->hdev->debug) {
++                                      ret = -EIO;
++                                      break;
++                              }
++ 
++                              /* allow O_NONBLOCK from other threads */
++                              mutex_unlock(&list->read_mutex);
++                              schedule();
++                              mutex_lock(&list->read_mutex);
++                              set_current_state(TASK_INTERRUPTIBLE);
++                      }
++ 
++                      set_current_state(TASK_RUNNING);
++                      remove_wait_queue(&list->hdev->debug_wait, &wait);
++              }
++ 
++              if (ret)
++                      goto out;
++ 
++              /* pass the ringbuffer contents to userspace */
++ copy_rest:
++              if (list->tail == list->head)
++                      goto out;
++              if (list->tail > list->head) {
++                      len = list->tail - list->head;
++ 
++                      if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
++                              ret = -EFAULT;
++                              goto out;
++                      }
++                      ret += len;
++                      list->head += len;
++              } else {
++                      len = HID_DEBUG_BUFSIZE - list->head;
++ 
++                      if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
++                              ret = -EFAULT;
++                              goto out;
++                      }
++                      list->head = 0;
++                      ret += len;
++                      goto copy_rest;
++              }
++ 
++      }
++ out:
++      mutex_unlock(&list->read_mutex);
++      return ret;
++ }
++ 
++ static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait)
++ {
++      struct hid_debug_list *list = file->private_data;
++ 
++      poll_wait(file, &list->hdev->debug_wait, wait);
++      if (list->head != list->tail)
++              return POLLIN | POLLRDNORM;
++      if (!list->hdev->debug)
++              return POLLERR | POLLHUP;
++      return 0;
++ }
++ 
++ static int hid_debug_events_release(struct inode *inode, struct file *file)
++ {
++      struct hid_debug_list *list = file->private_data;
++ 
++      list_del(&list->node);
++      kfree(list->hid_debug_buf);
++      kfree(list);
++ 
++      return 0;
++ }
++ 
++ static const struct file_operations hid_debug_rdesc_fops = {
++      .open           = hid_debug_rdesc_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release,
++ };
++ 
++ static const struct file_operations hid_debug_events_fops = {
++      .owner =        THIS_MODULE,
++      .open           = hid_debug_events_open,
++      .read           = hid_debug_events_read,
++      .poll           = hid_debug_events_poll,
++      .release        = hid_debug_events_release,
++ };
++ 
++ 
++ void hid_debug_register(struct hid_device *hdev, const char *name)
++ {
++      hdev->debug_dir = debugfs_create_dir(name, hid_debug_root);
++      hdev->debug_rdesc = debugfs_create_file("rdesc", 0400,
++                      hdev->debug_dir, hdev, &hid_debug_rdesc_fops);
++      hdev->debug_events = debugfs_create_file("events", 0400,
++                      hdev->debug_dir, hdev, &hid_debug_events_fops);
++      hdev->debug = 1;
++ }
++ 
++ void hid_debug_unregister(struct hid_device *hdev)
++ {
++      hdev->debug = 0;
++      wake_up_interruptible(&hdev->debug_wait);
++      debugfs_remove(hdev->debug_rdesc);
++      debugfs_remove(hdev->debug_events);
++      debugfs_remove(hdev->debug_dir);
++ }
++ 
++ void hid_debug_init(void)
++ {
++      hid_debug_root = debugfs_create_dir("hid", NULL);
++ }
++ 
++ void hid_debug_exit(void)
++ {
++      debugfs_remove_recursive(hid_debug_root);
++ }
++ 
index 25f38a5af26931bff9d99c7c370eb07e8325b939,3c1fcb7640abe1458d52146f8456c16295ec531f,708aa52d07534d462c466c35df478c67c41ae833..1b0e07a67d6d079c26848f42b28ce6835bdb6014
@@@@ -4,8 -4,8 -4,8 +4,8 @@@@
    *  Copyright (c) 1999 Andreas Gal
    *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
    *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
--  *  Copyright (c) 2006-2008 Jiri Kosina
    *  Copyright (c) 2007-2008 Oliver Neukum
++  *  Copyright (c) 2006-2009 Jiri Kosina
    */
   
   /*
   #include <linux/list.h>
   #include <linux/mm.h>
   #include <linux/mutex.h>
  -#include <linux/smp_lock.h>
   #include <linux/spinlock.h>
   #include <asm/unaligned.h>
   #include <asm/byteorder.h>
@@@@ -489,8 -489,7 -490,7 +489,8 @@@@ static void hid_ctrl(struct urb *urb
        wake_up(&usbhid->wait);
   }
   
 --void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
 ++static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report,
 ++                                unsigned char dir)
   {
        int head;
        struct usbhid_device *usbhid = hid->driver_data;
@@@@ -886,11 -885,11 -886,6 +886,6 @@@@ static int usbhid_parse(struct hid_devi
                goto err;
        }
   
--      dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
--      for (n = 0; n < rsize; n++)
--              dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
--      dbg_hid_line("\n");
-- 
        ret = hid_parse_report(hid, rdesc, rsize);
        kfree(rdesc);
        if (ret) {
@@@@ -986,6 -985,7 -981,7 +981,6 @@@@ static int usbhid_start(struct hid_devi
        INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
        setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
   
 --     spin_lock_init(&usbhid->lock);
        spin_lock_init(&usbhid->lock);
   
        usbhid->intf = intf;
        usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
   
        usbhid_init_reports(hid);
--      hid_dump_device(hid);
   
        set_bit(HID_STARTED, &usbhid->iofl);
   
@@@@ -1233,11 -1233,11 -1228,12 +1227,11 @@@@ static int hid_post_reset(struct usb_in
        struct hid_device *hid = usb_get_intfdata(intf);
        struct usbhid_device *usbhid = hid->driver_data;
        int status;
  - 
  +
        spin_lock_irq(&usbhid->lock);
        clear_bit(HID_RESET_PENDING, &usbhid->iofl);
        spin_unlock_irq(&usbhid->lock);
        hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
  -     /* FIXME: Any more reinitialization needed? */
        status = hid_start_in(hid);
        if (status < 0)
                hid_io_error(hid);
   int usbhid_get_power(struct hid_device *hid)
   {
        struct usbhid_device *usbhid = hid->driver_data;
  - 
  +
        return usb_autopm_get_interface(usbhid->intf);
   }
   
   void usbhid_put_power(struct hid_device *hid)
   {
        struct usbhid_device *usbhid = hid->driver_data;
  - 
  +
        usb_autopm_put_interface(usbhid->intf);
   }
   
diff --combined include/linux/hid.h
index 53489fd4d7006e35e6fe7bc95a50a0a956aee8dd,53489fd4d7006e35e6fe7bc95a50a0a956aee8dd,60fa52913f891419f4e916e16d5a279950963e92..a0ebdace7baa2fa496d2d8fc09cf1a2c0b6f1b60
@@@@ -238,42 -238,42 -238,6 +238,42 @@@@ struct hid_item 
   #define HID_GD_RIGHT         0x00010092
   #define HID_GD_LEFT          0x00010093
   
  +#define HID_DG_DIGITIZER     0x000d0001
  +#define HID_DG_PEN           0x000d0002
  +#define HID_DG_LIGHTPEN              0x000d0003
  +#define HID_DG_TOUCHSCREEN   0x000d0004
  +#define HID_DG_TOUCHPAD              0x000d0005
  +#define HID_DG_STYLUS                0x000d0020
  +#define HID_DG_PUCK          0x000d0021
  +#define HID_DG_FINGER                0x000d0022
  +#define HID_DG_TIPPRESSURE   0x000d0030
  +#define HID_DG_BARRELPRESSURE        0x000d0031
  +#define HID_DG_INRANGE               0x000d0032
  +#define HID_DG_TOUCH         0x000d0033
  +#define HID_DG_UNTOUCH               0x000d0034
  +#define HID_DG_TAP           0x000d0035
  +#define HID_DG_TABLETFUNCTIONKEY     0x000d0039
  +#define HID_DG_PROGRAMCHANGEKEY      0x000d003a
  +#define HID_DG_INVERT                0x000d003c
  +#define HID_DG_TIPSWITCH     0x000d0042
  +#define HID_DG_TIPSWITCH2    0x000d0043
  +#define HID_DG_BARRELSWITCH  0x000d0044
  +#define HID_DG_ERASER                0x000d0045
  +#define HID_DG_TABLETPICK    0x000d0046
  +/*
  + * as of May 20, 2009 the usages below are not yet in the official USB spec
  + * but are being pushed by Microsft as described in their paper "Digitizer
  + * Drivers for Windows Touch and Pen-Based Computers"
  + */
  +#define HID_DG_CONFIDENCE    0x000d0047
  +#define HID_DG_WIDTH         0x000d0048
  +#define HID_DG_HEIGHT                0x000d0049
  +#define HID_DG_CONTACTID     0x000d0051
  +#define HID_DG_INPUTMODE     0x000d0052
  +#define HID_DG_DEVICEINDEX   0x000d0053
  +#define HID_DG_CONTACTCOUNT  0x000d0054
  +#define HID_DG_CONTACTMAX    0x000d0055
  +
   /*
    * HID report types --- Ouch! HID spec says 1 2 3!
    */
@@@@ -500,6 -500,6 -464,14 +500,14 @@@@ struct hid_device {                                                     /* device rep
   
        /* handler for raw output data, used by hidraw */
        int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
++ 
++      /* debugging support via debugfs */
++      unsigned short debug;
++      struct dentry *debug_dir;
++      struct dentry *debug_rdesc;
++      struct dentry *debug_events;
++      struct list_head debug_list;
++      wait_queue_head_t debug_wait;
   };
   
   static inline void *hid_get_drvdata(struct hid_device *hdev)
@@@@ -657,9 -657,9 -629,7 +665,7 @@@@ struct hid_ll_driver 
   
   /* HID core API */
   
-- #ifdef CONFIG_HID_DEBUG
   extern int hid_debug;
-- #endif
   
   extern int hid_add_device(struct hid_device *);
   extern void hid_destroy_device(struct hid_device *);
@@@@ -815,21 -815,21 -785,9 +821,9 @@@@ int hid_pidff_init(struct hid_device *h
   #define hid_pidff_init NULL
   #endif
   
-- #ifdef CONFIG_HID_DEBUG
   #define dbg_hid(format, arg...) if (hid_debug) \
                                printk(KERN_DEBUG "%s: " format ,\
                                __FILE__ , ## arg)
-- #define dbg_hid_line(format, arg...) if (hid_debug) \
--                              printk(format, ## arg)
-- #else
-- static inline int __attribute__((format(printf, 1, 2)))
-- dbg_hid(const char *fmt, ...)
-- {
--      return 0;
-- }
-- #define dbg_hid_line dbg_hid
-- #endif /* HID_DEBUG */
-- 
   #define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
                __FILE__ , ## arg)
   #endif /* HID_FF */