Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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()

+112 -36
+4 -3
drivers/hid/hid-apple.c
··· 365 365 { "A3R" }, 366 366 { "hfd.cn" }, 367 367 { "WKB603" }, 368 + { "TH87" }, /* EPOMAKER TH87 BT mode */ 369 + { "HFD Epomaker TH87" }, /* EPOMAKER TH87 USB mode */ 370 + { "2.4G Wireless Receiver" }, /* EPOMAKER TH87 dongle */ 368 371 }; 369 372 370 373 static bool apple_is_non_apple_keyboard(struct hid_device *hdev) ··· 689 686 hid_info(hdev, 690 687 "fixing up Magic Keyboard battery report descriptor\n"); 691 688 *rsize = *rsize - 1; 692 - rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL); 693 - if (!rdesc) 694 - return NULL; 689 + rdesc = rdesc + 1; 695 690 696 691 rdesc[0] = 0x05; 697 692 rdesc[1] = 0x01;
+14 -4
drivers/hid/hid-asus.c
··· 1399 1399 */ 1400 1400 if (*rsize == rsize_orig && 1401 1401 rdesc[offs] == 0x09 && rdesc[offs + 1] == 0x76) { 1402 - *rsize = rsize_orig + 1; 1403 - rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL); 1404 - if (!rdesc) 1405 - return NULL; 1402 + __u8 *new_rdesc; 1403 + 1404 + new_rdesc = devm_kzalloc(&hdev->dev, rsize_orig + 1, 1405 + GFP_KERNEL); 1406 + if (!new_rdesc) 1407 + return rdesc; 1406 1408 1407 1409 hid_info(hdev, "Fixing up %s keyb report descriptor\n", 1408 1410 drvdata->quirks & QUIRK_T100CHI ? 1409 1411 "T100CHI" : "T90CHI"); 1412 + 1413 + memcpy(new_rdesc, rdesc, rsize_orig); 1414 + *rsize = rsize_orig + 1; 1415 + rdesc = new_rdesc; 1416 + 1410 1417 memmove(rdesc + offs + 4, rdesc + offs + 2, 12); 1411 1418 rdesc[offs] = 0x19; 1412 1419 rdesc[offs + 1] = 0x00; ··· 1497 1490 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, 1498 1491 USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X), 1499 1492 QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD }, 1493 + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, 1494 + USB_DEVICE_ID_ASUSTEK_XGM_2023), 1495 + }, 1500 1496 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, 1501 1497 USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD), 1502 1498 QUIRK_ROG_CLAYMORE_II_KEYBOARD },
+1 -1
drivers/hid/hid-cmedia.c
··· 99 99 { 100 100 struct cmhid *cm = hid_get_drvdata(hid); 101 101 102 - if (len != CM6533_JD_RAWEV_LEN) 102 + if (len != CM6533_JD_RAWEV_LEN || !(hid->claimed & HID_CLAIMED_INPUT)) 103 103 goto out; 104 104 if (memcmp(data+CM6533_JD_SFX_OFFSET, ji_sfx, sizeof(ji_sfx))) 105 105 goto out;
+1 -1
drivers/hid/hid-creative-sb0540.c
··· 153 153 u64 code, main_code; 154 154 int key; 155 155 156 - if (len != 6) 156 + if (len != 6 || !(hid->claimed & HID_CLAIMED_INPUT)) 157 157 return 0; 158 158 159 159 /* From daemons/hw_hiddev.c sb0540_rec() in lirc */
+1
drivers/hid/hid-ids.h
··· 229 229 #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c 230 230 #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b 231 231 #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 232 + #define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a 232 233 233 234 #define USB_VENDOR_ID_ATEN 0x0557 234 235 #define USB_DEVICE_ID_ATEN_UC100KM 0x2004
+2 -4
drivers/hid/hid-magicmouse.c
··· 990 990 */ 991 991 if ((is_usb_magicmouse2(hdev->vendor, hdev->product) || 992 992 is_usb_magictrackpad2(hdev->vendor, hdev->product)) && 993 - *rsize == 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) { 993 + *rsize >= 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) { 994 994 hid_info(hdev, 995 995 "fixing up magicmouse battery report descriptor\n"); 996 996 *rsize = *rsize - 1; 997 - rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL); 998 - if (!rdesc) 999 - return NULL; 997 + rdesc = rdesc + 1; 1000 998 1001 999 rdesc[0] = 0x05; 1002 1000 rdesc[1] = 0x01;
+2
drivers/hid/hid-mcp2221.c
··· 353 353 usleep_range(90, 100); 354 354 retries++; 355 355 } else { 356 + usleep_range(980, 1000); 357 + mcp_cancel_last_cmd(mcp); 356 358 return ret; 357 359 } 358 360 } else {
+38 -5
drivers/hid/hid-multitouch.c
··· 77 77 #define MT_QUIRK_ORIENTATION_INVERT BIT(22) 78 78 #define MT_QUIRK_APPLE_TOUCHBAR BIT(23) 79 79 #define MT_QUIRK_YOGABOOK9I BIT(24) 80 + #define MT_QUIRK_KEEP_LATENCY_ON_CLOSE BIT(25) 80 81 81 82 #define MT_INPUTMODE_TOUCHSCREEN 0x02 82 83 #define MT_INPUTMODE_TOUCHPAD 0x03 ··· 215 214 #define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016 216 215 #define MT_CLS_WIN_8_NO_STICKY_FINGERS 0x0017 217 216 #define MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU 0x0018 217 + #define MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE 0x0019 218 218 219 219 /* vendor specific classes */ 220 220 #define MT_CLS_3M 0x0101 ··· 235 233 #define MT_CLS_SMART_TECH 0x0113 236 234 #define MT_CLS_APPLE_TOUCHBAR 0x0114 237 235 #define MT_CLS_YOGABOOK9I 0x0115 236 + #define MT_CLS_EGALAX_P80H84 0x0116 238 237 #define MT_CLS_SIS 0x0457 239 238 240 239 #define MT_DEFAULT_MAXCONTACT 10 ··· 336 333 MT_QUIRK_HOVERING | 337 334 MT_QUIRK_CONTACT_CNT_ACCURATE | 338 335 MT_QUIRK_WIN8_PTP_BUTTONS, 336 + .export_all_inputs = true }, 337 + { .name = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE, 338 + .quirks = MT_QUIRK_ALWAYS_VALID | 339 + MT_QUIRK_IGNORE_DUPLICATES | 340 + MT_QUIRK_HOVERING | 341 + MT_QUIRK_CONTACT_CNT_ACCURATE | 342 + MT_QUIRK_STICKY_FINGERS | 343 + MT_QUIRK_WIN8_PTP_BUTTONS | 344 + MT_QUIRK_KEEP_LATENCY_ON_CLOSE, 339 345 .export_all_inputs = true }, 340 346 341 347 /* ··· 449 437 MT_QUIRK_HOVERING | 450 438 MT_QUIRK_YOGABOOK9I, 451 439 .export_all_inputs = true 440 + }, 441 + { .name = MT_CLS_EGALAX_P80H84, 442 + .quirks = MT_QUIRK_ALWAYS_VALID | 443 + MT_QUIRK_IGNORE_DUPLICATES | 444 + MT_QUIRK_CONTACT_CNT_ACCURATE, 452 445 }, 453 446 { } 454 447 }; ··· 866 849 if ((cls->name == MT_CLS_WIN_8 || 867 850 cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT || 868 851 cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU || 869 - cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP) && 852 + cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP || 853 + cls->name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE) && 870 854 (field->application == HID_DG_TOUCHPAD || 871 855 field->application == HID_DG_TOUCHSCREEN)) 872 856 app->quirks |= MT_QUIRK_CONFIDENCE; ··· 1780 1762 int ret; 1781 1763 1782 1764 if (td->is_haptic_touchpad && (td->mtclass.name == MT_CLS_WIN_8 || 1783 - td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT)) { 1765 + td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT || 1766 + td->mtclass.name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE)) { 1784 1767 if (hid_haptic_input_configured(hdev, td->haptic, hi) == 0) 1785 1768 td->is_haptic_touchpad = false; 1786 1769 } else { ··· 2094 2075 2095 2076 static void mt_on_hid_hw_close(struct hid_device *hdev) 2096 2077 { 2097 - mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE); 2078 + struct mt_device *td = hid_get_drvdata(hdev); 2079 + 2080 + if (td->mtclass.quirks & MT_QUIRK_KEEP_LATENCY_ON_CLOSE) 2081 + mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_NONE); 2082 + else 2083 + mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE); 2098 2084 } 2099 2085 2100 2086 /* ··· 2239 2215 { .driver_data = MT_CLS_EGALAX_SERIAL, 2240 2216 MT_USB_DEVICE(USB_VENDOR_ID_DWAV, 2241 2217 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C000) }, 2242 - { .driver_data = MT_CLS_EGALAX, 2243 - MT_USB_DEVICE(USB_VENDOR_ID_DWAV, 2218 + { .driver_data = MT_CLS_EGALAX_P80H84, 2219 + HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8, 2220 + USB_VENDOR_ID_DWAV, 2244 2221 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) }, 2245 2222 2246 2223 /* Elan devices */ ··· 2485 2460 { .driver_data = MT_CLS_NSMU, 2486 2461 MT_USB_DEVICE(USB_VENDOR_ID_UNITEC, 2487 2462 USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, 2463 + 2464 + /* Uniwill touchpads */ 2465 + { .driver_data = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE, 2466 + HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, 2467 + USB_VENDOR_ID_PIXART, 0x0255) }, 2468 + { .driver_data = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE, 2469 + HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, 2470 + USB_VENDOR_ID_PIXART, 0x0274) }, 2488 2471 2489 2472 /* VTL panels */ 2490 2473 { .driver_data = MT_CLS_VTL,
+1 -1
drivers/hid/hid-zydacron.c
··· 114 114 unsigned key; 115 115 unsigned short index; 116 116 117 - if (report->id == data[0]) { 117 + if (report->id == data[0] && (hdev->claimed & HID_CLAIMED_INPUT)) { 118 118 119 119 /* break keys */ 120 120 for (index = 0; index < 4; index++) {
+2
drivers/hid/intel-ish-hid/ipc/hw-ish.h
··· 39 39 #define PCI_DEVICE_ID_INTEL_ISH_PTL_H 0xE345 40 40 #define PCI_DEVICE_ID_INTEL_ISH_PTL_P 0xE445 41 41 #define PCI_DEVICE_ID_INTEL_ISH_WCL 0x4D45 42 + #define PCI_DEVICE_ID_INTEL_ISH_NVL_H 0xD354 43 + #define PCI_DEVICE_ID_INTEL_ISH_NVL_S 0x6E78 42 44 43 45 #define REVISION_ID_CHT_A0 0x6 44 46 #define REVISION_ID_CHT_Ax_SI 0x0
+12
drivers/hid/intel-ish-hid/ipc/pci-ish.c
··· 28 28 ISHTP_DRIVER_DATA_LNL_M, 29 29 ISHTP_DRIVER_DATA_PTL, 30 30 ISHTP_DRIVER_DATA_WCL, 31 + ISHTP_DRIVER_DATA_NVL_H, 32 + ISHTP_DRIVER_DATA_NVL_S, 31 33 }; 32 34 33 35 #define ISH_FW_GEN_LNL_M "lnlm" 34 36 #define ISH_FW_GEN_PTL "ptl" 35 37 #define ISH_FW_GEN_WCL "wcl" 38 + #define ISH_FW_GEN_NVL_H "nvlh" 39 + #define ISH_FW_GEN_NVL_S "nvls" 36 40 37 41 #define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin" 38 42 #define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin" ··· 50 46 }, 51 47 [ISHTP_DRIVER_DATA_WCL] = { 52 48 .fw_generation = ISH_FW_GEN_WCL, 49 + }, 50 + [ISHTP_DRIVER_DATA_NVL_H] = { 51 + .fw_generation = ISH_FW_GEN_NVL_H, 52 + }, 53 + [ISHTP_DRIVER_DATA_NVL_S] = { 54 + .fw_generation = ISH_FW_GEN_NVL_S, 53 55 }, 54 56 }; 55 57 ··· 86 76 {PCI_DEVICE_DATA(INTEL, ISH_PTL_H, ISHTP_DRIVER_DATA_PTL)}, 87 77 {PCI_DEVICE_DATA(INTEL, ISH_PTL_P, ISHTP_DRIVER_DATA_PTL)}, 88 78 {PCI_DEVICE_DATA(INTEL, ISH_WCL, ISHTP_DRIVER_DATA_WCL)}, 79 + {PCI_DEVICE_DATA(INTEL, ISH_NVL_H, ISHTP_DRIVER_DATA_NVL_H)}, 80 + {PCI_DEVICE_DATA(INTEL, ISH_NVL_S, ISHTP_DRIVER_DATA_NVL_S)}, 89 81 {} 90 82 }; 91 83 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
+7 -4
drivers/hid/usbhid/hid-pidff.c
··· 1452 1452 hid_warn(pidff->hid, "unknown ramp effect layout\n"); 1453 1453 1454 1454 if (PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { 1455 - if (test_and_clear_bit(FF_SPRING, dev->ffbit) || 1456 - test_and_clear_bit(FF_DAMPER, dev->ffbit) || 1457 - test_and_clear_bit(FF_FRICTION, dev->ffbit) || 1458 - test_and_clear_bit(FF_INERTIA, dev->ffbit)) 1455 + bool test = false; 1456 + 1457 + test |= test_and_clear_bit(FF_SPRING, dev->ffbit); 1458 + test |= test_and_clear_bit(FF_DAMPER, dev->ffbit); 1459 + test |= test_and_clear_bit(FF_FRICTION, dev->ffbit); 1460 + test |= test_and_clear_bit(FF_INERTIA, dev->ffbit); 1461 + if (test) 1459 1462 hid_warn(pidff->hid, "unknown condition effect layout\n"); 1460 1463 } 1461 1464
+6
include/linux/hid.h
··· 836 836 * raw_event and event should return negative on error, any other value will 837 837 * pass the event on to .event() typically return 0 for success. 838 838 * 839 + * report_fixup must return a report descriptor pointer whose lifetime is at 840 + * least that of the input rdesc. This is usually done by mutating the input 841 + * rdesc and returning it or a sub-portion of it. In case a new buffer is 842 + * allocated and returned, the implementation of report_fixup is responsible for 843 + * freeing it later. 844 + * 839 845 * input_mapping shall return a negative value to completely ignore this usage 840 846 * (e.g. doubled or invalid usage), zero to continue with parsing of this 841 847 * usage by generic code (no special handling needed) or positive to skip
+21 -13
tools/testing/selftests/hid/tests/test_wacom_generic.py
··· 598 598 if unit_set: 599 599 assert required[usage].contains(field) 600 600 601 - def test_prop_direct(self): 602 - """ 603 - Todo: Verify that INPUT_PROP_DIRECT is set on display devices. 604 - """ 605 - pass 606 - 607 - def test_prop_pointer(self): 608 - """ 609 - Todo: Verify that INPUT_PROP_POINTER is set on opaque devices. 610 - """ 611 - pass 612 - 613 601 614 602 class PenTabletTest(BaseTest.TestTablet): 615 603 def assertName(self, uhdev): ··· 664 676 self.sync_and_assert_events( 665 677 uhdev.event(130, 240, pressure=0), [], auto_syn=False, strict=True 666 678 ) 679 + 680 + def test_prop_pointer(self): 681 + """ 682 + Verify that INPUT_PROP_POINTER is set and INPUT_PROP_DIRECT 683 + is not set on opaque devices. 684 + """ 685 + evdev = self.uhdev.get_evdev() 686 + assert libevdev.INPUT_PROP_POINTER in evdev.properties 687 + assert libevdev.INPUT_PROP_DIRECT not in evdev.properties 667 688 668 689 669 690 class TestOpaqueCTLTablet(TestOpaqueTablet): ··· 859 862 ) 860 863 861 864 862 - class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest): 865 + class DirectTabletTest(): 866 + def test_prop_direct(self): 867 + """ 868 + Verify that INPUT_PROP_DIRECT is set and INPUT_PROP_POINTER 869 + is not set on display devices. 870 + """ 871 + evdev = self.uhdev.get_evdev() 872 + assert libevdev.INPUT_PROP_DIRECT in evdev.properties 873 + assert libevdev.INPUT_PROP_POINTER not in evdev.properties 874 + 875 + 876 + class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest, DirectTabletTest): 863 877 ContactIds = namedtuple("ContactIds", "contact_id, tracking_id, slot_num") 864 878 865 879 def create_device(self):