hid-for-linus-2026030601

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEoEVH9lhNrxiMPSyI7MXwXhnZSjYFAmmqkoIACgkQ7MXwXhnZ
 SjZg1xAAo8zWO1w8U99bYckAqgjWNEUbNiBo3370HbaNiOknW4B2Hzib4LIex4NE
 I/b1W1Wjq9ifgLLdHKP18eWVk4JgKupruTyoomfBrkHZSMbh8Y17GRdzpEj+4UEj
 HjmWTtNGKxJxpgVlSxPQuh1jNmkJm7FIYOMoSEM0CQJWHuUYERDrKsvJoHdZrX+p
 /C1Mn4+4o32CN2nUR7eRsvSisXjy/nTbNllLJNYZCCNBcvh3FaJNpEH5F+XMwg3n
 QKa5Ex0ZWMur1dN3y7xmJNdZszJoFFwb4UL1eWG3N0rIoHZpzbwdHDu2IXqJc0Jq
 HmdWqIceiScuhyjHNZ/DEes+GLMyIUUApO9Bs3Zmnde3yPtkbXc5TOvFeSL0ih+5
 WZjcW0b3rDhwibilgZA9ZuZfD44ajZsAOeZWJrc/7mNYoploJCc6ZOo3Ze7MJqjA
 tNnx33eX4+FpZndXVBAdkmM8iNTVNIaJ2SGPwauAfOUADaskdg83NFVa/q3IMAo3
 44Sw8Wk5E59J5vxGlceqvzySDgO5uB8v4J3kHnDKxOPtNivvV+38cnLAwnaI+/+h
 adGcCC9B67ekw02gAOOu+ExiijCCYLfKxIUckCKvGBiIXJELjzx98+H863/m+QwE
 gyvKdLM0EFu6qnAycma5IXtsM0aPlNz/WHOw/SQgGeMz2NePtLw=
 =fPAZ
 -----END PGP SIGNATURE-----

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

Pull HID fixes from Benjamin Tissoires:

 - fix a few memory leaks (Günther Noack)

 - fix potential kernel crashes in cmedia, creative-sb0540 and zydacron
   (Greg Kroah-Hartman)

 - fix NULL pointer dereference in pidff (Tomasz Pakuła)

 - fix battery reporting for Apple Magic Trackpad 2 (Julius Lehmann)

 - mcp2221 proper handling of failed read operation (Romain Sioen)

 - various device quirks / device ID additions

* tag 'hid-for-linus-2026030601' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: mcp2221: cancel last I2C command on read error
  HID: asus: add xg mobile 2023 external hardware support
  HID: multitouch: Keep latency normal on deactivate for reactivation gesture
  HID: apple: Add EPOMAKER TH87 to the non-apple keyboards list
  HID: intel-ish-hid: ipc: Add Nova Lake-H/S PCI device IDs
  selftests: hid: tests: test_wacom_generic: add tests for display devices and opaque devices
  HID: multitouch: new class MT_CLS_EGALAX_P80H84
  HID: magicmouse: fix battery reporting for Apple Magic Trackpad 2
  HID: pidff: Fix condition effect bit clearing
  HID: Add HID_CLAIMED_INPUT guards in raw_event callbacks missing them
  HID: asus: avoid memory leak in asus_report_fixup()
  HID: magicmouse: avoid memory leak in magicmouse_report_fixup()
  HID: apple: avoid memory leak in apple_report_fixup()
  HID: Document memory allocation properties of report_fixup()
This commit is contained in:
Linus Torvalds 2026-03-06 10:00:58 -08:00
commit 48976c0eba
14 changed files with 112 additions and 36 deletions

View File

@ -365,6 +365,9 @@ static const struct apple_non_apple_keyboard non_apple_keyboards[] = {
{ "A3R" },
{ "hfd.cn" },
{ "WKB603" },
{ "TH87" }, /* EPOMAKER TH87 BT mode */
{ "HFD Epomaker TH87" }, /* EPOMAKER TH87 USB mode */
{ "2.4G Wireless Receiver" }, /* EPOMAKER TH87 dongle */
};
static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
@ -686,9 +689,7 @@ static const __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info(hdev,
"fixing up Magic Keyboard battery report descriptor\n");
*rsize = *rsize - 1;
rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL);
if (!rdesc)
return NULL;
rdesc = rdesc + 1;
rdesc[0] = 0x05;
rdesc[1] = 0x01;

View File

@ -1399,14 +1399,21 @@ static const __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*/
if (*rsize == rsize_orig &&
rdesc[offs] == 0x09 && rdesc[offs + 1] == 0x76) {
*rsize = rsize_orig + 1;
rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL);
if (!rdesc)
return NULL;
__u8 *new_rdesc;
new_rdesc = devm_kzalloc(&hdev->dev, rsize_orig + 1,
GFP_KERNEL);
if (!new_rdesc)
return rdesc;
hid_info(hdev, "Fixing up %s keyb report descriptor\n",
drvdata->quirks & QUIRK_T100CHI ?
"T100CHI" : "T90CHI");
memcpy(new_rdesc, rdesc, rsize_orig);
*rsize = rsize_orig + 1;
rdesc = new_rdesc;
memmove(rdesc + offs + 4, rdesc + offs + 2, 12);
rdesc[offs] = 0x19;
rdesc[offs + 1] = 0x00;
@ -1490,6 +1497,9 @@ static const struct hid_device_id asus_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X),
QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_XGM_2023),
},
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD),
QUIRK_ROG_CLAYMORE_II_KEYBOARD },

View File

@ -99,7 +99,7 @@ static int cmhid_raw_event(struct hid_device *hid, struct hid_report *report,
{
struct cmhid *cm = hid_get_drvdata(hid);
if (len != CM6533_JD_RAWEV_LEN)
if (len != CM6533_JD_RAWEV_LEN || !(hid->claimed & HID_CLAIMED_INPUT))
goto out;
if (memcmp(data+CM6533_JD_SFX_OFFSET, ji_sfx, sizeof(ji_sfx)))
goto out;

View File

@ -153,7 +153,7 @@ static int creative_sb0540_raw_event(struct hid_device *hid,
u64 code, main_code;
int key;
if (len != 6)
if (len != 6 || !(hid->claimed & HID_CLAIMED_INPUT))
return 0;
/* From daemons/hw_hiddev.c sb0540_rec() in lirc */

View File

@ -229,6 +229,7 @@
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c
#define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b
#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869
#define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a
#define USB_VENDOR_ID_ATEN 0x0557
#define USB_DEVICE_ID_ATEN_UC100KM 0x2004

View File

@ -990,13 +990,11 @@ static const __u8 *magicmouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*/
if ((is_usb_magicmouse2(hdev->vendor, hdev->product) ||
is_usb_magictrackpad2(hdev->vendor, hdev->product)) &&
*rsize == 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) {
*rsize >= 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) {
hid_info(hdev,
"fixing up magicmouse battery report descriptor\n");
*rsize = *rsize - 1;
rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL);
if (!rdesc)
return NULL;
rdesc = rdesc + 1;
rdesc[0] = 0x05;
rdesc[1] = 0x01;

View File

@ -353,6 +353,8 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
usleep_range(90, 100);
retries++;
} else {
usleep_range(980, 1000);
mcp_cancel_last_cmd(mcp);
return ret;
}
} else {

View File

@ -77,6 +77,7 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_ORIENTATION_INVERT BIT(22)
#define MT_QUIRK_APPLE_TOUCHBAR BIT(23)
#define MT_QUIRK_YOGABOOK9I BIT(24)
#define MT_QUIRK_KEEP_LATENCY_ON_CLOSE BIT(25)
#define MT_INPUTMODE_TOUCHSCREEN 0x02
#define MT_INPUTMODE_TOUCHPAD 0x03
@ -214,6 +215,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
#define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016
#define MT_CLS_WIN_8_NO_STICKY_FINGERS 0x0017
#define MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU 0x0018
#define MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE 0x0019
/* vendor specific classes */
#define MT_CLS_3M 0x0101
@ -233,6 +235,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
#define MT_CLS_SMART_TECH 0x0113
#define MT_CLS_APPLE_TOUCHBAR 0x0114
#define MT_CLS_YOGABOOK9I 0x0115
#define MT_CLS_EGALAX_P80H84 0x0116
#define MT_CLS_SIS 0x0457
#define MT_DEFAULT_MAXCONTACT 10
@ -334,6 +337,15 @@ static const struct mt_class mt_classes[] = {
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_WIN8_PTP_BUTTONS,
.export_all_inputs = true },
{ .name = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
.quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_IGNORE_DUPLICATES |
MT_QUIRK_HOVERING |
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_STICKY_FINGERS |
MT_QUIRK_WIN8_PTP_BUTTONS |
MT_QUIRK_KEEP_LATENCY_ON_CLOSE,
.export_all_inputs = true },
/*
* vendor specific classes
@ -438,6 +450,11 @@ static const struct mt_class mt_classes[] = {
MT_QUIRK_YOGABOOK9I,
.export_all_inputs = true
},
{ .name = MT_CLS_EGALAX_P80H84,
.quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_IGNORE_DUPLICATES |
MT_QUIRK_CONTACT_CNT_ACCURATE,
},
{ }
};
@ -849,7 +866,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if ((cls->name == MT_CLS_WIN_8 ||
cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU ||
cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP) &&
cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP ||
cls->name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE) &&
(field->application == HID_DG_TOUCHPAD ||
field->application == HID_DG_TOUCHSCREEN))
app->quirks |= MT_QUIRK_CONFIDENCE;
@ -1762,7 +1780,8 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
int ret;
if (td->is_haptic_touchpad && (td->mtclass.name == MT_CLS_WIN_8 ||
td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT)) {
td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
td->mtclass.name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE)) {
if (hid_haptic_input_configured(hdev, td->haptic, hi) == 0)
td->is_haptic_touchpad = false;
} else {
@ -2075,7 +2094,12 @@ static void mt_on_hid_hw_open(struct hid_device *hdev)
static void mt_on_hid_hw_close(struct hid_device *hdev)
{
mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE);
struct mt_device *td = hid_get_drvdata(hdev);
if (td->mtclass.quirks & MT_QUIRK_KEEP_LATENCY_ON_CLOSE)
mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_NONE);
else
mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE);
}
/*
@ -2215,8 +2239,9 @@ static const struct hid_device_id mt_devices[] = {
{ .driver_data = MT_CLS_EGALAX_SERIAL,
MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C000) },
{ .driver_data = MT_CLS_EGALAX,
MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
{ .driver_data = MT_CLS_EGALAX_P80H84,
HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8,
USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) },
/* Elan devices */
@ -2461,6 +2486,14 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
/* Uniwill touchpads */
{ .driver_data = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
USB_VENDOR_ID_PIXART, 0x0255) },
{ .driver_data = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
USB_VENDOR_ID_PIXART, 0x0274) },
/* VTL panels */
{ .driver_data = MT_CLS_VTL,
MT_USB_DEVICE(USB_VENDOR_ID_VTL,

View File

@ -114,7 +114,7 @@ static int zc_raw_event(struct hid_device *hdev, struct hid_report *report,
unsigned key;
unsigned short index;
if (report->id == data[0]) {
if (report->id == data[0] && (hdev->claimed & HID_CLAIMED_INPUT)) {
/* break keys */
for (index = 0; index < 4; index++) {

View File

@ -39,6 +39,8 @@
#define PCI_DEVICE_ID_INTEL_ISH_PTL_H 0xE345
#define PCI_DEVICE_ID_INTEL_ISH_PTL_P 0xE445
#define PCI_DEVICE_ID_INTEL_ISH_WCL 0x4D45
#define PCI_DEVICE_ID_INTEL_ISH_NVL_H 0xD354
#define PCI_DEVICE_ID_INTEL_ISH_NVL_S 0x6E78
#define REVISION_ID_CHT_A0 0x6
#define REVISION_ID_CHT_Ax_SI 0x0

View File

@ -28,11 +28,15 @@ enum ishtp_driver_data_index {
ISHTP_DRIVER_DATA_LNL_M,
ISHTP_DRIVER_DATA_PTL,
ISHTP_DRIVER_DATA_WCL,
ISHTP_DRIVER_DATA_NVL_H,
ISHTP_DRIVER_DATA_NVL_S,
};
#define ISH_FW_GEN_LNL_M "lnlm"
#define ISH_FW_GEN_PTL "ptl"
#define ISH_FW_GEN_WCL "wcl"
#define ISH_FW_GEN_NVL_H "nvlh"
#define ISH_FW_GEN_NVL_S "nvls"
#define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin"
#define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin"
@ -47,6 +51,12 @@ static struct ishtp_driver_data ishtp_driver_data[] = {
[ISHTP_DRIVER_DATA_WCL] = {
.fw_generation = ISH_FW_GEN_WCL,
},
[ISHTP_DRIVER_DATA_NVL_H] = {
.fw_generation = ISH_FW_GEN_NVL_H,
},
[ISHTP_DRIVER_DATA_NVL_S] = {
.fw_generation = ISH_FW_GEN_NVL_S,
},
};
static const struct pci_device_id ish_pci_tbl[] = {
@ -76,6 +86,8 @@ static const struct pci_device_id ish_pci_tbl[] = {
{PCI_DEVICE_DATA(INTEL, ISH_PTL_H, ISHTP_DRIVER_DATA_PTL)},
{PCI_DEVICE_DATA(INTEL, ISH_PTL_P, ISHTP_DRIVER_DATA_PTL)},
{PCI_DEVICE_DATA(INTEL, ISH_WCL, ISHTP_DRIVER_DATA_WCL)},
{PCI_DEVICE_DATA(INTEL, ISH_NVL_H, ISHTP_DRIVER_DATA_NVL_H)},
{PCI_DEVICE_DATA(INTEL, ISH_NVL_S, ISHTP_DRIVER_DATA_NVL_S)},
{}
};
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);

View File

@ -1452,10 +1452,13 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
hid_warn(pidff->hid, "unknown ramp effect layout\n");
if (PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
if (test_and_clear_bit(FF_SPRING, dev->ffbit) ||
test_and_clear_bit(FF_DAMPER, dev->ffbit) ||
test_and_clear_bit(FF_FRICTION, dev->ffbit) ||
test_and_clear_bit(FF_INERTIA, dev->ffbit))
bool test = false;
test |= test_and_clear_bit(FF_SPRING, dev->ffbit);
test |= test_and_clear_bit(FF_DAMPER, dev->ffbit);
test |= test_and_clear_bit(FF_FRICTION, dev->ffbit);
test |= test_and_clear_bit(FF_INERTIA, dev->ffbit);
if (test)
hid_warn(pidff->hid, "unknown condition effect layout\n");
}

View File

@ -836,6 +836,12 @@ struct hid_usage_id {
* raw_event and event should return negative on error, any other value will
* pass the event on to .event() typically return 0 for success.
*
* report_fixup must return a report descriptor pointer whose lifetime is at
* least that of the input rdesc. This is usually done by mutating the input
* rdesc and returning it or a sub-portion of it. In case a new buffer is
* allocated and returned, the implementation of report_fixup is responsible for
* freeing it later.
*
* input_mapping shall return a negative value to completely ignore this usage
* (e.g. doubled or invalid usage), zero to continue with parsing of this
* usage by generic code (no special handling needed) or positive to skip

View File

@ -598,18 +598,6 @@ class BaseTest:
if unit_set:
assert required[usage].contains(field)
def test_prop_direct(self):
"""
Todo: Verify that INPUT_PROP_DIRECT is set on display devices.
"""
pass
def test_prop_pointer(self):
"""
Todo: Verify that INPUT_PROP_POINTER is set on opaque devices.
"""
pass
class PenTabletTest(BaseTest.TestTablet):
def assertName(self, uhdev):
@ -677,6 +665,15 @@ class TestOpaqueTablet(PenTabletTest):
uhdev.event(130, 240, pressure=0), [], auto_syn=False, strict=True
)
def test_prop_pointer(self):
"""
Verify that INPUT_PROP_POINTER is set and INPUT_PROP_DIRECT
is not set on opaque devices.
"""
evdev = self.uhdev.get_evdev()
assert libevdev.INPUT_PROP_POINTER in evdev.properties
assert libevdev.INPUT_PROP_DIRECT not in evdev.properties
class TestOpaqueCTLTablet(TestOpaqueTablet):
def create_device(self):
@ -862,7 +859,18 @@ class TestPTHX60_Pen(TestOpaqueCTLTablet):
)
class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest):
class DirectTabletTest():
def test_prop_direct(self):
"""
Verify that INPUT_PROP_DIRECT is set and INPUT_PROP_POINTER
is not set on display devices.
"""
evdev = self.uhdev.get_evdev()
assert libevdev.INPUT_PROP_DIRECT in evdev.properties
assert libevdev.INPUT_PROP_POINTER not in evdev.properties
class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest, DirectTabletTest):
ContactIds = namedtuple("ContactIds", "contact_id, tracking_id, slot_num")
def create_device(self):