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

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull HID fixes from Jiri Kosina:

- fixes for memory corruption in intel-thc-hid, hid-multitouch,
hid-mcp2221 and hid-asus (Aaron Ma, Qasim Ijaz, Arnaud Lecomte)

- power management/resume fix for intel-ish-hid (Zhang Lixu)

- driver reinitialization fix for intel-thc-hid (Even Xu)

- ensure that battery level status is reported as soon as possible,
which is required at least for some Android use-cases (José Expósito)

- quite a few new device ID additions and device-specific quirks

* tag 'hid-for-linus-2025082901' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
HID: quirks: add support for Legion Go dual dinput modes
HID: elecom: add support for ELECOM M-DT2DRBK
HID: logitech: Add ids for G PRO 2 LIGHTSPEED
HID: input: report battery status changes immediately
HID: input: rename hidinput_set_battery_charge_status()
HID: intel-thc-hid: Intel-quicki2c: Enhance driver re-install flow
HID: hid-ntrig: fix unable to handle page fault in ntrig_report_version()
HID: asus: fix UAF via HID_CLAIMED_INPUT validation
hid: fix I2C read buffer overflow in raw_event() for mcp2221
HID: wacom: Add a new Art Pen 2
HID: multitouch: fix slab out-of-bounds access in mt_report_fixup()
HID: Kconfig: Fix spelling mistake "enthropy" -> "entropy"
HID: intel-ish-hid: Increase ISHTP resume ack timeout to 300ms
HID: intel-thc-hid: intel-thc: Fix incorrect pointer arithmetic in I2C regs save
HID: intel-thc-hid: intel-quicki2c: Fix ACPI dsd ICRS/ISUB length

+79 -42
+1 -1
drivers/hid/Kconfig
··· 1243 1243 1244 1244 U2F Zero supports custom commands for blinking the LED 1245 1245 and getting data from the internal hardware RNG. 1246 - The internal hardware can be used to feed the enthropy pool. 1246 + The internal hardware can be used to feed the entropy pool. 1247 1247 1248 1248 U2F Zero only supports blinking its LED, so this driver doesn't 1249 1249 allow setting the brightness to anything but 1, which will
+7 -1
drivers/hid/hid-asus.c
··· 1213 1213 return ret; 1214 1214 } 1215 1215 1216 - if (!drvdata->input) { 1216 + /* 1217 + * Check that input registration succeeded. Checking that 1218 + * HID_CLAIMED_INPUT is set prevents a UAF when all input devices 1219 + * were freed during registration due to no usages being mapped, 1220 + * leaving drvdata->input pointing to freed memory. 1221 + */ 1222 + if (!drvdata->input || !(hdev->claimed & HID_CLAIMED_INPUT)) { 1217 1223 hid_err(hdev, "Asus input not registered\n"); 1218 1224 ret = -ENOMEM; 1219 1225 goto err_stop_hw;
+2
drivers/hid/hid-elecom.c
··· 101 101 */ 102 102 mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8); 103 103 break; 104 + case USB_DEVICE_ID_ELECOM_M_DT2DRBK: 104 105 case USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C: 105 106 /* 106 107 * Report descriptor format: ··· 124 123 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) }, 125 124 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, 126 125 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, 126 + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT2DRBK) }, 127 127 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK_010C) }, 128 128 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK_019B) }, 129 129 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) },
+4
drivers/hid/hid-ids.h
··· 451 451 #define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd 452 452 #define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe 453 453 #define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff 454 + #define USB_DEVICE_ID_ELECOM_M_DT2DRBK 0x018d 454 455 #define USB_DEVICE_ID_ELECOM_M_HT1URBK_010C 0x010c 455 456 #define USB_DEVICE_ID_ELECOM_M_HT1URBK_019B 0x019b 456 457 #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D 0x010d ··· 835 834 #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019 836 835 #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E 0x602e 837 836 #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093 0x6093 837 + #define USB_DEVICE_ID_LENOVO_LEGION_GO_DUAL_DINPUT 0x6184 838 + #define USB_DEVICE_ID_LENOVO_LEGION_GO2_DUAL_DINPUT 0x61ed 838 839 839 840 #define USB_VENDOR_ID_LETSKETCH 0x6161 840 841 #define USB_DEVICE_ID_WP9620N 0x4d15 ··· 910 907 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534 911 908 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 0xc539 912 909 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1 0xc53f 910 + #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2 0xc543 913 911 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a 914 912 #define USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER 0xc548 915 913 #define USB_DEVICE_ID_SPACETRAVELLER 0xc623
+5 -5
drivers/hid/hid-input-test.c
··· 7 7 8 8 #include <kunit/test.h> 9 9 10 - static void hid_test_input_set_battery_charge_status(struct kunit *test) 10 + static void hid_test_input_update_battery_charge_status(struct kunit *test) 11 11 { 12 12 struct hid_device *dev; 13 13 bool handled; ··· 15 15 dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); 16 16 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 17 17 18 - handled = hidinput_set_battery_charge_status(dev, HID_DG_HEIGHT, 0); 18 + handled = hidinput_update_battery_charge_status(dev, HID_DG_HEIGHT, 0); 19 19 KUNIT_EXPECT_FALSE(test, handled); 20 20 KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_UNKNOWN); 21 21 22 - handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 0); 22 + handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 0); 23 23 KUNIT_EXPECT_TRUE(test, handled); 24 24 KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_DISCHARGING); 25 25 26 - handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 1); 26 + handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 1); 27 27 KUNIT_EXPECT_TRUE(test, handled); 28 28 KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_CHARGING); 29 29 } ··· 63 63 } 64 64 65 65 static struct kunit_case hid_input_tests[] = { 66 - KUNIT_CASE(hid_test_input_set_battery_charge_status), 66 + KUNIT_CASE(hid_test_input_update_battery_charge_status), 67 67 KUNIT_CASE(hid_test_input_get_battery_property), 68 68 { } 69 69 };
+24 -27
drivers/hid/hid-input.c
··· 595 595 dev->battery = NULL; 596 596 } 597 597 598 - static void hidinput_update_battery(struct hid_device *dev, int value) 598 + static bool hidinput_update_battery_charge_status(struct hid_device *dev, 599 + unsigned int usage, int value) 600 + { 601 + switch (usage) { 602 + case HID_BAT_CHARGING: 603 + dev->battery_charge_status = value ? 604 + POWER_SUPPLY_STATUS_CHARGING : 605 + POWER_SUPPLY_STATUS_DISCHARGING; 606 + return true; 607 + } 608 + 609 + return false; 610 + } 611 + 612 + static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, 613 + int value) 599 614 { 600 615 int capacity; 601 616 602 617 if (!dev->battery) 603 618 return; 619 + 620 + if (hidinput_update_battery_charge_status(dev, usage, value)) { 621 + power_supply_changed(dev->battery); 622 + return; 623 + } 604 624 605 625 if (value == 0 || value < dev->battery_min || value > dev->battery_max) 606 626 return; ··· 637 617 power_supply_changed(dev->battery); 638 618 } 639 619 } 640 - 641 - static bool hidinput_set_battery_charge_status(struct hid_device *dev, 642 - unsigned int usage, int value) 643 - { 644 - switch (usage) { 645 - case HID_BAT_CHARGING: 646 - dev->battery_charge_status = value ? 647 - POWER_SUPPLY_STATUS_CHARGING : 648 - POWER_SUPPLY_STATUS_DISCHARGING; 649 - return true; 650 - } 651 - 652 - return false; 653 - } 654 620 #else /* !CONFIG_HID_BATTERY_STRENGTH */ 655 621 static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, 656 622 struct hid_field *field, bool is_percentage) ··· 648 642 { 649 643 } 650 644 651 - static void hidinput_update_battery(struct hid_device *dev, int value) 645 + static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, 646 + int value) 652 647 { 653 - } 654 - 655 - static bool hidinput_set_battery_charge_status(struct hid_device *dev, 656 - unsigned int usage, int value) 657 - { 658 - return false; 659 648 } 660 649 #endif /* CONFIG_HID_BATTERY_STRENGTH */ 661 650 ··· 1516 1515 return; 1517 1516 1518 1517 if (usage->type == EV_PWR) { 1519 - bool handled = hidinput_set_battery_charge_status(hid, usage->hid, value); 1520 - 1521 - if (!handled) 1522 - hidinput_update_battery(hid, value); 1523 - 1518 + hidinput_update_battery(hid, usage->hid, value); 1524 1519 return; 1525 1520 } 1526 1521
+4
drivers/hid/hid-logitech-dj.c
··· 1983 1983 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1984 1984 USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1), 1985 1985 .driver_data = recvr_type_gaming_hidpp}, 1986 + { /* Logitech lightspeed receiver (0xc543) */ 1987 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 1988 + USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2), 1989 + .driver_data = recvr_type_gaming_hidpp}, 1986 1990 1987 1991 { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */ 1988 1992 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
+2
drivers/hid/hid-logitech-hidpp.c
··· 4596 4596 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC094) }, 4597 4597 { /* Logitech G Pro X Superlight 2 Gaming Mouse over USB */ 4598 4598 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC09b) }, 4599 + { /* Logitech G PRO 2 LIGHTSPEED Wireless Mouse over USB */ 4600 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xc09a) }, 4599 4601 4600 4602 { /* G935 Gaming Headset */ 4601 4603 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87),
+4
drivers/hid/hid-mcp2221.c
··· 906 906 } 907 907 if (data[2] == MCP2221_I2C_READ_COMPL || 908 908 data[2] == MCP2221_I2C_READ_PARTIAL) { 909 + if (!mcp->rxbuf || mcp->rxbuf_idx < 0 || data[3] > 60) { 910 + mcp->status = -EINVAL; 911 + break; 912 + } 909 913 buf = mcp->rxbuf; 910 914 memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]); 911 915 mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];
+8
drivers/hid/hid-multitouch.c
··· 1503 1503 if (hdev->vendor == I2C_VENDOR_ID_GOODIX && 1504 1504 (hdev->product == I2C_DEVICE_ID_GOODIX_01E8 || 1505 1505 hdev->product == I2C_DEVICE_ID_GOODIX_01E9)) { 1506 + if (*size < 608) { 1507 + dev_info( 1508 + &hdev->dev, 1509 + "GT7868Q fixup: report descriptor is only %u bytes, skipping\n", 1510 + *size); 1511 + return rdesc; 1512 + } 1513 + 1506 1514 if (rdesc[607] == 0x15) { 1507 1515 rdesc[607] = 0x25; 1508 1516 dev_info(
+3
drivers/hid/hid-ntrig.c
··· 144 144 struct usb_device *usb_dev = hid_to_usb_dev(hdev); 145 145 unsigned char *data = kmalloc(8, GFP_KERNEL); 146 146 147 + if (!hid_is_usb(hdev)) 148 + return; 149 + 147 150 if (!data) 148 151 goto err_free; 149 152
+3
drivers/hid/hid-quirks.c
··· 124 124 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT }, 125 125 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_T609A), HID_QUIRK_MULTI_INPUT }, 126 126 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE), HID_QUIRK_ALWAYS_POLL }, 127 + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_LEGION_GO_DUAL_DINPUT), HID_QUIRK_MULTI_INPUT }, 128 + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_LEGION_GO2_DUAL_DINPUT), HID_QUIRK_MULTI_INPUT }, 127 129 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E), HID_QUIRK_ALWAYS_POLL }, 128 130 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL }, 129 131 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL }, ··· 413 411 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) }, 414 412 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, 415 413 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, 414 + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT2DRBK) }, 416 415 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK_010C) }, 417 416 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK_019B) }, 418 417 { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) },
-3
drivers/hid/intel-ish-hid/ipc/pci-ish.c
··· 264 264 265 265 static struct device __maybe_unused *ish_resume_device; 266 266 267 - /* 50ms to get resume response */ 268 - #define WAIT_FOR_RESUME_ACK_MS 50 269 - 270 267 /** 271 268 * ish_resume_handler() - Work function to complete resume 272 269 * @work: work struct
+3
drivers/hid/intel-ish-hid/ishtp-hid-client.c
··· 759 759 if (ishtp_wait_resume(ishtp_get_ishtp_device(hid_ishtp_cl))) { 760 760 client_data->suspended = false; 761 761 wake_up_interruptible(&client_data->ishtp_resume_wait); 762 + } else { 763 + hid_ishtp_trace(client_data, "hid client: wait for resume timed out"); 764 + dev_err(cl_data_to_dev(client_data), "wait for resume timed out"); 762 765 } 763 766 } 764 767
-3
drivers/hid/intel-ish-hid/ishtp/bus.c
··· 852 852 */ 853 853 bool ishtp_wait_resume(struct ishtp_device *dev) 854 854 { 855 - /* 50ms to get resume response */ 856 - #define WAIT_FOR_RESUME_ACK_MS 50 857 - 858 855 /* Waiting to get resume response */ 859 856 if (dev->resume_flag) 860 857 wait_event_interruptible_timeout(dev->resume_wait,
+3
drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
··· 47 47 48 48 #define MAX_DMA_DELAY 20 49 49 50 + /* 300ms to get resume response */ 51 + #define WAIT_FOR_RESUME_ACK_MS 300 52 + 50 53 /* ISHTP device states */ 51 54 enum ishtp_dev_state { 52 55 ISHTP_DEV_INITIALIZING = 0,
+1
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
··· 419 419 */ 420 420 static void quicki2c_dev_deinit(struct quicki2c_device *qcdev) 421 421 { 422 + thc_interrupt_quiesce(qcdev->thc_hw, true); 422 423 thc_interrupt_enable(qcdev->thc_hw, false); 423 424 thc_ltr_unconfig(qcdev->thc_hw); 424 425 thc_wot_unconfig(qcdev->thc_hw);
+2
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
··· 77 77 u16 device_address; 78 78 u64 connection_speed; 79 79 u8 addressing_mode; 80 + u8 reserved; 80 81 } __packed; 81 82 82 83 /** ··· 127 126 u64 HMTD; 128 127 u64 HMRD; 129 128 u64 HMSL; 129 + u8 reserved; 130 130 }; 131 131 132 132 /**
+2 -2
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c
··· 1540 1540 1541 1541 for (int i = 0; i < ARRAY_SIZE(i2c_subip_regs); i++) { 1542 1542 ret = thc_i2c_subip_pio_read(dev, i2c_subip_regs[i], 1543 - &read_size, (u32 *)&dev->i2c_subip_regs + i); 1543 + &read_size, &dev->i2c_subip_regs[i]); 1544 1544 if (ret < 0) 1545 1545 return ret; 1546 1546 } ··· 1563 1563 1564 1564 for (int i = 0; i < ARRAY_SIZE(i2c_subip_regs); i++) { 1565 1565 ret = thc_i2c_subip_pio_write(dev, i2c_subip_regs[i], 1566 - write_size, (u32 *)&dev->i2c_subip_regs + i); 1566 + write_size, &dev->i2c_subip_regs[i]); 1567 1567 if (ret < 0) 1568 1568 return ret; 1569 1569 }
+1
drivers/hid/wacom_wac.c
··· 684 684 case 0x885: /* Intuos3 Marker Pen */ 685 685 case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ 686 686 case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */ 687 + case 0x204: /* Art Pen 2 */ 687 688 is_art_pen = true; 688 689 break; 689 690 }