summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt3
-rw-r--r--Documentation/devicetree/bindings/input/hid-over-i2c.txt16
-rw-r--r--Documentation/input/event-codes.txt5
-rw-r--r--drivers/hid/Kconfig29
-rw-r--r--drivers/hid/Makefile2
-rw-r--r--drivers/hid/hid-accutouch.c52
-rw-r--r--drivers/hid/hid-asus.c248
-rw-r--r--drivers/hid/hid-core.c10
-rw-r--r--drivers/hid/hid-cp2112.c4
-rw-r--r--drivers/hid/hid-debug.c2
-rw-r--r--drivers/hid/hid-ids.h14
-rw-r--r--drivers/hid/hid-input.c20
-rw-r--r--drivers/hid/hid-logitech-dj.c19
-rw-r--r--drivers/hid/hid-logitech-hidpp.c846
-rw-r--r--drivers/hid/hid-multitouch.c18
-rw-r--r--drivers/hid/hid-nti.c59
-rw-r--r--drivers/hid/hid-sony.c1674
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c105
-rw-r--r--drivers/hid/usbhid/hid-core.c45
-rw-r--r--drivers/hid/usbhid/hid-quirks.c15
-rw-r--r--drivers/hid/usbhid/hiddev.c24
-rw-r--r--drivers/hid/wacom.h5
-rw-r--r--drivers/hid/wacom_sys.c53
-rw-r--r--drivers/hid/wacom_wac.c306
-rw-r--r--drivers/hid/wacom_wac.h10
-rw-r--r--include/linux/hid.h5
-rw-r--r--include/linux/hiddev.h12
-rw-r--r--include/linux/i2c/i2c-hid.h6
-rw-r--r--include/uapi/linux/input-event-codes.h1
-rw-r--r--include/uapi/linux/input.h11
30 files changed, 2490 insertions, 1129 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 8d676d2a48ac..e4c9e0e46b95 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4127,6 +4127,9 @@
usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at.
+ usbhid.jspoll=
+ [USBHID] The interval which joysticks are to be polled at.
+
usb-storage.delay_use=
[UMS] The delay in seconds before a new device is
scanned for Logical Units (default 1).
diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.txt b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
index 488edcb264c4..28e8bd8b7d64 100644
--- a/Documentation/devicetree/bindings/input/hid-over-i2c.txt
+++ b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
@@ -17,6 +17,22 @@ Required properties:
- interrupt-parent: the phandle for the interrupt controller
- interrupts: interrupt line
+Additional optional properties:
+
+Some devices may support additional optional properties to help with, e.g.,
+power sequencing. The following properties can be supported by one or more
+device-specific compatible properties, which should be used in addition to the
+"hid-over-i2c" string.
+
+- compatible:
+ * "wacom,w9013" (Wacom W9013 digitizer). Supports:
+ - vdd-supply
+ - post-power-on-delay-ms
+
+- vdd-supply: phandle of the regulator that provides the supply voltage.
+- post-power-on-delay-ms: time required by the device after enabling its regulators
+ before it is ready for communication. Must be used with 'vdd-supply'.
+
Example:
i2c-hid-dev@2c {
diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt
index 36ea940e5bb9..575415f4cef0 100644
--- a/Documentation/input/event-codes.txt
+++ b/Documentation/input/event-codes.txt
@@ -301,7 +301,10 @@ them as any other INPUT_PROP_BUTTONPAD device.
INPUT_PROP_ACCELEROMETER
-------------------------
Directional axes on this device (absolute and/or relative x, y, z) represent
-accelerometer data. All other axes retain their meaning. A device must not mix
+accelerometer data. Some devices also report gyroscope data, which devices
+can report through the rotational axes (absolute and/or relative rx, ry, rz).
+
+All other axes retain their meaning. A device must not mix
regular directional axes and accelerometer axes on the same event node.
Guidelines:
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8c54cb8f5d6d..fe40e5e499dd 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -98,6 +98,18 @@ config HID_A4TECH
---help---
Support for A4 tech X5 and WOP-35 / Trust 450L mice.
+config HID_ACCUTOUCH
+ tristate "Accutouch touch device"
+ depends on USB_HID
+ ---help---
+ This selects a driver for the Accutouch 2216 touch controller.
+
+ The driver works around a problem in the reported device capabilities
+ which causes userspace to detect the device as a mouse rather than
+ a touchscreen.
+
+ Say Y here if you have a Accutouch 2216 touch controller.
+
config HID_ACRUX
tristate "ACRUX game controller support"
depends on HID
@@ -136,13 +148,16 @@ config HID_APPLEIR
config HID_ASUS
tristate "Asus"
- depends on I2C_HID
+ depends on LEDS_CLASS
---help---
- Support for Asus notebook built-in keyboard and touchpad via i2c.
+ Support for Asus notebook built-in keyboard and touchpad via i2c, and
+ the Asus Republic of Gamers laptop keyboard special keys.
Supported devices:
- EeeBook X205TA
- VivoBook E200HA
+ - GL553V series
+ - GL753V series
config HID_AUREAL
tristate "Aureal"
@@ -215,7 +230,8 @@ config HID_CMEDIA
config HID_CP2112
tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
- depends on USB_HID && I2C && GPIOLIB && GPIOLIB_IRQCHIP
+ depends on USB_HID && I2C && GPIOLIB
+ select GPIOLIB_IRQCHIP
---help---
Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge.
This is a HID device driver which registers as an i2c adapter
@@ -441,6 +457,7 @@ config HID_LOGITECH_DJ
config HID_LOGITECH_HIDPP
tristate "Logitech HID++ devices support"
depends on HID_LOGITECH
+ select POWER_SUPPLY
---help---
Support for Logitech devices relyingon the HID++ Logitech specification
@@ -581,6 +598,12 @@ config HID_MULTITOUCH
To compile this driver as a module, choose M here: the
module will be called hid-multitouch.
+config HID_NTI
+ tristate "NTI keyboard adapters"
+ ---help---
+ Support for the "extra" Sun keyboard keys on keyboards attached
+ through Network Technologies USB-SUN keyboard adapters.
+
config HID_NTRIG
tristate "N-Trig touch screen"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 4d111f23e801..fef027bc7fa3 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -21,6 +21,7 @@ hid-wiimote-y := hid-wiimote-core.o hid-wiimote-modules.o
hid-wiimote-$(CONFIG_DEBUG_FS) += hid-wiimote-debug.o
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
+obj-$(CONFIG_HID_ACCUTOUCH) += hid-accutouch.o
obj-$(CONFIG_HID_ALPS) += hid-alps.o
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o
@@ -62,6 +63,7 @@ obj-$(CONFIG_HID_MAYFLASH) += hid-mf.o
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o
+obj-$(CONFIG_HID_NTI) += hid-nti.o
obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
obj-$(CONFIG_HID_ORTEK) += hid-ortek.o
obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o
diff --git a/drivers/hid/hid-accutouch.c b/drivers/hid/hid-accutouch.c
new file mode 100644
index 000000000000..4e287160c50a
--- /dev/null
+++ b/drivers/hid/hid-accutouch.c
@@ -0,0 +1,52 @@
+/*
+ * HID driver for Elo Accutouch touchscreens
+ *
+ * Copyright (c) 2016, Collabora Ltd.
+ * Copyright (c) 2016, General Electric Company
+ *
+ * based on hid-penmount.c
+ * Copyright (c) 2014 Christian Gmeiner <christian.gmeiner <at> gmail.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/module.h>
+#include "hid-ids.h"
+
+static int accutouch_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi,
+ struct hid_field *field,
+ struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
+ hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+ return 1;
+ }
+
+ return 0;
+}
+
+static const struct hid_device_id accutouch_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, accutouch_devices);
+
+static struct hid_driver accutouch_driver = {
+ .name = "hid-accutouch",
+ .id_table = accutouch_devices,
+ .input_mapping = accutouch_input_mapping,
+};
+
+module_hid_driver(accutouch_driver);
+
+MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk");
+MODULE_DESCRIPTION("Elo Accutouch HID TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 70b12f89a193..16df6cc90235 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -40,8 +40,12 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define FEATURE_REPORT_ID 0x0d
#define INPUT_REPORT_ID 0x5d
+#define FEATURE_KBD_REPORT_ID 0x5a
#define INPUT_REPORT_SIZE 28
+#define FEATURE_KBD_REPORT_SIZE 16
+
+#define SUPPORT_KBD_BACKLIGHT BIT(0)
#define MAX_CONTACTS 5
@@ -63,18 +67,31 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define QUIRK_NO_INIT_REPORTS BIT(1)
#define QUIRK_SKIP_INPUT_MAPPING BIT(2)
#define QUIRK_IS_MULTITOUCH BIT(3)
+#define QUIRK_NO_CONSUMER_USAGES BIT(4)
+#define QUIRK_USE_KBD_BACKLIGHT BIT(5)
-#define KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
- QUIRK_NO_INIT_REPORTS)
-#define TOUCHPAD_QUIRKS (QUIRK_NO_INIT_REPORTS | \
+#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
+ QUIRK_NO_INIT_REPORTS | \
+ QUIRK_NO_CONSUMER_USAGES)
+#define I2C_TOUCHPAD_QUIRKS (QUIRK_NO_INIT_REPORTS | \
QUIRK_SKIP_INPUT_MAPPING | \
QUIRK_IS_MULTITOUCH)
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
+struct asus_kbd_leds {
+ struct led_classdev cdev;
+ struct hid_device *hdev;
+ struct work_struct work;
+ unsigned int brightness;
+ bool removed;
+};
+
struct asus_drvdata {
unsigned long quirks;
struct input_dev *input;
+ struct asus_kbd_leds *kbd_backlight;
+ bool enable_backlight;
};
static void asus_report_contact_down(struct input_dev *input,
@@ -169,6 +186,148 @@ static int asus_raw_event(struct hid_device *hdev,
return 0;
}
+static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size)
+{
+ unsigned char *dmabuf;
+ int ret;
+
+ dmabuf = kmemdup(buf, buf_size, GFP_KERNEL);
+ if (!dmabuf)
+ return -ENOMEM;
+
+ ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, dmabuf,
+ buf_size, HID_FEATURE_REPORT,
+ HID_REQ_SET_REPORT);
+ kfree(dmabuf);
+
+ return ret;
+}
+
+static int asus_kbd_init(struct hid_device *hdev)
+{
+ u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
+ 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
+ int ret;
+
+ ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
+ if (ret < 0)
+ hid_err(hdev, "Asus failed to send init command: %d\n", ret);
+
+ return ret;
+}
+
+static int asus_kbd_get_functions(struct hid_device *hdev,
+ unsigned char *kbd_func)
+{
+ u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
+ u8 *readbuf;
+ int ret;
+
+ ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
+ if (ret < 0) {
+ hid_err(hdev, "Asus failed to send configuration command: %d\n", ret);
+ return ret;
+ }
+
+ readbuf = kzalloc(FEATURE_KBD_REPORT_SIZE, GFP_KERNEL);
+ if (!readbuf)
+ return -ENOMEM;
+
+ ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, readbuf,
+ FEATURE_KBD_REPORT_SIZE, HID_FEATURE_REPORT,
+ HID_REQ_GET_REPORT);
+ if (ret < 0) {
+ hid_err(hdev, "Asus failed to request functions: %d\n", ret);
+ kfree(readbuf);
+ return ret;
+ }
+
+ *kbd_func = readbuf[6];
+
+ kfree(readbuf);
+ return ret;
+}
+
+static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
+ cdev);
+ if (led->brightness == brightness)
+ return;
+
+ led->brightness = brightness;
+ schedule_work(&led->work);
+}
+
+static enum led_brightness asus_kbd_backlight_get(struct led_classdev *led_cdev)
+{
+ struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
+ cdev);
+
+ return led->brightness;
+}
+
+static void asus_kbd_backlight_work(struct work_struct *work)
+{
+ struct asus_kbd_leds *led = container_of(work, struct asus_kbd_leds, work);
+ u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4, 0x00 };
+ int ret;
+
+ if (led->removed)
+ return;
+
+ buf[4] = led->brightness;
+
+ ret = asus_kbd_set_report(led->hdev, buf, sizeof(buf));
+ if (ret < 0)
+ hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret);
+}
+
+static int asus_kbd_register_leds(struct hid_device *hdev)
+{
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+ unsigned char kbd_func;
+ int ret;
+
+ /* Initialize keyboard */
+ ret = asus_kbd_init(hdev);
+ if (ret < 0)
+ return ret;
+
+ /* Get keyboard functions */
+ ret = asus_kbd_get_functions(hdev, &kbd_func);
+ if (ret < 0)
+ return ret;
+
+ /* Check for backlight support */
+ if (!(kbd_func & SUPPORT_KBD_BACKLIGHT))
+ return -ENODEV;
+
+ drvdata->kbd_backlight = devm_kzalloc(&hdev->dev,
+ sizeof(struct asus_kbd_leds),
+ GFP_KERNEL);
+ if (!drvdata->kbd_backlight)
+ return -ENOMEM;
+
+ drvdata->kbd_backlight->removed = false;
+ drvdata->kbd_backlight->brightness = 0;
+ drvdata->kbd_backlight->hdev = hdev;
+ drvdata->kbd_backlight->cdev.name = "asus::kbd_backlight";
+ drvdata->kbd_backlight->cdev.max_brightness = 3;
+ drvdata->kbd_backlight->cdev.brightness_set = asus_kbd_backlight_set;
+ drvdata->kbd_backlight->cdev.brightness_get = asus_kbd_backlight_get;
+ INIT_WORK(&drvdata->kbd_backlight->work, asus_kbd_backlight_work);
+
+ ret = devm_led_classdev_register(&hdev->dev, &drvdata->kbd_backlight->cdev);
+ if (ret < 0) {
+ /* No need to have this still around */
+ devm_kfree(&hdev->dev, drvdata->kbd_backlight);
+ }
+
+ return ret;
+}
+
static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct input_dev *input = hi->input;
@@ -196,9 +355,14 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
drvdata->input = input;
+ if (drvdata->enable_backlight && asus_kbd_register_leds(hdev))
+ hid_warn(hdev, "Failed to initialize backlight.\n");
+
return 0;
}
+#define asus_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, \
+ max, EV_KEY, (c))
static int asus_input_mapping(struct hid_device *hdev,
struct hid_input *hi, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit,
@@ -213,6 +377,65 @@ static int asus_input_mapping(struct hid_device *hdev,
return -1;
}
+ /* ASUS-specific keyboard hotkeys */
+ if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) {
+ set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN); break;
+ case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP); break;
+ case 0x35: asus_map_key_clear(KEY_DISPLAY_OFF); break;
+ case 0x6c: asus_map_key_clear(KEY_SLEEP); break;
+ case 0x82: asus_map_key_clear(KEY_CAMERA); break;
+ case 0x88: asus_map_key_clear(KEY_RFKILL); break;
+ case 0xb5: asus_map_key_clear(KEY_CALC); break;
+ case 0xc4: asus_map_key_clear(KEY_KBDILLUMUP); break;
+ case 0xc5: asus_map_key_clear(KEY_KBDILLUMDOWN); break;
+
+ /* ASUS touchpad toggle */
+ case 0x6b: asus_map_key_clear(KEY_F21); break;
+
+ /* ROG key */
+ case 0x38: asus_map_key_clear(KEY_PROG1); break;
+
+ /* Fn+C ASUS Splendid */
+ case 0xba: asus_map_key_clear(KEY_PROG2); break;
+
+ /* Fn+Space Power4Gear Hybrid */
+ case 0x5c: asus_map_key_clear(KEY_PROG3); break;
+
+ default:
+ /* ASUS lazily declares 256 usages, ignore the rest,
+ * as some make the keyboard appear as a pointer device. */
+ return -1;
+ }
+
+ /*
+ * Check and enable backlight only on devices with UsagePage ==
+ * 0xff31 to avoid initializing the keyboard firmware multiple
+ * times on devices with multiple HID descriptors but same
+ * PID/VID.
+ */
+ if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT)
+ drvdata->enable_backlight = true;
+
+ return 1;
+ }
+
+ if (drvdata->quirks & QUIRK_NO_CONSUMER_USAGES &&
+ (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
+ switch (usage->hid & HID_USAGE) {
+ case 0xe2: /* Mute */
+ case 0xe9: /* Volume up */
+ case 0xea: /* Volume down */
+ return 0;
+ default:
+ /* Ignore dummy Consumer usages which make the
+ * keyboard incorrectly appear as a pointer device.
+ */
+ return -1;
+ }
+ }
+
return 0;
}
@@ -305,6 +528,16 @@ err_stop_hw:
return ret;
}
+static void asus_remove(struct hid_device *hdev)
+{
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+
+ if (drvdata->kbd_backlight) {
+ drvdata->kbd_backlight->removed = true;
+ cancel_work_sync(&drvdata->kbd_backlight->work);
+ }
+}
+
static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
@@ -320,9 +553,13 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
static const struct hid_device_id asus_devices[] = {
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
- USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD), KEYBOARD_QUIRKS},
+ USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD), I2C_KEYBOARD_QUIRKS},
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
- USB_DEVICE_ID_ASUSTEK_TOUCHPAD), TOUCHPAD_QUIRKS },
+ USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD), I2C_TOUCHPAD_QUIRKS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT },
{ }
};
MODULE_DEVICE_TABLE(hid, asus_devices);
@@ -332,6 +569,7 @@ static struct hid_driver asus_driver = {
.id_table = asus_devices,
.report_fixup = asus_report_fixup,
.probe = asus_probe,
+ .remove = asus_remove,
.input_mapping = asus_input_mapping,
.input_configured = asus_input_configured,
#ifdef CONFIG_PM
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index d162f0dc76e3..37084b645785 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1694,7 +1694,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
len += sprintf(buf + len, "input");
if (hdev->claimed & HID_CLAIMED_HIDDEV)
len += sprintf(buf + len, "%shiddev%d", len ? "," : "",
- hdev->minor);
+ ((struct hiddev *)hdev->hiddev)->minor);
if (hdev->claimed & HID_CLAIMED_HIDRAW)
len += sprintf(buf + len, "%shidraw%d", len ? "," : "",
((struct hidraw *)hdev->hidraw)->minor);
@@ -1851,8 +1851,10 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
- { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) },
- { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_TOUCHPAD) },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
@@ -1891,6 +1893,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
@@ -1991,6 +1994,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTI, USB_DEVICE_ID_USB_SUN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index b22d0f83f8e3..078026f63b6f 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -27,6 +27,7 @@
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/hid.h>
+#include <linux/hidraw.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/nls.h>
@@ -1297,7 +1298,8 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
dev->adap.algo_data = dev;
dev->adap.dev.parent = &hdev->dev;
snprintf(dev->adap.name, sizeof(dev->adap.name),
- "CP2112 SMBus Bridge on hiddev%d", hdev->minor);
+ "CP2112 SMBus Bridge on hidraw%d",
+ ((struct hidraw *)hdev->hidraw)->minor);
dev->hwversion = buf[2];
init_waitqueue_head(&dev->wait);
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index c6c9c51c806f..5271db593478 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -140,9 +140,11 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x03, "LightPen"},
{0, 0x04, "TouchScreen"},
{0, 0x05, "TouchPad"},
+ {0, 0x0e, "DeviceConfiguration"},
{0, 0x20, "Stylus"},
{0, 0x21, "Puck"},
{0, 0x22, "Finger"},
+ {0, 0x23, "DeviceSettings"},
{0, 0x30, "TipPressure"},
{0, 0x31, "BarrelPressure"},
{0, 0x32, "InRange"},
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index b26c030926c1..643390ba749d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -173,8 +173,10 @@
#define USB_VENDOR_ID_ASUSTEK 0x0b05
#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726
#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b
-#define USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD 0x8585
-#define USB_DEVICE_ID_ASUSTEK_TOUCHPAD 0x0101
+#define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585
+#define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101
+#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854
+#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2 0x1837
#define USB_VENDOR_ID_ATEN 0x0557
#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
@@ -184,6 +186,7 @@
#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208
#define USB_DEVICE_ID_ATEN_CS682 0x2213
#define USB_DEVICE_ID_ATEN_CS692 0x8021
+#define USB_DEVICE_ID_ATEN_CS1758 0x2220
#define USB_VENDOR_ID_ATMEL 0x03eb
#define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c
@@ -366,6 +369,7 @@
#define USB_VENDOR_ID_ELO 0x04E7
#define USB_DEVICE_ID_ELO_TS2515 0x0022
#define USB_DEVICE_ID_ELO_TS2700 0x0020
+#define USB_DEVICE_ID_ELO_ACCUTOUCH_2216 0x0050
#define USB_VENDOR_ID_EMS 0x2006
#define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
@@ -548,6 +552,9 @@
#define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615
#define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070
+#define USB_VENDOR_ID_INNOMEDIA 0x1292
+#define USB_DEVICE_ID_INNEX_GENESIS_ATARI 0x4745
+
#define USB_VENDOR_ID_ITE 0x048d
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
@@ -771,6 +778,9 @@
#define USB_DEVICE_ID_NOVATEK_PCT 0x0600
#define USB_DEVICE_ID_NOVATEK_MOUSE 0x1602
+#define USB_VENDOR_ID_NTI 0x0757
+#define USB_DEVICE_ID_USB_SUN 0x0a00
+
#define USB_VENDOR_ID_NTRIG 0x1b96
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index d05f903c7614..a1ebdd7d4d4d 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1150,18 +1150,26 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
/*
* Ignore out-of-range values as per HID specification,
- * section 5.10 and 6.2.25.
+ * section 5.10 and 6.2.25, when NULL state bit is present.
+ * When it's not, clamp the value to match Microsoft's input
+ * driver as mentioned in "Required HID usages for digitizers":
+ * https://msdn.microsoft.com/en-us/library/windows/hardware/dn672278(v=vs.85).asp
*
* The logical_minimum < logical_maximum check is done so that we
* don't unintentionally discard values sent by devices which
* don't specify logical min and max.
*/
if ((field->flags & HID_MAIN_ITEM_VARIABLE) &&
- (field->logical_minimum < field->logical_maximum) &&
- (value < field->logical_minimum ||
- value > field->logical_maximum)) {
- dbg_hid("Ignoring out-of-range value %x\n", value);
- return;
+ (field->logical_minimum < field->logical_maximum)) {
+ if (field->flags & HID_MAIN_ITEM_NULL_STATE &&
+ (value < field->logical_minimum ||
+ value > field->logical_maximum)) {
+ dbg_hid("Ignoring out-of-range value %x\n", value);
+ return;
+ }
+ value = clamp(value,
+ field->logical_minimum,
+ field->logical_maximum);
}
/*
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 5bc6d80d5be7..826fa1e1c8d9 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -692,8 +692,12 @@ static void logi_dj_ll_close(struct hid_device *hid)
dbg_hid("%s:%s\n", __func__, hid->phys);
}
-static u8 unifying_name_query[] = {0x10, 0xff, 0x83, 0xb5, 0x40, 0x00, 0x00};
-static u8 unifying_name_answer[] = {0x11, 0xff, 0x83, 0xb5};
+/*
+ * Register 0xB5 is "pairing information". It is solely intended for the
+ * receiver, so do not overwrite the device index.
+ */
+static u8 unifying_pairing_query[] = {0x10, 0xff, 0x83, 0xb5};
+static u8 unifying_pairing_answer[] = {0x11, 0xff, 0x83, 0xb5};
static int logi_dj_ll_raw_request(struct hid_device *hid,
unsigned char reportnum, __u8 *buf,
@@ -712,9 +716,9 @@ static int logi_dj_ll_raw_request(struct hid_device *hid,
/* special case where we should not overwrite
* the device_index */
- if (count == 7 && !memcmp(buf, unifying_name_query,
- sizeof(unifying_name_query)))
- buf[4] |= djdev->device_index - 1;
+ if (count == 7 && !memcmp(buf, unifying_pairing_query,
+ sizeof(unifying_pairing_query)))
+ buf[4] = (buf[4] & 0xf0) | (djdev->device_index - 1);
else
buf[1] = djdev->device_index;
return hid_hw_raw_request(djrcv_dev->hdev, reportnum, buf,
@@ -911,9 +915,8 @@ static int logi_dj_hidpp_event(struct hid_device *hdev,
/* special case were the device wants to know its unifying
* name */
if (size == HIDPP_REPORT_LONG_LENGTH &&
- !memcmp(data, unifying_name_answer,
- sizeof(unifying_name_answer)) &&
- ((data[4] & 0xF0) == 0x40))
+ !memcmp(data, unifying_pairing_answer,
+ sizeof(unifying_pairing_answer)))
device_index = (data[4] & 0x0F) + 1;
else
return false;
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 2e2515a4c070..41b39464ded8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -56,15 +56,21 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_QUIRK_CLASS_M560 BIT(1)
#define HIDPP_QUIRK_CLASS_K400 BIT(2)
#define HIDPP_QUIRK_CLASS_G920 BIT(3)
+#define HIDPP_QUIRK_CLASS_K750 BIT(4)
/* bits 2..20 are reserved for classes */
-#define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
+/* #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21) disabled */
#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
+#define HIDPP_QUIRK_UNIFYING BIT(25)
-#define HIDPP_QUIRK_DELAYED_INIT (HIDPP_QUIRK_NO_HIDINPUT | \
- HIDPP_QUIRK_CONNECT_EVENTS)
+#define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT
+
+#define HIDPP_CAPABILITY_HIDPP10_BATTERY BIT(0)
+#define HIDPP_CAPABILITY_HIDPP20_BATTERY BIT(1)
+#define HIDPP_CAPABILITY_BATTERY_MILEAGE BIT(2)
+#define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS BIT(3)
/*
* There are two hidpp protocols in use, the first version hidpp10 is known
@@ -110,6 +116,18 @@ struct hidpp_report {
};
} __packed;
+struct hidpp_battery {
+ u8 feature_index;
+ u8 solar_feature_index;
+ struct power_supply_desc desc;
+ struct power_supply *ps;
+ char name[64];
+ int status;
+ int capacity;
+ int level;
+ bool online;
+};
+
struct hidpp_device {
struct hid_device *hid_dev;
struct mutex send_mutex;
@@ -128,8 +146,10 @@ struct hidpp_device {
struct input_dev *delayed_input;
unsigned long quirks;
-};
+ unsigned long capabilities;
+ struct hidpp_battery battery;
+};
/* HID++ 1.0 error codes */
#define HIDPP_ERROR 0x8f
@@ -380,15 +400,220 @@ static void hidpp_prefix_name(char **name, int name_length)
#define HIDPP_SET_LONG_REGISTER 0x82
#define HIDPP_GET_LONG_REGISTER 0x83
+#define HIDPP_REG_GENERAL 0x00
+
+static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev)
+{
+ struct hidpp_report response;
+ int ret;
+ u8 params[3] = { 0 };
+
+ ret = hidpp_send_rap_command_sync(hidpp_dev,
+ REPORT_ID_HIDPP_SHORT,