]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
Merge branch 'for-4.17/multitouch' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Thu, 5 Apr 2018 11:19:57 +0000 (13:19 +0200)
committerJiri Kosina <jkosina@suse.cz>
Thu, 5 Apr 2018 11:27:22 +0000 (13:27 +0200)
Pull Razer Blade Stealth support improvement and a few generic cleanups

17 files changed:
Documentation/ABI/testing/sysfs-driver-hid-logitech-hidpp [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-hid-ntrig [new file with mode: 0644]
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-corsair.c
drivers/hid/hid-elan.c [new file with mode: 0644]
drivers/hid/hid-elecom.c
drivers/hid/hid-google-hammer.c [new file with mode: 0644]
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-quirks.c
drivers/hid/hid-rmi.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/wacom_sys.c
include/linux/hid.h

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-hidpp b/Documentation/ABI/testing/sysfs-driver-hid-logitech-hidpp
new file mode 100644 (file)
index 0000000..d8f831f
--- /dev/null
@@ -0,0 +1,19 @@
+What:          /sys/bus/hid/drivers/logitech-hidpp-device/<dev>/range
+Date:          Jan, 2016
+KernelVersion: 4.6
+Contact:       linux-input@vger.kernel.org
+Description:
+               (RW) This attribute controls the amount of 'turn' permitted in
+               Logitech G920 wheel. Reading from the file shows the current
+               range of the steering wheel. Writing a value within the min and
+               max boundary sets the range of the wheel.
+
+What:          /sys/bus/hid/drivers/logitech-hidpp-device/<dev>/builtin_power_supply
+Date:          Apr, 2017
+KernelVersion: 4.12
+Contact:       linux-input@vger.kernel.org
+Description:
+               Presence of this file indicates that HID++ driver is capable of
+               handling battery properties in the kernel. This way, upower can
+               add a udev rule to decide whether or not it should use the
+               internal unifying support or the generic kernel one.
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-ntrig b/Documentation/ABI/testing/sysfs-driver-hid-ntrig
new file mode 100644 (file)
index 0000000..e574a56
--- /dev/null
@@ -0,0 +1,70 @@
+What:          /sys/bus/hid/drivers/ntrig/<dev>/activate_slack
+Date:          May, 2010
+KernelVersion: 2.6.35
+Contact:       linux-input@vger.kernel.org
+Description:
+               (RW) Number of contact frames ignored before acknowledging the
+               start of activity (activating touch).
+
+
+What:          /sys/bus/hid/drivers/ntrig/<dev>/decativate_slack
+Date:          May, 2010
+KernelVersion: 2.6.35
+Contact:       linux-input@vger.kernel.org
+Description:
+               (RW) Number of empty (no contact) frames ignored before
+               acknowledging the end of activity (deactivating touch).
+
+               When the last finger is removed from the device, it sends a
+               number of empty frames. By holding off on deactivation for a few
+               frames false erroneous disconnects can be tolerated, where the
+               sensor may mistakenly not detect a finger that is still present.
+
+
+What:          /sys/bus/hid/drivers/ntrig/<dev>/activation_width
+What:          /sys/bus/hid/drivers/ntrig/<dev>/activation_height
+Date:          May, 2010
+KernelVersion: 2.6.35
+Contact:       linux-input@vger.kernel.org
+Description:
+               Threholds to override activation slack.
+
+               activation_width:       (RW) Width threshold to immediately
+                                       start processing touch events.
+
+               activation_height:      (RW) Height threshold to immediately
+                                       start processing touch events.
+
+
+What:          /sys/bus/hid/drivers/ntrig/<dev>/min_width
+What:          /sys/bus/hid/drivers/ntrig/<dev>/min_height
+Date:          May, 2010
+KernelVersion: 2.6.35
+Contact:       linux-input@vger.kernel.org
+Description:
+               Minimum size contact accepted.
+
+               min_width:      (RW) Minimum touch contact width to decide
+                               activation and activity.
+
+               min_height:     (RW) Minimum touch contact height to decide
+                               activation and activity.
+
+
+What:          /sys/bus/hid/drivers/ntrig/<dev>/sensor_physical_width
+What:          /sys/bus/hid/drivers/ntrig/<dev>/sensor_physical_height
+Date:          May, 2010
+KernelVersion: 2.6.35
+Contact:       linux-input@vger.kernel.org
+Description:
+               (RO) These are internal ranges not used for normal events but
+               useful for tuning.
+
+
+What:          /sys/bus/hid/drivers/ntrig/<dev>/sensor_logical_width
+What:          /sys/bus/hid/drivers/ntrig/<dev>/sensor_logical_height
+Date:          May, 2010
+KernelVersion: 2.6.35
+Contact:       linux-input@vger.kernel.org
+Description:
+               (RO) The range for positions reported during activity.
index 19c499f5623d776576a51a8da4ea13395f76d69a..60252fd796f6a86513b577f7b05cb3123ddeec81 100644 (file)
@@ -274,15 +274,23 @@ config HID_EMS_FF
        Currently the following devices are known to be supported:
         - Trio Linker Plus II
 
+config HID_ELAN
+       tristate "ELAN USB Touchpad Support"
+       depends on LEDS_CLASS && USB_HID
+       ---help---
+       Say Y to enable support for the USB ELAN touchpad
+       Currently the following devices are known to be supported:
+        - HP Pavilion X2 10-p0XX.
+
 config HID_ELECOM
        tristate "ELECOM HID devices"
        depends on HID
        ---help---
        Support for ELECOM devices:
          - BM084 Bluetooth Mouse
-         - EX-G Trackball (Wired and wireless)
-         - DEFT Trackball (Wired and wireless)
-         - HUGE Trackball (Wired and wireless)
+         - EX-G Trackballs (M-XT3DRBK, M-XT3URBK)
+         - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK)
+         - HUGE Trackballs (M-HT1DRBK, M-HT1URBK)
 
 config HID_ELO
        tristate "ELO USB 4000/4500 touchscreen"
@@ -331,6 +339,12 @@ config HOLTEK_FF
          Say Y here if you have a Holtek On Line Grip based game controller
          and want to have force feedback support for it.
 
+config HID_GOOGLE_HAMMER
+       tristate "Google Hammer Keyboard"
+       depends on USB_HID && LEDS_CLASS
+       ---help---
+       Say Y here if you have a Google Hammer device.
+
 config HID_GT683R
        tristate "MSI GT68xR LED support"
        depends on LEDS_CLASS && USB_HID
index eb13b9e92d8528d01f9e8581b6d92eaa76a5b5d5..17a8bd97da9dc29ad7146e79d12bcfcade911d7e 100644 (file)
@@ -39,11 +39,13 @@ obj-$(CONFIG_HID_CP2112)    += hid-cp2112.o
 obj-$(CONFIG_HID_CYPRESS)      += hid-cypress.o
 obj-$(CONFIG_HID_DRAGONRISE)   += hid-dr.o
 obj-$(CONFIG_HID_EMS_FF)       += hid-emsff.o
+obj-$(CONFIG_HID_ELAN)         += hid-elan.o
 obj-$(CONFIG_HID_ELECOM)       += hid-elecom.o
 obj-$(CONFIG_HID_ELO)          += hid-elo.o
 obj-$(CONFIG_HID_EZKEY)                += hid-ezkey.o
 obj-$(CONFIG_HID_GEMBIRD)      += hid-gembird.o
 obj-$(CONFIG_HID_GFRM)         += hid-gfrm.o
+obj-$(CONFIG_HID_GOOGLE_HAMMER)        += hid-google-hammer.o
 obj-$(CONFIG_HID_GT683R)       += hid-gt683r.o
 obj-$(CONFIG_HID_GYRATION)     += hid-gyration.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtek-kbd.o
index fdb8b6ed6d4cd9e03c6b3efacbb6a6b2ea6d7117..a40681d5a2a33c5b566af67dfda25e9634711c50 100644 (file)
@@ -1365,7 +1365,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
         * of implement() working on 8 byte chunks
         */
 
-       int len = hid_report_len(report) + 7;
+       u32 len = hid_report_len(report) + 7;
 
        return kmalloc(len, flags);
 }
@@ -1430,7 +1430,7 @@ void __hid_request(struct hid_device *hid, struct hid_report *report,
 {
        char *buf;
        int ret;
-       int len;
+       u32 len;
 
        buf = hid_alloc_report_buf(report, GFP_KERNEL);
        if (!buf)
@@ -1456,14 +1456,14 @@ out:
 }
 EXPORT_SYMBOL_GPL(__hid_request);
 
-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
                int interrupt)
 {
        struct hid_report_enum *report_enum = hid->report_enum + type;
        struct hid_report *report;
        struct hid_driver *hdrv;
        unsigned int a;
-       int rsize, csize = size;
+       u32 rsize, csize = size;
        u8 *cdata = data;
        int ret = 0;
 
@@ -1521,7 +1521,7 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
  *
  * This is data entry for lower layers.
  */
-int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
+int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int interrupt)
 {
        struct hid_report_enum *report_enum;
        struct hid_driver *hdrv;
index 9ba5d98a118042a52dc40b895c3b2e8df67c0b39..ec9e060ec46cc8ea381dfb70284e2c827eceee64 100644 (file)
@@ -2,11 +2,14 @@
  * HID driver for Corsair devices
  *
  * Supported devices:
+ *  - Vengeance K70 Keyboard
+ *  - K70 RAPIDFIRE Keyboard
  *  - Vengeance K90 Keyboard
  *  - Scimitar PRO RGB Gaming Mouse
  *
  * Copyright (c) 2015 Clement Vuchener
  * Copyright (c) 2017 Oscar Campos
+ * Copyright (c) 2017 Aaron Bottegal
  */
 
 /*
@@ -673,7 +676,7 @@ static int corsair_input_mapping(struct hid_device *dev,
 }
 
 /*
- * The report descriptor of Corsair Scimitar RGB Pro gaming mouse is
+ * The report descriptor of some of the Corsair gaming mice is
  * non parseable as they define two consecutive Logical Minimum for
  * the Usage Page (Consumer) in rdescs bytes 75 and 77 being 77 0x16
  * that should be obviousy 0x26 for Logical Magimum of 16 bits. This
@@ -681,7 +684,8 @@ static int corsair_input_mapping(struct hid_device *dev,
  * Minimum being larger than Logical Maximum.
  *
  * This driver fixes the report descriptor for:
- * - USB ID b1c:1b3e, sold as Scimitar RGB Pro Gaming mouse
+ * - USB ID 1b1c:1b34, sold as GLAIVE RGB Gaming mouse
+ * - USB ID 1b1c:1b3e, sold as Scimitar RGB Pro Gaming mouse
  */
 
 static __u8 *corsair_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -691,13 +695,14 @@ static __u8 *corsair_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 
        if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
                /*
-                * Corsair Scimitar RGB Pro report descriptor is broken and
-                * defines two different Logical Minimum for the Consumer
-                * Application. The byte 77 should be a 0x26 defining a 16
-                * bits integer for the Logical Maximum but it is a 0x16
+                * Corsair GLAIVE RGB and Scimitar RGB Pro report descriptor is
+                * broken and defines two different Logical Minimum for the
+                * Consumer Application. The byte 77 should be a 0x26 defining
+                * a 16 bits integer for the Logical Maximum but it is a 0x16
                 * instead (Logical Minimum)
                 */
                switch (hdev->product) {
+               case USB_DEVICE_ID_CORSAIR_GLAIVE_RGB:
                case USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB:
                        if (*rsize >= 172 && rdesc[75] == 0x15 && rdesc[77] == 0x16
                        && rdesc[78] == 0xff && rdesc[79] == 0x0f) {
@@ -715,8 +720,15 @@ static const struct hid_device_id corsair_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90),
                .driver_data = CORSAIR_USE_K90_MACRO |
                               CORSAIR_USE_K90_BACKLIGHT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,
+            USB_DEVICE_ID_CORSAIR_GLAIVE_RGB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,
             USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
+       /*
+        * Vengeance K70 and K70 RAPIDFIRE share product IDs.
+        */
+       { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,
+            USB_DEVICE_ID_CORSAIR_K70R) },
        {}
 };
 
diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c
new file mode 100644 (file)
index 0000000..803a725
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * HID Driver for ELAN Touchpad
+ *
+ * Currently only supports touchpad found on HP Pavilion X2 10
+ *
+ * Copyright (c) 2016 Alexandrov Stanislav <neko@nya.ai>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/hid.h>
+#include <linux/input/mt.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#define ELAN_SINGLE_FINGER     0x81
+#define ELAN_MT_FIRST_FINGER   0x82
+#define ELAN_MT_SECOND_FINGER  0x83
+#define ELAN_INPUT_REPORT_SIZE 8
+
+#define ELAN_MUTE_LED_REPORT   0xBC
+#define ELAN_LED_REPORT_SIZE   8
+
+struct elan_touchpad_settings {
+       u8 max_fingers;
+       u16 max_x;
+       u16 max_y;
+       u8 max_area_x;
+       u8 max_area_y;
+       u8 max_w;
+       int usb_bInterfaceNumber;
+};
+
+struct elan_drvdata {
+       struct input_dev *input;
+       u8 prev_report[ELAN_INPUT_REPORT_SIZE];
+       struct led_classdev mute_led;
+       u8 mute_led_state;
+       struct elan_touchpad_settings *settings;
+};
+
+static int is_not_elan_touchpad(struct hid_device *hdev)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+
+       return (intf->altsetting->desc.bInterfaceNumber != drvdata->settings->usb_bInterfaceNumber);
+}
+
+static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+                             struct hid_field *field, struct hid_usage *usage,
+                             unsigned long **bit, int *max)
+{
+       if (is_not_elan_touchpad(hdev))
+               return 0;
+
+       if (field->report->id == ELAN_SINGLE_FINGER ||
+           field->report->id == ELAN_MT_FIRST_FINGER ||
+           field->report->id == ELAN_MT_SECOND_FINGER)
+               return -1;
+
+       return 0;
+}
+
+static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
+{
+       int ret;
+       struct input_dev *input;
+       struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+
+       if (is_not_elan_touchpad(hdev))
+               return 0;
+
+       input = devm_input_allocate_device(&hdev->dev);
+       if (!input)
+               return -ENOMEM;
+
+       input->name = "Elan Touchpad";
+       input->phys = hdev->phys;
+       input->uniq = hdev->uniq;
+       input->id.bustype = hdev->bus;
+       input->id.vendor  = hdev->vendor;
+       input->id.product = hdev->product;
+       input->id.version = hdev->version;
+       input->dev.parent = &hdev->dev;
+
+       input_set_abs_params(input, ABS_MT_POSITION_X, 0,
+                            drvdata->settings->max_x, 0, 0);
+       input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
+                            drvdata->settings->max_y, 0, 0);
+       input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
+                            drvdata->settings->max_fingers, 0, 0);
+       input_set_abs_params(input, ABS_TOOL_WIDTH, 0,
+                            drvdata->settings->max_w, 0, 0);
+
+       __set_bit(BTN_LEFT, input->keybit);
+       __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+
+       ret = input_mt_init_slots(input, drvdata->settings->max_fingers,
+                                 INPUT_MT_POINTER);
+       if (ret) {
+               hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
+               return ret;
+       }
+
+       ret = input_register_device(input);
+       if (ret) {
+               hid_err(hdev, "Failed to register elan input device: %d\n",
+                       ret);
+               input_free_device(input);
+               return ret;
+       }
+
+       drvdata->input = input;
+
+       return 0;
+}
+
+static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
+                               unsigned int slot_num)
+{
+       struct input_dev *input = drvdata->input;
+       int x, y, w;
+
+       bool active = !!data;
+
+       input_mt_slot(input, slot_num);
+       input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
+       if (active) {
+               x = ((data[0] & 0xF0) << 4) | data[1];
+               y = drvdata->settings->max_y -
+                   (((data[0] & 0x07) << 8) | data[2]);
+               w = data[4];
+
+               input_report_abs(input, ABS_MT_POSITION_X, x);
+               input_report_abs(input, ABS_MT_POSITION_Y, y);
+               input_report_abs(input, ABS_TOOL_WIDTH, w);
+       }
+}
+
+static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
+{
+       int i;
+       struct input_dev *input = drvdata->input;
+
+       /*
+        * There is 3 types of reports: for single touch,
+        * for multitouch - first finger and for multitouch - second finger
+        *
+        * packet structure for ELAN_SINGLE_FINGER and ELAN_MT_FIRST_FINGER:
+        *
+        * byte 1: 1   0   0   0   0   0   0   1  // 0x81 or 0x82
+        * byte 2: 0   0   0   0   0   0   0   0  // looks like unused
+        * byte 3: f5  f4  f3  f2  f1  0   0   L
+        * byte 4: x12 x11 x10 x9  0?  y11 y10 y9
+        * byte 5: x8  x7  x6  x5  x4  x3  x2  x1
+        * byte 6: y8  y7  y6  y5  y4  y3  y2  y1
+        * byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
+        * byte 8: w8  w7  w6  w5  w4  w3  w2  w1
+        *
+        * packet structure for ELAN_MT_SECOND_FINGER:
+        *
+        * byte 1: 1   0   0   0   0   0   1   1  // 0x83
+        * byte 2: x12 x11 x10 x9  0   y11 y10 y9
+        * byte 3: x8  x7  x6  x5  x4  x3  x2  x1
+        * byte 4: y8  y7  y6  y5  y4  y3  y2  y1
+        * byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
+        * byte 6: w8  w7  w6  w5  w4  w3  w2  w1
+        * byte 7: 0   0   0   0   0   0   0   0
+        * byte 8: 0   0   0   0   0   0   0   0
+        *
+        * f5-f1: finger touch bits
+        * L: clickpad button
+        * sy / sx: not sure yet, but this looks like rectangular
+        * area for finger
+        * w: looks like finger width
+        */
+
+       if (data[0] == ELAN_SINGLE_FINGER) {
+               for (i = 0; i < drvdata->settings->max_fingers; i++) {
+                       if (data[2] & BIT(i + 3))
+                               elan_report_mt_slot(drvdata, data + 3, i);
+                       else
+                               elan_report_mt_slot(drvdata, NULL, i);
+               }
+               input_report_key(input, BTN_LEFT, data[2] & 0x01);
+       }
+       /*
+        * When touched with two fingers Elan touchpad will emit two HID reports
+        * first is ELAN_MT_FIRST_FINGER and second is ELAN_MT_SECOND_FINGER
+        * we will save ELAN_MT_FIRST_FINGER report and wait for
+        * ELAN_MT_SECOND_FINGER to finish multitouch
+        */
+       if (data[0] == ELAN_MT_FIRST_FINGER) {
+               memcpy(drvdata->prev_report, data,
+                      sizeof(drvdata->prev_report));
+               return;
+       }
+
+       if (data[0] == ELAN_MT_SECOND_FINGER) {
+               int first = 0;
+               u8 *prev_report = drvdata->prev_report;
+
+               if (prev_report[0] != ELAN_MT_FIRST_FINGER)
+                       return;
+
+               for (i = 0; i < drvdata->settings->max_fingers; i++) {
+                       if (prev_report[2] & BIT(i + 3)) {
+                               if (!first) {
+                                       first = 1;
+                                       elan_report_mt_slot(drvdata, prev_report + 3, i);
+                               } else {
+                                       elan_report_mt_slot(drvdata, data + 1, i);
+                               }
+                       } else {
+                               elan_report_mt_slot(drvdata, NULL, i);
+                       }
+               }
+               input_report_key(input, BTN_LEFT, prev_report[2] & 0x01);
+       }
+
+       input_mt_sync_frame(input);
+       input_sync(input);
+}
+
+static int elan_raw_event(struct hid_device *hdev,
+                         struct hid_report *report, u8 *data, int size)
+{
+       struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+
+       if (is_not_elan_touchpad(hdev))
+               return 0;
+
+       if (data[0] == ELAN_SINGLE_FINGER ||
+           data[0] == ELAN_MT_FIRST_FINGER ||
+           data[0] == ELAN_MT_SECOND_FINGER) {
+               if (size == ELAN_INPUT_REPORT_SIZE) {
+                       elan_report_input(drvdata, data);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int elan_start_multitouch(struct hid_device *hdev)
+{
+       int ret;
+
+       /*
+        * This byte sequence will enable multitouch mode and disable
+        * mouse emulation
+        */
+       const unsigned char buf[] = { 0x0D, 0x00, 0x03, 0x21, 0x00 };
+       unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
+
+       if (!dmabuf)
+               return -ENOMEM;
+
+       ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf),
+                                HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+       kfree(dmabuf);
+
+       if (ret != sizeof(buf)) {
+               hid_err(hdev, "Failed to start multitouch: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static enum led_brightness elan_mute_led_get_brigtness(struct led_classdev *led_cdev)
+{
+       struct device *dev = led_cdev->dev->parent;
+       struct hid_device *hdev = to_hid_device(dev);
+       struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+
+       return drvdata->mute_led_state;
+}
+
+static int elan_mute_led_set_brigtness(struct led_classdev *led_cdev,
+                                      enum led_brightness value)
+{
+       int ret;
+       u8 led_state;
+       struct device *dev = led_cdev->dev->parent;
+       struct hid_device *hdev = to_hid_device(dev);
+       struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+
+       unsigned char *dmabuf = kzalloc(ELAN_LED_REPORT_SIZE, GFP_KERNEL);
+
+       if (!dmabuf)
+               return -ENOMEM;
+
+       led_state = !!value;
+
+       dmabuf[0] = ELAN_MUTE_LED_REPORT;
+       dmabuf[1] = 0x02;
+       dmabuf[2] = led_state;
+
+       ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, ELAN_LED_REPORT_SIZE,
+                                HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+       kfree(dmabuf);
+
+       if (ret != ELAN_LED_REPORT_SIZE) {
+               hid_err(hdev, "Failed to set mute led brightness: %d\n", ret);
+               return ret;
+       }
+
+       drvdata->mute_led_state = led_state;
+       return 0;
+}
+
+static int elan_init_mute_led(struct hid_device *hdev)
+{
+       struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+       struct led_classdev *mute_led = &drvdata->mute_led;
+
+       mute_led->name = "elan:red:mute";
+       mute_led->brightness_get = elan_mute_led_get_brigtness;
+       mute_led->brightness_set_blocking = elan_mute_led_set_brigtness;
+       mute_led->max_brightness = LED_ON;
+       mute_led->dev = &hdev->dev;
+
+       return devm_led_classdev_register(&hdev->dev, mute_led);
+}
+
+static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+       struct elan_drvdata *drvdata;
+
+       drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
+
+       if (!drvdata)
+               return -ENOMEM;
+
+       drvdata->settings = (struct elan_touchpad_settings *)id->driver_data;
+       hid_set_drvdata(hdev, drvdata);
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               hid_err(hdev, "Hid Parse failed\n");
+               return ret;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               hid_err(hdev, "Hid hw start failed\n");
+               return ret;
+       }
+
+       if (is_not_elan_touchpad(hdev))
+               return 0;
+
+       if (!drvdata->input) {
+               hid_err(hdev, "Input device is not registred\n");
+               ret = -ENAVAIL;
+               goto err;
+       }
+
+       ret = elan_start_multitouch(hdev);
+       if (ret)
+               goto err;
+
+       ret = elan_init_mute_led(hdev);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       hid_hw_stop(hdev);
+       return ret;
+}
+
+static void elan_remove(struct hid_device *hdev)
+{
+       hid_hw_stop(hdev);
+}
+
+static const struct elan_touchpad_settings hp_x2_10_touchpad_data = {
+       .max_fingers = 5,
+       .max_x = 2930,
+       .max_y = 1250,
+       .max_area_x = 15,
+       .max_area_y = 15,
+       .max_w = 255,
+       .usb_bInterfaceNumber = 1,
+};
+
+static const struct hid_device_id elan_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
+               (kernel_ulong_t)&hp_x2_10_touchpad_data},
+       { }
+};
+
+MODULE_DEVICE_TABLE(hid, elan_devices);
+
+static struct hid_driver elan_driver = {
+       .name = "elan",
+       .id_table = elan_devices,
+       .input_mapping = elan_input_mapping,
+       .input_configured = elan_input_configured,
+       .raw_event = elan_raw_event,
+       .probe = elan_probe,
+       .remove = elan_remove,
+};
+
+module_hid_driver(elan_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexandrov Stanislav");
+MODULE_DESCRIPTION("Driver for HID ELAN Touchpads");
index 1a1ecc491c02d4a0f7eca9a095f7956e453ea51c..ae8e9413c79d55b5f80fab056757d8a1b2624313 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *  HID driver for ELECOM devices:
  *  - BM084 Bluetooth Mouse
- *  - EX-G Trackball (Wired and wireless)
- *  - DEFT Trackball (Wired and wireless)
- *  - HUGE Trackball (Wired and wireless)
+ *  - EX-G Trackballs (M-XT3DRBK, M-XT3URBK, M-XT4DRBK)
+ *  - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK)
+ *  - HUGE Trackballs (M-HT1DRBK, M-HT1URBK)
  *
  *  Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
  *  Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
@@ -65,14 +65,15 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        rdesc[47] = 0x00;
                }
                break;
-       case USB_DEVICE_ID_ELECOM_EX_G_WIRED:
-       case USB_DEVICE_ID_ELECOM_EX_G_WIRELESS:
+       case USB_DEVICE_ID_ELECOM_M_XT3URBK:
+       case USB_DEVICE_ID_ELECOM_M_XT3DRBK:
+       case USB_DEVICE_ID_ELECOM_M_XT4DRBK:
                mouse_button_fixup(hdev, rdesc, *rsize, 6);
                break;
-       case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
-       case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
-       case USB_DEVICE_ID_ELECOM_HUGE_WIRED:
-       case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS:
+       case USB_DEVICE_ID_ELECOM_M_DT1URBK:
+       case USB_DEVICE_ID_ELECOM_M_DT1DRBK:
+       case USB_DEVICE_ID_ELECOM_M_HT1URBK:
+       case USB_DEVICE_ID_ELECOM_M_HT1DRBK:
                mouse_button_fixup(hdev, rdesc, *rsize, 8);
                break;
        }
@@ -81,12 +82,13 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 
 static const struct hid_device_id elecom_devices[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRED) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRELESS) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, elecom_devices);
diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c
new file mode 100644 (file)
index 0000000..7b8e17b
--- /dev/null
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  HID driver for Google Hammer device.
+ *
+ *  Copyright (c) 2017 Google Inc.
+ *  Author: Wei-Ning Huang <wnhuang@google.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/hid.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define MAX_BRIGHTNESS 100
+
+/* HID usage for keyboard backlight (Alphanumeric display brightness) */
+#define HID_AD_BRIGHTNESS 0x00140046
+
+struct hammer_kbd_leds {
+       struct led_classdev cdev;
+       struct hid_device *hdev;
+       u8 buf[2] ____cacheline_aligned;
+};
+
+static int hammer_kbd_brightness_set_blocking(struct led_classdev *cdev,
+               enum led_brightness br)
+{
+       struct hammer_kbd_leds *led = container_of(cdev,
+                                                  struct hammer_kbd_leds,
+                                                  cdev);
+       int ret;
+
+       led->buf[0] = 0;
+       led->buf[1] = br;
+
+       /*
+        * Request USB HID device to be in Full On mode, so that sending
+        * hardware output report and hardware raw request won't fail.
+        */
+       ret = hid_hw_power(led->hdev, PM_HINT_FULLON);
+       if (ret < 0) {
+               hid_err(led->hdev, "failed: device not resumed %d\n", ret);
+               return ret;
+       }
+
+       ret = hid_hw_output_report(led->hdev, led->buf, sizeof(led->buf));
+       if (ret == -ENOSYS)
+               ret = hid_hw_raw_request(led->hdev, 0, led->buf,
+                                        sizeof(led->buf),
+                                        HID_OUTPUT_REPORT,
+                                        HID_REQ_SET_REPORT);
+       if (ret < 0)
+               hid_err(led->hdev, "failed to set keyboard backlight: %d\n",
+                       ret);
+
+       /* Request USB HID device back to Normal Mode. */
+       hid_hw_power(led->hdev, PM_HINT_NORMAL);
+
+       return ret;
+}
+
+static int hammer_register_leds(struct hid_device *hdev)
+{
+       struct hammer_kbd_leds *kbd_backlight;
+
+       kbd_backlight = devm_kzalloc(&hdev->dev,
+                                    sizeof(*kbd_backlight),
+                                    GFP_KERNEL);
+       if (!kbd_backlight)
+               return -ENOMEM;
+
+       kbd_backlight->hdev = hdev;
+       kbd_backlight->cdev.name = "hammer::kbd_backlight";
+       kbd_backlight->cdev.max_brightness = MAX_BRIGHTNESS;
+       kbd_backlight->cdev.brightness_set_blocking =
+               hammer_kbd_brightness_set_blocking;
+       kbd_backlight->cdev.flags = LED_HW_PLUGGABLE;
+
+       /* Set backlight to 0% initially. */
+       hammer_kbd_brightness_set_blocking(&kbd_backlight->cdev, 0);
+
+       return devm_led_classdev_register(&hdev->dev, &kbd_backlight->cdev);
+}
+
+static int hammer_input_configured(struct hid_device *hdev,
+                                  struct hid_input *hi)
+{
+       struct list_head *report_list =
+               &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct hid_report *report;
+
+       if (list_empty(report_list))
+               return 0;
+
+       report = list_first_entry(report_list, struct hid_report, list);
+
+       if (report->maxfield == 1 &&
+           report->field[0]->application == HID_GD_KEYBOARD &&
+           report->field[0]->maxusage == 1 &&
+           report->field[0]->usage[0].hid == HID_AD_BRIGHTNESS) {
+               int err = hammer_register_leds(hdev);
+
+               if (err)
+                       hid_warn(hdev,
+                               "Failed to register keyboard backlight: %d\n",
+                               err);
+       }
+
+       return 0;
+}
+
+static const struct hid_device_id hammer_devices[] = {
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WAND) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, hammer_devices);
+
+static struct hid_driver hammer_driver = {
+       .name = "hammer",
+       .id_table = hammer_devices,
+       .input_configured = hammer_input_configured,
+};
+module_hid_driver(hammer_driver);
+
+MODULE_LICENSE("GPL");
index 43ddcdfbd0da415b4fc397a89582290f3f37c786..18933074e59abb612b83dd186aef799fb21ddbd6 100644 (file)
 #define USB_DEVICE_ID_CORSAIR_K70RGB    0x1b13
 #define USB_DEVICE_ID_CORSAIR_STRAFE    0x1b15
 #define USB_DEVICE_ID_CORSAIR_K65RGB    0x1b17
+#define USB_DEVICE_ID_CORSAIR_GLAIVE_RGB        0x1b34
 #define USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE  0x1b38
 #define USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE  0x1b39
 #define USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB  0x1b3e
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001      0xa001
 
 #define USB_VENDOR_ID_ELAN             0x04f3
+#define USB_DEVICE_ID_HP_X2_10_COVER   0x0755
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
-#define USB_DEVICE_ID_ELECOM_EX_G_WIRED        0x00fb
-#define USB_DEVICE_ID_ELECOM_EX_G_WIRELESS     0x00fc
-#define USB_DEVICE_ID_ELECOM_DEFT_WIRED        0x00fe
-#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS     0x00ff
-#define USB_DEVICE_ID_ELECOM_HUGE_WIRED        0x010c
-#define USB_DEVICE_ID_ELECOM_HUGE_WIRELESS     0x010d
+#define USB_DEVICE_ID_ELECOM_M_XT3URBK 0x00fb
+#define USB_DEVICE_ID_ELECOM_M_XT3DRBK 0x00fc
+#define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd
+#define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe
+#define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff
+#define USB_DEVICE_ID_ELECOM_M_HT1URBK 0x010c
+#define USB_DEVICE_ID_ELECOM_M_HT1DRBK 0x010d
 
 #define USB_VENDOR_ID_DREAM_CHEEKY     0x1d34
 #define USB_DEVICE_ID_DREAM_CHEEKY_WN  0x0004
 #define USB_DEVICE_ID_GOODTOUCH_000f   0x000f
 
 #define USB_VENDOR_ID_GOOGLE           0x18d1
+#define USB_DEVICE_ID_GOOGLE_HAMMER    0x5022
 #define USB_DEVICE_ID_GOOGLE_TOUCH_ROSE        0x5028
+#define USB_DEVICE_ID_GOOGLE_STAFF     0x502b
+#define USB_DEVICE_ID_GOOGLE_WAND      0x502d
 
 #define USB_VENDOR_ID_GOTOP            0x08f2
 #define USB_DEVICE_ID_SUPER_Q2         0x007f
index b237b5590227b1e7142f025671a44d17c85acfa8..6836a856c243ab5c05ff7b1ff2f4af354fd34efb 100644 (file)
@@ -1368,7 +1368,8 @@ static void hidinput_led_worker(struct work_struct *work)
                                              led_work);
        struct hid_field *field;
        struct hid_report *report;
-       int len, ret;
+       int ret;
+       u32 len;
        __u8 *buf;
 
        field = hidinput_get_led_field(hid);
index 6ae2d14146b3b22eb50ff2a94bdfcb4b2ba41d56..ba32f0172030f8401a3b507d0f4fa8a0738d7218 100644 (file)
@@ -379,7 +379,8 @@ static const struct attribute_group mt_attribute_group = {
 
 static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
 {
-       int ret, size = hid_report_len(report);
+       int ret;
+       u32 size = hid_report_len(report);
        u8 *buf;
 
        /*
@@ -1187,7 +1188,7 @@ static void mt_set_input_mode(struct hid_device *hdev)
        struct hid_report_enum *re;
        struct mt_class *cls = &td->mtclass;
        char *buf;
-       int report_len;
+       u32 report_len;
 
        if (td->inputmode < 0)
                return;
index 5f6035a5ce367a947aa8fb773de8b39c5bd22bd7..0176a927070a858db1a985cb73b29016bd10cc02 100644 (file)
@@ -62,6 +62,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB), HID_QUIRK_NO_INIT_REPORTS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_GLAIVE_RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51), HID_QUIRK_NOGET },
@@ -317,6 +318,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 #endif
 #if IS_ENABLED(CONFIG_HID_CORSAIR)
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_GLAIVE_RGB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
 #endif
 #if IS_ENABLED(CONFIG_HID_CP2112)
@@ -333,14 +335,18 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
 #endif
+#if IS_ENABLED(CONFIG_HID_ELAN)
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER) },
+#endif
 #if IS_ENABLED(CONFIG_HID_ELECOM)
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRED) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRELESS) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
 #endif
 #if IS_ENABLED(CONFIG_HID_ELO)
        { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
index c6c05df3e8d207616745ada7ba7c1191ccfede03..9c93621496411695bb97326244271f39f39d6683 100644 (file)
@@ -89,8 +89,8 @@ struct rmi_data {
        u8 *writeReport;
        u8 *readReport;
 
-       int input_report_size;
-       int output_report_size;
+       u32 input_report_size;
+       u32 output_report_size;
 
        unsigned long flags;
 
index 7230243b94d30732f3ba5cf835ec929e99fcfe58..97689e98e53fbe9ba1ca80e2d8a9c34a42224026 100644 (file)
@@ -144,10 +144,10 @@ struct i2c_hid {
                                                   * register of the HID
                                                   * descriptor. */
        unsigned int            bufsize;        /* i2c buffer size */
-       char                    *inbuf;         /* Input buffer */
-       char                    *rawbuf;        /* Raw Input buffer */
-       char                    *cmdbuf;        /* Command buffer */
-       char                    *argsbuf;       /* Command arguments buffer */
+       u8                      *inbuf;         /* Input buffer */
+       u8                      *rawbuf;        /* Raw Input buffer */
+       u8                      *cmdbuf;        /* Command buffer */
+       u8                      *argsbuf;       /* Command arguments buffer */
 
        unsigned long           flags;          /* device flags */
        unsigned long           quirks;         /* Various quirks */
@@ -455,7 +455,8 @@ out_unlock:
 
 static void i2c_hid_get_input(struct i2c_hid *ihid)
 {
-       int ret, ret_size;
+       int ret;
+       u32 ret_size;
        int size = le16_to_cpu(ihid->hdesc.wMaxInputLength);
 
        if (size > ihid->bufsize)
@@ -480,7 +481,7 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
                return;
        }
 
-       if (ret_size > size) {
+       if ((ret_size > size) || (ret_size <= 2)) {
                dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
                        __func__, size, ret_size);
                return;
@@ -891,10 +892,10 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
 
 static void i2c_hid_acpi_fix_up_power(struct device *dev)
 {
-       acpi_handle handle = ACPI_HANDLE(dev);
        struct acpi_device *adev;
 
-       if (handle && acpi_bus_get_device(handle, &adev) == 0)
+       adev = ACPI_COMPANION(dev);
+       if (adev)
                acpi_device_fix_up_power(adev);
 }
 
index 409543160af77069e098c40f07b84ec51e7ff0ea..b54ef1ffcbec329b99520365a63bf347d16a66d2 100644 (file)
@@ -219,7 +219,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
        unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
        u8 *data;
        int ret;
-       int n;
+       u32 n;
 
        switch (equivalent_usage) {
        case HID_DG_CONTACTMAX:
@@ -519,7 +519,7 @@ static int wacom_set_device_mode(struct hid_device *hdev,
        u8 *rep_data;
        struct hid_report *r;
        struct hid_report_enum *re;
-       int length;
+       u32 length;
        int error = -ENOMEM, limit = 0;
 
        if (wacom_wac->mode_report < 0)
index b0db16fa709338002f2890b6ab138804a1f8101e..0f5cc64b2e5144ccce10e6954755ef758a45d38f 100644 (file)
@@ -852,7 +852,7 @@ extern int hidinput_connect(struct hid_device *hid, unsigned int force);
 extern void hidinput_disconnect(struct hid_device *);
 
 int hid_set_field(struct hid_field *, unsigned, __s32);
-int hid_input_report(struct hid_device *, int type, u8 *, int, int);
+int hid_input_report(struct hid_device *, int type, u8 *, u32, int);
 int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
 struct hid_field *hidinput_get_led_field(struct hid_device *hid);
 unsigned int hidinput_count_leds(struct hid_device *hid);
@@ -1103,13 +1103,13 @@ static inline void hid_hw_wait(struct hid_device *hdev)
  *
  * @report: the report we want to know the length
  */
-static inline int hid_report_len(struct hid_report *report)
+static inline u32 hid_report_len(struct hid_report *report)
 {
        /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
        return ((report->size - 1) >> 3) + 1 + (report->id > 0);
 }
 
-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
                int interrupt);
 
 /* HID quirks API */