Commit 6df62e79 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID fixes from Jiri Kosina:

 - corner-case oops fixes for Asus and Wacom drivers from Carlo Caione
   and Jason Gerecke

 - power management fix (reported on SIS0817 touchscreen) for i2c-hid
   devices from Hans de Goede

 - device-id-specific fixes and quirks from Hans de Goede, Diego Elio
   Pettenò and Che-Liang Chiou

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
  HID: asus: Stop underlying hardware on remove
  HID: i2c: Call acpi_device_fix_up_power for ACPI-enumerated devices
  HID: asus: Add support for T100 keyboard
  HID: elecom: extend to fix the descriptor for DEFT trackballs
  HID: magicmouse: Set multi-touch keybits for Magic Mouse
  HID: wacom: Have wacom_tpc_irq guard against possible NULL dereference
parents 035f1456 715e944f
...@@ -275,10 +275,12 @@ config HID_EMS_FF ...@@ -275,10 +275,12 @@ config HID_EMS_FF
- Trio Linker Plus II - Trio Linker Plus II
config HID_ELECOM config HID_ELECOM
tristate "ELECOM BM084 bluetooth mouse" tristate "ELECOM HID devices"
depends on HID depends on HID
---help--- ---help---
Support for the ELECOM BM084 (bluetooth mouse). Support for ELECOM devices:
- BM084 Bluetooth Mouse
- DEFT Trackball (Wired and wireless)
config HID_ELO config HID_ELO
tristate "ELO USB 4000/4500 touchscreen" tristate "ELO USB 4000/4500 touchscreen"
......
...@@ -69,6 +69,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); ...@@ -69,6 +69,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define QUIRK_IS_MULTITOUCH BIT(3) #define QUIRK_IS_MULTITOUCH BIT(3)
#define QUIRK_NO_CONSUMER_USAGES BIT(4) #define QUIRK_NO_CONSUMER_USAGES BIT(4)
#define QUIRK_USE_KBD_BACKLIGHT BIT(5) #define QUIRK_USE_KBD_BACKLIGHT BIT(5)
#define QUIRK_T100_KEYBOARD BIT(6)
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
QUIRK_NO_INIT_REPORTS | \ QUIRK_NO_INIT_REPORTS | \
...@@ -536,6 +537,8 @@ static void asus_remove(struct hid_device *hdev) ...@@ -536,6 +537,8 @@ static void asus_remove(struct hid_device *hdev)
drvdata->kbd_backlight->removed = true; drvdata->kbd_backlight->removed = true;
cancel_work_sync(&drvdata->kbd_backlight->work); cancel_work_sync(&drvdata->kbd_backlight->work);
} }
hid_hw_stop(hdev);
} }
static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
...@@ -548,6 +551,12 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, ...@@ -548,6 +551,12 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info(hdev, "Fixing up Asus notebook report descriptor\n"); hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
rdesc[55] = 0xdd; rdesc[55] = 0xdd;
} }
if (drvdata->quirks & QUIRK_T100_KEYBOARD &&
*rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) {
hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
}
return rdesc; return rdesc;
} }
...@@ -560,6 +569,9 @@ static const struct hid_device_id asus_devices[] = { ...@@ -560,6 +569,9 @@ static const struct hid_device_id asus_devices[] = {
USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) }, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT }, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, asus_devices); MODULE_DEVICE_TABLE(hid, asus_devices);
......
...@@ -1855,6 +1855,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1855,6 +1855,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) }, { 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_KEYBOARD1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, { 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_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
...@@ -1891,6 +1892,8 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1891,6 +1892,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) }, { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
{ 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_ELO, 0x0009) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) }, { 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_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) },
......
/* /*
* HID driver for Elecom BM084 (bluetooth mouse). * HID driver for ELECOM devices.
* Removes a non-existing horizontal wheel from
* the HID descriptor.
* (This module is based on "hid-ortek".)
*
* Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com> * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
* Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
* Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
*/ */
/* /*
...@@ -23,15 +21,61 @@ ...@@ -23,15 +21,61 @@
static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize) unsigned int *rsize)
{ {
if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { switch (hdev->product) {
hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); case USB_DEVICE_ID_ELECOM_BM084:
rdesc[47] = 0x00; /* The BM084 Bluetooth mouse includes a non-existing horizontal
* wheel in the HID descriptor. */
if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
rdesc[47] = 0x00;
}
break;
case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
/* The DEFT trackball has eight buttons, but its descriptor only
* reports five, disabling the three Fn buttons on the top of
* the mouse.
*
* Apply the following diff to the descriptor:
*
* Collection (Physical), Collection (Physical),
* Report ID (1), Report ID (1),
* Report Count (5), -> Report Count (8),
* Report Size (1), Report Size (1),
* Usage Page (Button), Usage Page (Button),
* Usage Minimum (01h), Usage Minimum (01h),
* Usage Maximum (05h), -> Usage Maximum (08h),
* Logical Minimum (0), Logical Minimum (0),
* Logical Maximum (1), Logical Maximum (1),
* Input (Variable), Input (Variable),
* Report Count (1), -> Report Count (0),
* Report Size (3), Report Size (3),
* Input (Constant), Input (Constant),
* Report Size (16), Report Size (16),
* Report Count (2), Report Count (2),
* Usage Page (Desktop), Usage Page (Desktop),
* Usage (X), Usage (X),
* Usage (Y), Usage (Y),
* Logical Minimum (-32768), Logical Minimum (-32768),
* Logical Maximum (32767), Logical Maximum (32767),
* Input (Variable, Relative), Input (Variable, Relative),
* End Collection, End Collection,
*/
if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) {
hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n");
rdesc[13] = 8; /* Button/Variable Report Count */
rdesc[21] = 8; /* Button/Variable Usage Maximum */
rdesc[29] = 0; /* Button/Constant Report Count */
}
break;
} }
return rdesc; return rdesc;
} }
static const struct hid_device_id elecom_devices[] = { static const struct hid_device_id elecom_devices[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084)}, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
{ 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) },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, elecom_devices); MODULE_DEVICE_TABLE(hid, elecom_devices);
......
...@@ -173,6 +173,7 @@ ...@@ -173,6 +173,7 @@
#define USB_VENDOR_ID_ASUSTEK 0x0b05 #define USB_VENDOR_ID_ASUSTEK 0x0b05
#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726
#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b
#define USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD 0x17e0
#define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585 #define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585
#define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101 #define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101
#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854
...@@ -358,6 +359,8 @@ ...@@ -358,6 +359,8 @@
#define USB_VENDOR_ID_ELECOM 0x056e #define USB_VENDOR_ID_ELECOM 0x056e
#define USB_DEVICE_ID_ELECOM_BM084 0x0061 #define USB_DEVICE_ID_ELECOM_BM084 0x0061
#define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe
#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff
#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34
#define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004
......
...@@ -349,6 +349,7 @@ static int magicmouse_raw_event(struct hid_device *hdev, ...@@ -349,6 +349,7 @@ static int magicmouse_raw_event(struct hid_device *hdev,
if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
magicmouse_emit_buttons(msc, clicks & 3); magicmouse_emit_buttons(msc, clicks & 3);
input_mt_report_pointer_emulation(input, true);
input_report_rel(input, REL_X, x); input_report_rel(input, REL_X, x);
input_report_rel(input, REL_Y, y); input_report_rel(input, REL_Y, y);
} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
...@@ -388,16 +389,16 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd ...@@ -388,16 +389,16 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
__clear_bit(BTN_RIGHT, input->keybit); __clear_bit(BTN_RIGHT, input->keybit);
__clear_bit(BTN_MIDDLE, input->keybit); __clear_bit(BTN_MIDDLE, input->keybit);
__set_bit(BTN_MOUSE, input->keybit); __set_bit(BTN_MOUSE, input->keybit);
__set_bit(BTN_TOOL_FINGER, input->keybit);
__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
__set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
__set_bit(BTN_TOOL_QUADTAP, input->keybit);
__set_bit(BTN_TOOL_QUINTTAP, input->keybit);
__set_bit(BTN_TOUCH, input->keybit);
__set_bit(INPUT_PROP_POINTER, input->propbit);
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit); __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
} }
__set_bit(BTN_TOOL_FINGER, input->keybit);
__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
__set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
__set_bit(BTN_TOOL_QUADTAP, input->keybit);
__set_bit(BTN_TOOL_QUINTTAP, input->keybit);
__set_bit(BTN_TOUCH, input->keybit);
__set_bit(INPUT_PROP_POINTER, input->propbit);
__set_bit(EV_ABS, input->evbit); __set_bit(EV_ABS, input->evbit);
......
...@@ -897,6 +897,15 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client, ...@@ -897,6 +897,15 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
return 0; return 0;
} }
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)
acpi_device_fix_up_power(adev);
}
static const struct acpi_device_id i2c_hid_acpi_match[] = { static const struct acpi_device_id i2c_hid_acpi_match[] = {
{"ACPI0C50", 0 }, {"ACPI0C50", 0 },
{"PNP0C50", 0 }, {"PNP0C50", 0 },
...@@ -909,6 +918,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client, ...@@ -909,6 +918,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
{ {
return -ENODEV; return -ENODEV;
} }
static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {}
#endif #endif
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -1030,6 +1041,8 @@ static int i2c_hid_probe(struct i2c_client *client, ...@@ -1030,6 +1041,8 @@ static int i2c_hid_probe(struct i2c_client *client,
if (ret < 0) if (ret < 0)
goto err_regulator; goto err_regulator;
i2c_hid_acpi_fix_up_power(&client->dev);
pm_runtime_get_noresume(&client->dev); pm_runtime_get_noresume(&client->dev);
pm_runtime_set_active(&client->dev); pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev); pm_runtime_enable(&client->dev);
......
...@@ -1571,37 +1571,38 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) ...@@ -1571,37 +1571,38 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
{ {
unsigned char *data = wacom->data; unsigned char *data = wacom->data;
if (wacom->pen_input) if (wacom->pen_input) {
dev_dbg(wacom->pen_input->dev.parent, dev_dbg(wacom->pen_input->dev.parent,
"%s: received report #%d\n", __func__, data[0]); "%s: received report #%d\n", __func__, data[0]);
else if (wacom->touch_input)
if (len == WACOM_PKGLEN_PENABLED ||
data[0] == WACOM_REPORT_PENABLED)
return wacom_tpc_pen(wacom);
}
else if (wacom->touch_input) {
dev_dbg(wacom->touch_input->dev.parent, dev_dbg(wacom->touch_input->dev.parent,
"%s: received report #%d\n", __func__, data[0]); "%s: received report #%d\n", __func__, data[0]);
switch (len) { switch (len) {
case WACOM_PKGLEN_TPC1FG: case WACOM_PKGLEN_TPC1FG:
return wacom_tpc_single_touch(wacom, len); return wacom_tpc_single_touch(wacom, len);
case WACOM_PKGLEN_TPC2FG: case WACOM_PKGLEN_TPC2FG:
return wacom_tpc_mt_touch(wacom); return wacom_tpc_mt_touch(wacom);
case WACOM_PKGLEN_PENABLED: default:
return wacom_tpc_pen(wacom); switch (data[0]) {
case WACOM_REPORT_TPC1FG:
case WACOM_REPORT_TPCHID:
case WACOM_REPORT_TPCST:
case WACOM_REPORT_TPC1FGE:
return wacom_tpc_single_touch(wacom, len);
default: case WACOM_REPORT_TPCMT:
switch (data[0]) { case WACOM_REPORT_TPCMT2:
case WACOM_REPORT_TPC1FG: return wacom_mt_touch(wacom);
case WACOM_REPORT_TPCHID:
case WACOM_REPORT_TPCST:
case WACOM_REPORT_TPC1FGE:
return wacom_tpc_single_touch(wacom, len);
case WACOM_REPORT_TPCMT:
case WACOM_REPORT_TPCMT2:
return wacom_mt_touch(wacom);
case WACOM_REPORT_PENABLED: }
return wacom_tpc_pen(wacom);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment