]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'upstream' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Mon, 1 Oct 2012 12:37:51 +0000 (14:37 +0200)
committerJiri Kosina <jkosina@suse.cz>
Mon, 1 Oct 2012 12:37:51 +0000 (14:37 +0200)
Conflicts:
drivers/hid/usbhid/hid-quirks.c

1  2 
drivers/hid/Kconfig
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-lenovo-tpkbd.c
drivers/hid/hid-lg.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-wacom.c
drivers/hid/hidraw.c
drivers/hid/usbhid/hid-quirks.c

diff --combined drivers/hid/Kconfig
index bf0617e47b892434120d782f864e55d8d588c6e6,d0045283e6043fcab1aeb9dc254212a1b2ed7286..2af774ad10606b7048e70ec7218ce36f33010c77
@@@ -307,7 -307,6 +307,6 @@@ config HID_LOGITEC
  config HID_LOGITECH_DJ
        tristate "Logitech Unifying receivers full support"
        depends on HID_LOGITECH
-       default m
        ---help---
        Say Y if you want support for Logitech Unifying receivers and devices.
        Unifying receivers are capable of pairing up to 6 Logitech compliant
@@@ -527,14 -526,6 +526,14 @@@ config HID_PICOLCD_LED
        ---help---
          Provide access to PicoLCD's GPO pins via leds class.
  
 +config HID_PICOLCD_CIR
 +      bool "CIR via RC class" if EXPERT
 +      default !EXPERT
 +      depends on HID_PICOLCD
 +      depends on HID_PICOLCD=RC_CORE || RC_CORE=y
 +      ---help---
 +        Provide access to PicoLCD's CIR interface via remote control (LIRC).
 +
  config HID_PRIMAX
        tristate "Primax non-fully HID-compliant devices"
        depends on USB_HID
        Support for Primax devices that are not fully compliant with the
        HID standard.
  
 +config HID_PS3REMOTE
 +      tristate "Sony PS3 BD Remote Control"
 +      depends on BT_HIDP
 +      ---help---
 +      Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech
 +      Harmony Adapter for PS3, which connect over Bluetooth.
 +
 +      Support for the 6-axis controllers is provided by HID_SONY.
 +
  config HID_ROCCAT
        tristate "Roccat device support"
        depends on USB_HID
@@@ -578,9 -560,7 +577,9 @@@ config HID_SON
        tristate "Sony PS3 controller"
        depends on USB_HID
        ---help---
 -      Support for Sony PS3 controller.
 +      Support for Sony PS3 6-axis controllers.
 +
 +      Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE.
  
  config HID_SPEEDLINK
        tristate "Speedlink VAD Cezanne mouse support"
diff --combined drivers/hid/hid-core.c
index 9072e0ed18761b9505e1d4ef9d27f1d0ee6febfe,ec917690c263d870d7119f0ff588d3ec7a9c0083..2cd6880b6b173d79ab244335f52d9f1324513e54
@@@ -126,7 -126,7 +126,7 @@@ static int open_collection(struct hid_p
  
        if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
                hid_err(parser->device, "collection stack overflow\n");
-               return -1;
+               return -EINVAL;
        }
  
        if (parser->device->maxcollection == parser->device->collection_size) {
                                parser->device->collection_size * 2, GFP_KERNEL);
                if (collection == NULL) {
                        hid_err(parser->device, "failed to reallocate collection array\n");
-                       return -1;
+                       return -ENOMEM;
                }
                memcpy(collection, parser->device->collection,
                        sizeof(struct hid_collection) *
@@@ -170,7 -170,7 +170,7 @@@ static int close_collection(struct hid_
  {
        if (!parser->collection_stack_ptr) {
                hid_err(parser->device, "collection stack underflow\n");
-               return -1;
+               return -EINVAL;
        }
        parser->collection_stack_ptr--;
        return 0;
@@@ -374,7 -374,7 +374,7 @@@ static int hid_parser_global(struct hid
  
        case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
                parser->global.report_size = item_udata(item);
-               if (parser->global.report_size > 96) {
+               if (parser->global.report_size > 128) {
                        hid_err(parser->device, "invalid report_size %d\n",
                                        parser->global.report_size);
                        return -1;
@@@ -757,6 -757,7 +757,7 @@@ int hid_open_report(struct hid_device *
        struct hid_item item;
        unsigned int size;
        __u8 *start;
+       __u8 *buf;
        __u8 *end;
        int ret;
        static int (*dispatch_type[])(struct hid_parser *parser,
                return -ENODEV;
        size = device->dev_rsize;
  
+       buf = kmemdup(start, size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
        if (device->driver->report_fixup)
-               start = device->driver->report_fixup(device, start, &size);
+               start = device->driver->report_fixup(device, buf, &size);
+       else
+               start = buf;
  
-       device->rdesc = kmemdup(start, size, GFP_KERNEL);
-       if (device->rdesc == NULL)
+       start = kmemdup(start, size, GFP_KERNEL);
+       kfree(buf);
+       if (start == NULL)
                return -ENOMEM;
+       device->rdesc = start;
        device->rsize = size;
  
        parser = vzalloc(sizeof(struct hid_parser));
@@@ -996,8 -1006,7 +1006,8 @@@ static void hid_process_event(struct hi
        struct hid_driver *hdrv = hid->driver;
        int ret;
  
 -      hid_dump_input(hid, usage, value);
 +      if (!list_empty(&hid->debug_list))
 +              hid_dump_input(hid, usage, value);
  
        if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
                ret = hdrv->event(hid, field, usage, value);
@@@ -1448,7 -1457,14 +1458,14 @@@ void hid_disconnect(struct hid_device *
  }
  EXPORT_SYMBOL_GPL(hid_disconnect);
  
- /* a list of devices for which there is a specialized driver on HID bus */
+ /*
+  * A list of devices for which there is a specialized driver on HID bus.
+  *
+  * Please note that for multitouch devices (driven by hid-multitouch driver),
+  * there is a proper autodetection and autoloading in place (based on presence
+  * of HID_DG_CONTACTID), so those devices don't need to be added to this list,
+  * as we are doing the right thing in hid_scan_usage().
+  */
  static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
 +#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD)
 +      { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
 +#endif
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
 +      { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
+ #if IS_ENABLED(CONFIG_HID_ROCCAT)
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
+ #endif
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
 +      { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
 +      { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
diff --combined drivers/hid/hid-ids.h
index a534375fdf2e37fd042e032b939ebdef6d912cf0,753f3d65f94c611a8dd95ebb2583461a358d3f73..c1da94a81a0dbb8403073741906802fc6b020685
@@@ -5,7 -5,6 +5,6 @@@
   *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
   *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
   *  Copyright (c) 2006-2007 Jiri Kosina
-  *  Copyright (c) 2007 Paul Walmsley
   */
  
  /*
  #define USB_VENDOR_ID_EMS             0x2006
  #define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
  
 +#define USB_VENDOR_ID_FLATFROG                0x25b5
 +#define USB_DEVICE_ID_MULTITOUCH_3200 0x0002
 +
  #define USB_VENDOR_ID_ESSENTIAL_REALITY       0x0d7f
  #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
  
  #define USB_VENDOR_ID_EZKEY           0x0518
  #define USB_DEVICE_ID_BTC_8193                0x0002
  
+ #define USB_VENDOR_ID_FREESCALE               0x15A2
+ #define USB_DEVICE_ID_FREESCALE_MX28  0x004F
  #define USB_VENDOR_ID_FRUCTEL 0x25B6
  #define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002
  
  #define USB_DEVICE_ID_LOGITECH_RECEIVER       0xc101
  #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
  #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
 +#define USB_DEVICE_ID_LOGITECH_HARMONY_PS3 0x0306
  #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a
  #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD      0xc211
  #define USB_DEVICE_ID_LOGITECH_EXTREME_3D     0xc215
  #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH            0x3000
  #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001               0x3001
  #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008               0x3008
- #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001
  
  #define USB_VENDOR_ID_ROCCAT          0x1e7d
  #define USB_DEVICE_ID_ROCCAT_ARVO     0x30d4
  
  #define USB_VENDOR_ID_SONY                    0x054c
  #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE     0x024b
 +#define USB_DEVICE_ID_SONY_PS3_BDREMOTE               0x0306
  #define USB_DEVICE_ID_SONY_PS3_CONTROLLER     0x0268
  #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER      0x042f
  
  #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U  0x0005
  #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062   0x0064
  #define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522
 +#define USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60   0x0781
  
  #define USB_VENDOR_ID_UNITEC  0x227d
  #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709   0x0709
index 60c4e1e85913fd435ba7c3fe977db50e4fb00f6c,32bfcc4808b7f9ff268889b44dfeb0d84a8b67ea..cea016e94f43e336ec1a4d73eb2cbbdba9e1ace7
@@@ -56,9 -56,8 +56,8 @@@ static int tpkbd_input_mapping(struct h
  static int tpkbd_features_set(struct hid_device *hdev)
  {
        struct hid_report *report;
-       struct tpkbd_data_pointer *data_pointer;
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
  
        report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
@@@ -77,14 -76,8 +76,8 @@@ static ssize_t pointer_press_to_select_
                struct device_attribute *attr,
                char *buf)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  
        return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
  }
@@@ -94,16 -87,10 +87,10 @@@ static ssize_t pointer_press_to_select_
                const char *buf,
                size_t count)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
        int value;
  
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        if (kstrtoint(buf, 10, &value))
                return -EINVAL;
        if (value < 0 || value > 1)
@@@ -119,14 -106,8 +106,8 @@@ static ssize_t pointer_dragging_show(st
                struct device_attribute *attr,
                char *buf)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  
        return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
  }
@@@ -136,16 -117,10 +117,10 @@@ static ssize_t pointer_dragging_store(s
                const char *buf,
                size_t count)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
        int value;
  
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        if (kstrtoint(buf, 10, &value))
                return -EINVAL;
        if (value < 0 || value > 1)
@@@ -161,14 -136,8 +136,8 @@@ static ssize_t pointer_release_to_selec
                struct device_attribute *attr,
                char *buf)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  
        return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
  }
@@@ -178,16 -147,10 +147,10 @@@ static ssize_t pointer_release_to_selec
                const char *buf,
                size_t count)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
        int value;
  
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        if (kstrtoint(buf, 10, &value))
                return -EINVAL;
        if (value < 0 || value > 1)
@@@ -203,14 -166,8 +166,8 @@@ static ssize_t pointer_select_right_sho
                struct device_attribute *attr,
                char *buf)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  
        return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
  }
@@@ -220,16 -177,10 +177,10 @@@ static ssize_t pointer_select_right_sto
                const char *buf,
                size_t count)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
        int value;
  
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        if (kstrtoint(buf, 10, &value))
                return -EINVAL;
        if (value < 0 || value > 1)
@@@ -245,14 -196,8 +196,8 @@@ static ssize_t pointer_sensitivity_show
                struct device_attribute *attr,
                char *buf)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  
        return snprintf(buf, PAGE_SIZE, "%u\n",
                data_pointer->sensitivity);
@@@ -263,16 -208,10 +208,10 @@@ static ssize_t pointer_sensitivity_stor
                const char *buf,
                size_t count)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
        int value;
  
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
                return -EINVAL;
  
@@@ -286,14 -225,10 +225,10 @@@ static ssize_t pointer_press_speed_show
                struct device_attribute *attr,
                char *buf)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+       data_pointer = hid_get_drvdata(hdev);
  
        return snprintf(buf, PAGE_SIZE, "%u\n",
                data_pointer->press_speed);
@@@ -304,16 -239,10 +239,10 @@@ static ssize_t pointer_press_speed_stor
                const char *buf,
                size_t count)
  {
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
        int value;
  
-       hdev = container_of(dev, struct hid_device, dev);
-       if (hdev == NULL)
-               return -ENODEV;
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
                return -EINVAL;
  
@@@ -370,15 -299,11 +299,11 @@@ static const struct attribute_group tpk
  static enum led_brightness tpkbd_led_brightness_get(
                        struct led_classdev *led_cdev)
  {
-       struct device *dev;
-       struct hid_device *hdev;
-       struct tpkbd_data_pointer *data_pointer;
+       struct device *dev = led_cdev->dev->parent;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
        int led_nr = 0;
  
-       dev = led_cdev->dev->parent;
-       hdev = container_of(dev, struct hid_device, dev);
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        if (led_cdev == &data_pointer->led_micmute)
                led_nr = 1;
  
  static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
                        enum led_brightness value)
  {
-       struct device *dev;
-       struct hid_device *hdev;
+       struct device *dev = led_cdev->dev->parent;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
        struct hid_report *report;
-       struct tpkbd_data_pointer *data_pointer;
        int led_nr = 0;
  
-       dev = led_cdev->dev->parent;
-       hdev = container_of(dev, struct hid_device, dev);
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        if (led_cdev == &data_pointer->led_micmute)
                led_nr = 1;
  
@@@ -508,19 -429,15 +429,17 @@@ err_free
  
  static void tpkbd_remove_tp(struct hid_device *hdev)
  {
-       struct tpkbd_data_pointer *data_pointer;
+       struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
  
        sysfs_remove_group(&hdev->dev.kobj,
                        &tpkbd_attr_group_pointer);
  
-       data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
        led_classdev_unregister(&data_pointer->led_micmute);
        led_classdev_unregister(&data_pointer->led_mute);
  
        hid_set_drvdata(hdev, NULL);
 +      kfree(data_pointer->led_micmute.name);
 +      kfree(data_pointer->led_mute.name);
        kfree(data_pointer);
  }
  
diff --combined drivers/hid/hid-lg.c
index afc4de389f81a715828170e7e0380745d1f6d53a,55ce2bfe51fafecfde782c7a9d74c4f678f60fa2..a2f8e88b9fa2503ed1a6a1dcb63f92f38372bc80
@@@ -5,7 -5,6 +5,6 @@@
   *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
   *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
   *  Copyright (c) 2006-2007 Jiri Kosina
-  *  Copyright (c) 2007 Paul Walmsley
   *  Copyright (c) 2008 Jiri Slaby
   *  Copyright (c) 2010 Hendrik Iben
   */
@@@ -109,7 -108,7 +108,7 @@@ static __u8 dfp_rdesc_fixed[] = 
  static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
  {
-       struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+       struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
  
        if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
                        rdesc[84] == 0x8c && rdesc[85] == 0x02) {
@@@ -278,7 -277,7 +277,7 @@@ static int lg_input_mapping(struct hid_
                  0,  0,  0,  0,  0,183,184,185,186,187,
                188,189,190,191,192,193,194,  0,  0,  0
        };
-       struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+       struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
        unsigned int hid = usage->hid;
  
        if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
@@@ -319,7 -318,7 +318,7 @@@ static int lg_input_mapped(struct hid_d
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
  {
-       struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+       struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
  
        if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
                        (field->flags & HID_MAIN_ITEM_RELATIVE))
  static int lg_event(struct hid_device *hdev, struct hid_field *field,
                struct hid_usage *usage, __s32 value)
  {
-       struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+       struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
  
        if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
                input_event(field->hidinput->input, usage->type, usage->code,
                                -value);
                return 1;
        }
 +      if (drv_data->quirks & LG_FF4) {
 +              return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
 +      }
  
        return 0;
  }
@@@ -361,7 -357,7 +360,7 @@@ static int lg_probe(struct hid_device *
                return -ENOMEM;
        }
        drv_data->quirks = id->driver_data;
 -      
 +
        hid_set_drvdata(hdev, (void *)drv_data);
  
        if (drv_data->quirks & LG_NOGET)
        }
  
        /* Setup wireless link with Logitech Wii wheel */
 -      if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
 +      if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
                unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  
                ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
@@@ -419,7 -415,7 +418,7 @@@ err_free
  
  static void lg_remove(struct hid_device *hdev)
  {
-       struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+       struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
        if (drv_data->quirks & LG_FF4)
                lg4ff_deinit(hdev);
  
@@@ -479,7 -475,7 +478,7 @@@ static const struct hid_device_id lg_de
                .driver_data = LG_NOGET | LG_FF4 },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
                .driver_data = LG_FF4 },
 -      { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
 +      { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
                .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
                .driver_data = LG_FF2 },
diff --combined drivers/hid/hid-lg4ff.c
index 4fb4a80928c8fe2ea6d18a7cd8a67af5276868ac,da23c6bf1a63b282ccf9dbcaa40f319246869875..d7947c701f3063ac6c3683c29d3eca333b7ca1b0
  #define G27_REV_MAJ 0x12
  #define G27_REV_MIN 0x38
  
 +#define DFP_X_MIN 0
 +#define DFP_X_MAX 16383
 +#define DFP_PEDAL_MIN 0
 +#define DFP_PEDAL_MAX 255
 +
  #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
  
  static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
@@@ -58,7 -53,6 +58,7 @@@ static ssize_t lg4ff_range_store(struc
  static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store);
  
  struct lg4ff_device_entry {
 +      __u32 product_id;
        __u16 range;
        __u16 min_range;
        __u16 max_range;
@@@ -135,77 -129,26 +135,77 @@@ static const struct lg4ff_usb_revision 
        {G27_REV_MAJ,  G27_REV_MIN,  &native_g27},      /* G27 */
  };
  
 +/* Recalculates X axis value accordingly to currently selected range */
 +static __s32 lg4ff_adjust_dfp_x_axis(__s32 value, __u16 range)
 +{
 +      __u16 max_range;
 +      __s32 new_value;
 +
 +      if (range == 900)
 +              return value;
 +      else if (range == 200)
 +              return value;
 +      else if (range < 200)
 +              max_range = 200;
 +      else
 +              max_range = 900;
 +
 +      new_value = 8192 + mult_frac(value - 8192, max_range, range);
 +      if (new_value < 0)
 +              return 0;
 +      else if (new_value > 16383)
 +              return 16383;
 +      else
 +              return new_value;
 +}
 +
 +int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
 +                           struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data)
 +{
 +      struct lg4ff_device_entry *entry = drv_data->device_props;
 +      __s32 new_value = 0;
 +
 +      if (!entry) {
 +              hid_err(hid, "Device properties not found");
 +              return 0;
 +      }
 +
 +      switch (entry->product_id) {
 +      case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
 +              switch (usage->code) {
 +              case ABS_X:
 +                      new_value = lg4ff_adjust_dfp_x_axis(value, entry->range);
 +                      input_event(field->hidinput->input, usage->type, usage->code, new_value);
 +                      return 1;
 +              default:
 +                      return 0;
 +              }
 +      default:
 +              return 0;
 +      }
 +}
 +
  static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
  {
        struct hid_device *hid = input_get_drvdata(dev);
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
 +      __s32 *value = report->field[0]->value;
        int x;
  
 -#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
 +#define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0)
  
        switch (effect->type) {
        case FF_CONSTANT:
                x = effect->u.ramp.start_level + 0x80;  /* 0x80 is no force */
                CLAMP(x);
 -              report->field[0]->value[0] = 0x11;      /* Slot 1 */
 -              report->field[0]->value[1] = 0x08;
 -              report->field[0]->value[2] = x;
 -              report->field[0]->value[3] = 0x80;
 -              report->field[0]->value[4] = 0x00;
 -              report->field[0]->value[5] = 0x00;
 -              report->field[0]->value[6] = 0x00;
 +              value[0] = 0x11;        /* Slot 1 */
 +              value[1] = 0x08;
 +              value[2] = x;
 +              value[3] = 0x80;
 +              value[4] = 0x00;
 +              value[5] = 0x00;
 +              value[6] = 0x00;
  
                usbhid_submit_report(hid, report, USB_DIR_OUT);
                break;
@@@ -220,15 -163,14 +220,15 @@@ static void hid_lg4ff_set_autocenter_de
        struct hid_device *hid = input_get_drvdata(dev);
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
 +      __s32 *value = report->field[0]->value;
  
 -      report->field[0]->value[0] = 0xfe;
 -      report->field[0]->value[1] = 0x0d;
 -      report->field[0]->value[2] = magnitude >> 13;
 -      report->field[0]->value[3] = magnitude >> 13;
 -      report->field[0]->value[4] = magnitude >> 8;
 -      report->field[0]->value[5] = 0x00;
 -      report->field[0]->value[6] = 0x00;
 +      value[0] = 0xfe;
 +      value[1] = 0x0d;
 +      value[2] = magnitude >> 13;
 +      value[3] = magnitude >> 13;
 +      value[4] = magnitude >> 8;
 +      value[5] = 0x00;
 +      value[6] = 0x00;
  
        usbhid_submit_report(hid, report, USB_DIR_OUT);
  }
@@@ -239,16 -181,16 +239,16 @@@ static void hid_lg4ff_set_autocenter_ff
        struct hid_device *hid = input_get_drvdata(dev);
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
 +      __s32 *value = report->field[0]->value;
        magnitude = magnitude * 90 / 65535;
 -      
  
 -      report->field[0]->value[0] = 0xfe;
 -      report->field[0]->value[1] = 0x03;
 -      report->field[0]->value[2] = magnitude >> 14;
 -      report->field[0]->value[3] = magnitude >> 14;
 -      report->field[0]->value[4] = magnitude;
 -      report->field[0]->value[5] = 0x00;
 -      report->field[0]->value[6] = 0x00;
 +      value[0] = 0xfe;
 +      value[1] = 0x03;
 +      value[2] = magnitude >> 14;
 +      value[3] = magnitude >> 14;
 +      value[4] = magnitude;
 +      value[5] = 0x00;
 +      value[6] = 0x00;
  
        usbhid_submit_report(hid, report, USB_DIR_OUT);
  }
@@@ -258,17 -200,15 +258,17 @@@ static void hid_lg4ff_set_range_g25(str
  {
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
 +      __s32 *value = report->field[0]->value;
 +
        dbg_hid("G25/G27/DFGT: setting range to %u\n", range);
  
 -      report->field[0]->value[0] = 0xf8;
 -      report->field[0]->value[1] = 0x81;
 -      report->field[0]->value[2] = range & 0x00ff;
 -      report->field[0]->value[3] = (range & 0xff00) >> 8;
 -      report->field[0]->value[4] = 0x00;
 -      report->field[0]->value[5] = 0x00;
 -      report->field[0]->value[6] = 0x00;
 +      value[0] = 0xf8;
 +      value[1] = 0x81;
 +      value[2] = range & 0x00ff;
 +      value[3] = (range & 0xff00) >> 8;
 +      value[4] = 0x00;
 +      value[5] = 0x00;
 +      value[6] = 0x00;
  
        usbhid_submit_report(hid, report, USB_DIR_OUT);
  }
@@@ -279,18 -219,16 +279,18 @@@ static void hid_lg4ff_set_range_dfp(str
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
        int start_left, start_right, full_range;
 +      __s32 *value = report->field[0]->value;
 +
        dbg_hid("Driving Force Pro: setting range to %u\n", range);
  
        /* Prepare "coarse" limit command */
 -      report->field[0]->value[0] = 0xf8;
 -      report->field[0]->value[1] = 0x00;      /* Set later */
 -      report->field[0]->value[2] = 0x00;
 -      report->field[0]->value[3] = 0x00;
 -      report->field[0]->value[4] = 0x00;
 -      report->field[0]->value[5] = 0x00;
 -      report->field[0]->value[6] = 0x00;
 +      value[0] = 0xf8;
 +      value[1] = 0x00;        /* Set later */
 +      value[2] = 0x00;
 +      value[3] = 0x00;
 +      value[4] = 0x00;
 +      value[5] = 0x00;
 +      value[6] = 0x00;
  
        if (range > 200) {
                report->field[0]->value[1] = 0x03;
        usbhid_submit_report(hid, report, USB_DIR_OUT);
  
        /* Prepare "fine" limit command */
 -      report->field[0]->value[0] = 0x81;
 -      report->field[0]->value[1] = 0x0b;
 -      report->field[0]->value[2] = 0x00;
 -      report->field[0]->value[3] = 0x00;
 -      report->field[0]->value[4] = 0x00;
 -      report->field[0]->value[5] = 0x00;
 -      report->field[0]->value[6] = 0x00;
 +      value[0] = 0x81;
 +      value[1] = 0x0b;
 +      value[2] = 0x00;
 +      value[3] = 0x00;
 +      value[4] = 0x00;
 +      value[5] = 0x00;
 +      value[6] = 0x00;
  
        if (range == 200 || range == 900) {     /* Do not apply any fine limit */
                usbhid_submit_report(hid, report, USB_DIR_OUT);
        start_left = (((full_range - range + 1) * 2047) / full_range);
        start_right = 0xfff - start_left;
  
 -      report->field[0]->value[2] = start_left >> 4;
 -      report->field[0]->value[3] = start_right >> 4;
 -      report->field[0]->value[4] = 0xff;
 -      report->field[0]->value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
 -      report->field[0]->value[6] = 0xff;
 +      value[2] = start_left >> 4;
 +      value[3] = start_right >> 4;
 +      value[4] = 0xff;
 +      value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
 +      value[6] = 0xff;
  
        usbhid_submit_report(hid, report, USB_DIR_OUT);
  }
@@@ -406,15 -344,14 +406,15 @@@ static void lg4ff_set_leds(struct hid_d
  {
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
 -
 -      report->field[0]->value[0] = 0xf8;
 -      report->field[0]->value[1] = 0x12;
 -      report->field[0]->value[2] = leds;
 -      report->field[0]->value[3] = 0x00;
 -      report->field[0]->value[4] = 0x00;
 -      report->field[0]->value[5] = 0x00;
 -      report->field[0]->value[6] = 0x00;
 +      __s32 *value = report->field[0]->value;
 +
 +      value[0] = 0xf8;
 +      value[1] = 0x12;
 +      value[2] = leds;
 +      value[3] = 0x00;
 +      value[4] = 0x00;
 +      value[5] = 0x00;
 +      value[6] = 0x00;
        usbhid_submit_report(hid, report, USB_DIR_OUT);
  }
  
@@@ -423,7 -360,7 +423,7 @@@ static void lg4ff_led_set_brightness(st
  {
        struct device *dev = led_cdev->dev->parent;
        struct hid_device *hid = container_of(dev, struct hid_device, dev);
-       struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+       struct lg_drv_data *drv_data = hid_get_drvdata(hid);
        struct lg4ff_device_entry *entry;
        int i, state = 0;
  
@@@ -458,7 -395,7 +458,7 @@@ static enum led_brightness lg4ff_led_ge
  {
        struct device *dev = led_cdev->dev->parent;
        struct hid_device *hid = container_of(dev, struct hid_device, dev);
-       struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+       struct lg_drv_data *drv_data = hid_get_drvdata(hid);
        struct lg4ff_device_entry *entry;
        int i, value = 0;
  
@@@ -564,7 -501,7 +564,7 @@@ int lg4ff_init(struct hid_device *hid
        /* Check if autocentering is available and
         * set the centering force to zero by default */
        if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
 -              if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN)  /* Formula Force EX expects different autocentering command */
 +              if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */
                        dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
                else
                        dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
        }
        drv_data->device_props = entry;
  
 +      entry->product_id = lg4ff_devices[i].product_id;
        entry->min_range = lg4ff_devices[i].min_range;
        entry->max_range = lg4ff_devices[i].max_range;
        entry->set_range = lg4ff_devices[i].set_range;
                return error;
        dbg_hid("sysfs interface created\n");
  
 +      /* Set default axes parameters */
 +      switch (lg4ff_devices[i].product_id) {
 +      case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
 +              dbg_hid("Setting axes parameters for Driving Force Pro\n");
 +              input_set_abs_params(dev, ABS_X, DFP_X_MIN, DFP_X_MAX, 0, 0);
 +              input_set_abs_params(dev, ABS_Y, DFP_PEDAL_MIN, DFP_PEDAL_MAX, 0, 0);
 +              input_set_abs_params(dev, ABS_RZ, DFP_PEDAL_MIN, DFP_PEDAL_MAX, 0, 0);
 +              break;
 +      default:
 +              break;
 +      }
 +
        /* Set the maximum range to start with */
        entry->range = entry->max_range;
        if (entry->set_range != NULL)
@@@ -670,8 -594,6 +670,8 @@@ out
        return 0;
  }
  
 +
 +
  int lg4ff_deinit(struct hid_device *hid)
  {
        struct lg4ff_device_entry *entry;
diff --combined drivers/hid/hid-wacom.c
index 75b970f116ee893d69068c9202e0693616063df5,a92d11690c1951a4e0205d1db8c03c6364723d38..2f60da9ed066539a5b4c2e479118ec0763a1b9f0
@@@ -5,7 -5,6 +5,6 @@@
   *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
   *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
   *  Copyright (c) 2006-2007 Jiri Kosina
-  *  Copyright (c) 2007 Paul Walmsley
   *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
   *  Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
   *  Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
@@@ -33,8 -32,6 +32,8 @@@
  #define PAD_DEVICE_ID 0x0F
  
  #define WAC_CMD_LED_CONTROL     0x20
 +#define WAC_CMD_ICON_START_STOP     0x21
 +#define WAC_CMD_ICON_TRANSFER       0x26
  
  struct wacom_data {
        __u16 tool;
@@@ -71,91 -68,6 +70,91 @@@ static enum power_supply_property wacom
        POWER_SUPPLY_PROP_SCOPE,
  };
  
 +static void wacom_scramble(__u8 *image)
 +{
 +      __u16 mask;
 +      __u16 s1;
 +      __u16 s2;
 +      __u16 r1 ;
 +      __u16 r2 ;
 +      __u16 r;
 +      __u8 buf[256];
 +      int i, w, x, y, z;
 +
 +      for (x = 0; x < 32; x++) {
 +              for (y = 0; y < 8; y++)
 +                      buf[(8 * x) + (7 - y)] = image[(8 * x) + y];
 +      }
 +
 +      /* Change 76543210 into GECA6420 as required by Intuos4 WL
 +       *        HGFEDCBA      HFDB7531
 +       */
 +      for (x = 0; x < 4; x++) {
 +              for (y = 0; y < 4; y++) {
 +                      for (z = 0; z < 8; z++) {
 +                              mask = 0x0001;
 +                              r1 = 0;
 +                              r2 = 0;
 +                              i = (x << 6) + (y << 4) + z;
 +                              s1 = buf[i];
 +                              s2 = buf[i+8];
 +                              for (w = 0; w < 8; w++) {
 +                                      r1 |= (s1 & mask);
 +                                      r2 |= (s2 & mask);
 +                                      s1 <<= 1;
 +                                      s2 <<= 1;
 +                                      mask <<= 2;
 +                              }
 +                              r = r1 | (r2 << 1);
 +                              i = (x << 6) + (y << 4) + (z << 1);
 +                              image[i] = 0xFF & r;
 +                              image[i+1] = (0xFF00 & r) >> 8;
 +                      }
 +              }
 +      }
 +}
 +
 +static void wacom_set_image(struct hid_device *hdev, const char *image,
 +                                              __u8 icon_no)
 +{
 +      __u8 rep_data[68];
 +      __u8 p[256];
 +      int ret, i, j;
 +
 +      for (i = 0; i < 256; i++)
 +              p[i] = image[i];
 +
 +      rep_data[0] = WAC_CMD_ICON_START_STOP;
 +      rep_data[1] = 0;
 +      ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
 +                              HID_FEATURE_REPORT);
 +      if (ret < 0)
 +              goto err;
 +
 +      rep_data[0] = WAC_CMD_ICON_TRANSFER;
 +      rep_data[1] = icon_no & 0x07;
 +
 +      wacom_scramble(p);
 +
 +      for (i = 0; i < 4; i++) {
 +              for (j = 0; j < 64; j++)
 +                      rep_data[j + 3] = p[(i << 6) + j];
 +
 +              rep_data[2] = i;
 +              ret = hdev->hid_output_raw_report(hdev, rep_data, 67,
 +                                      HID_FEATURE_REPORT);
 +      }
 +
 +      rep_data[0] = WAC_CMD_ICON_START_STOP;
 +      rep_data[1] = 0;
 +
 +      ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
 +                              HID_FEATURE_REPORT);
 +
 +err:
 +      return;
 +}
 +
  static void wacom_leds_set_brightness(struct led_classdev *led_dev,
                                                enum led_brightness value)
  {
        if (buf) {
                buf[0] = WAC_CMD_LED_CONTROL;
                buf[1] = led;
 -              buf[2] = value;
 +              buf[2] = value >> 2;
 +              buf[3] = value;
 +              /* use fixed brightness for OLEDs */
 +              buf[4] = 0x08;
                hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT);
                kfree(buf);
        }
@@@ -407,34 -316,6 +406,34 @@@ static ssize_t wacom_store_speed(struc
  static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
                wacom_show_speed, wacom_store_speed);
  
 +#define WACOM_STORE(OLED_ID)                                          \
 +static ssize_t wacom_oled##OLED_ID##_store(struct device *dev,                \
 +                              struct device_attribute *attr,          \
 +                              const char *buf, size_t count)          \
 +{                                                                     \
 +      struct hid_device *hdev = container_of(dev, struct hid_device,  \
 +                              dev);                                   \
 +                                                                      \
 +      if (count != 256)                                               \
 +              return -EINVAL;                                         \
 +                                                                      \
 +      wacom_set_image(hdev, buf, OLED_ID);                            \
 +                                                                      \
 +      return count;                                                   \
 +}                                                                     \
 +                                                                      \
 +static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL,      \
 +                              wacom_oled##OLED_ID##_store)
 +
 +WACOM_STORE(0);
 +WACOM_STORE(1);
 +WACOM_STORE(2);
 +WACOM_STORE(3);
 +WACOM_STORE(4);
 +WACOM_STORE(5);
 +WACOM_STORE(6);
 +WACOM_STORE(7);
 +
  static int wacom_gr_parse_report(struct hid_device *hdev,
                        struct wacom_data *wdata,
                        struct input_dev *input, unsigned char *data)
@@@ -835,33 -716,17 +834,33 @@@ static int wacom_probe(struct hid_devic
                hid_warn(hdev,
                         "can't create sysfs speed attribute err: %d\n", ret);
  
 +#define OLED_INIT(OLED_ID)                                            \
 +      do {                                                            \
 +              ret = device_create_file(&hdev->dev,                    \
 +                              &dev_attr_oled##OLED_ID##_img);         \
 +              if (ret)                                                \
 +                      hid_warn(hdev,                                  \
 +                       "can't create sysfs oled attribute, err: %d\n", ret);\
 +      } while (0)
 +
 +OLED_INIT(0);
 +OLED_INIT(1);
 +OLED_INIT(2);
 +OLED_INIT(3);
 +OLED_INIT(4);
 +OLED_INIT(5);
 +OLED_INIT(6);
 +OLED_INIT(7);
 +
        wdata->features = 0;
        wacom_set_features(hdev, 1);
  
        if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) {
                sprintf(hdev->name, "%s", "Wacom Intuos4 WL");
                ret = wacom_initialize_leds(hdev);
 -              if (ret) {
 +              if (ret)
                        hid_warn(hdev,
                                 "can't create led attribute, err: %d\n", ret);
 -                      goto destroy_leds;
 -              }
        }
  
        wdata->battery.properties = wacom_battery_props;
  
        ret = power_supply_register(&hdev->dev, &wdata->battery);
        if (ret) {
 -              hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
 -                       ret);
 +              hid_err(hdev, "can't create sysfs battery attribute, err: %d\n",
 +                      ret);
                goto err_battery;
        }
  
  
        ret = power_supply_register(&hdev->dev, &wdata->ac);
        if (ret) {
 -              hid_warn(hdev,
 -                       "can't create ac battery attribute, err: %d\n", ret);
 +              hid_err(hdev,
 +                      "can't create ac battery attribute, err: %d\n", ret);
                goto err_ac;
        }
  
  err_ac:
        power_supply_unregister(&wdata->battery);
  err_battery:
 +      wacom_destroy_leds(hdev);
 +      device_remove_file(&hdev->dev, &dev_attr_oled0_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled1_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled2_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled3_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled4_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled5_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled6_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled7_img);
        device_remove_file(&hdev->dev, &dev_attr_speed);
        hid_hw_stop(hdev);
 -destroy_leds:
 -      wacom_destroy_leds(hdev);
  err_free:
        kfree(wdata);
        return ret;
@@@ -922,14 -780,6 +921,14 @@@ static void wacom_remove(struct hid_dev
        struct wacom_data *wdata = hid_get_drvdata(hdev);
  
        wacom_destroy_leds(hdev);
 +      device_remove_file(&hdev->dev, &dev_attr_oled0_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled1_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled2_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled3_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled4_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled5_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled6_img);
 +      device_remove_file(&hdev->dev, &dev_attr_oled7_img);
        device_remove_file(&hdev->dev, &dev_attr_speed);
        hid_hw_stop(hdev);
  
diff --combined drivers/hid/hidraw.c
index c46c5f1037f4bfaed739e5ca9d164df326fbeb0b,7c47fc3f7b2b0b28f27021c75bb3b8d8f3771c4d..17d15bb610d15ac4b544e11af3007cd5b6357fd8
@@@ -42,7 -42,6 +42,7 @@@ static struct cdev hidraw_cdev
  static struct class *hidraw_class;
  static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
  static DEFINE_MUTEX(minors_lock);
 +static void drop_ref(struct hidraw *hid, int exists_bit);
  
  static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
  {
@@@ -114,7 -113,7 +114,7 @@@ static ssize_t hidraw_send_report(struc
        __u8 *buf;
        int ret = 0;
  
 -      if (!hidraw_table[minor]) {
 +      if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
                ret = -ENODEV;
                goto out;
        }
@@@ -262,7 -261,7 +262,7 @@@ static int hidraw_open(struct inode *in
        }
  
        mutex_lock(&minors_lock);
 -      if (!hidraw_table[minor]) {
 +      if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
                err = -ENODEV;
                goto out_unlock;
        }
@@@ -299,12 -298,36 +299,12 @@@ out
  static int hidraw_release(struct inode * inode, struct file * file)
  {
        unsigned int minor = iminor(inode);
 -      struct hidraw *dev;
        struct hidraw_list *list = file->private_data;
 -      int ret;
 -      int i;
 -
 -      mutex_lock(&minors_lock);
 -      if (!hidraw_table[minor]) {
 -              ret = -ENODEV;
 -              goto unlock;
 -      }
  
 +      drop_ref(hidraw_table[minor], 0);
        list_del(&list->node);
 -      dev = hidraw_table[minor];
 -      if (!--dev->open) {
 -              if (list->hidraw->exist) {
 -                      hid_hw_power(dev->hid, PM_HINT_NORMAL);
 -                      hid_hw_close(dev->hid);
 -              } else {
 -                      kfree(list->hidraw);
 -              }
 -      }
 -
 -      for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
 -              kfree(list->buffer[i].value);
        kfree(list);
 -      ret = 0;
 -unlock:
 -      mutex_unlock(&minors_lock);
 -
 -      return ret;
 +      return 0;
  }
  
  static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@@ -506,7 -529,21 +506,7 @@@ EXPORT_SYMBOL_GPL(hidraw_connect)
  void hidraw_disconnect(struct hid_device *hid)
  {
        struct hidraw *hidraw = hid->hidraw;
 -
 -      mutex_lock(&minors_lock);
 -      hidraw->exist = 0;
 -
 -      device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
 -
 -      hidraw_table[hidraw->minor] = NULL;
 -
 -      if (hidraw->open) {
 -              hid_hw_close(hid);
 -              wake_up_interruptible(&hidraw->wait);
 -      } else {
 -              kfree(hidraw);
 -      }
 -      mutex_unlock(&minors_lock);
 +      drop_ref(hidraw, 1);
  }
  EXPORT_SYMBOL_GPL(hidraw_disconnect);
  
@@@ -522,21 -559,28 +522,28 @@@ int __init hidraw_init(void
  
        if (result < 0) {
                pr_warn("can't get major number\n");
-               result = 0;
                goto out;
        }
  
        hidraw_class = class_create(THIS_MODULE, "hidraw");
        if (IS_ERR(hidraw_class)) {
                result = PTR_ERR(hidraw_class);
-               unregister_chrdev(hidraw_major, "hidraw");
-               goto out;
+               goto error_cdev;
        }
  
          cdev_init(&hidraw_cdev, &hidraw_ops);
-         cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
+       result = cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
+       if (result < 0)
+               goto error_class;
  out:
        return result;
+ error_class:
+       class_destroy(hidraw_class);
+ error_cdev:
+       unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
+       goto out;
  }
  
  void hidraw_exit(void)
        unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
  
  }
 +
 +static void drop_ref(struct hidraw *hidraw, int exists_bit)
 +{
 +      mutex_lock(&minors_lock);
 +      if (exists_bit) {
 +              hid_hw_close(hidraw->hid);
 +              hidraw->exist = 0;
 +              if (hidraw->open)
 +                      wake_up_interruptible(&hidraw->wait);
 +      } else {
 +              --hidraw->open;
 +      }
 +
 +      if (!hidraw->open && !hidraw->exist) {
 +              device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
 +              hidraw_table[hidraw->minor] = NULL;
 +              kfree(hidraw);
 +      }
 +      mutex_unlock(&minors_lock);
 +}
index 991e85c7325c849d4e7c287afe28364a8e3351e6,9af530e4555c519be2c54c3fb96f0d391363a3eb..11c7932dc7e6c5628f940d141b50366ca57008ad
@@@ -70,12 -70,12 +70,13 @@@ static const struct hid_blacklist 
        { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
 +      { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
-       { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },