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.

HID: huawei: fix CD30 keyboard report descriptor issue

When the Huawei CD30 USB keyboard undergoes 500 reboot cycles,
initialization may fail due to a report descriptor problem.
The error log is as follows:
[pid:175,cpu0,kworker/0:1,6]usb 1-1.2.2: new low-speed USB device number 6 using xhci-hcd
[pid:175,cpu0,kworker/0:1,9]usb 1-1.2.2: New USB device found, idVendor=12d1, idProduct=109b, bcdDevice= 1.03
[pid:175,cpu0,kworker/0:1,0]usb 1-1.2.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[pid:175,cpu0,kworker/0:1,1]usb 1-1.2.2: Product: HUAWEI USB Wired Keyboard
[pid:175,cpu0,kworker/0:1,2]usb 1-1.2.2: Manufacturer: HUAWEI
[pid:175,cpu0,kworker/0:1,4]input: HUAWEI HUAWEI USB Wired Keyboard as /devices/platform/efc00000.hisi_usb/efc00000.dwc3/xhci-hcd.1.auto/usb1/1-1/1-1.2/1-1.2.2/1-1.2.2:1.0/0003:12D1:109B.0002/input/input6
[pid:175,cpu0,kworker/0:1,5]hid-generic 0003:12D1:109B.0002: input,hidraw1: USB HID v1.10 Keyboard [HUAWEI HUAWEI USB Wired Keyboard] on usb-xhci-hcd.1.auto-1.2.2/input0
[pid:175,cpu0,kworker/0:1,9]hid-generic 0003:12D1:109B.0003: collection stack underflow
[pid:175,cpu0,kworker/0:1,0]hid-generic 0003:12D1:109B.0003: item 0 0 0 12 parsing failed
[pid:175,cpu0,kworker/0:1,1]hid-generic: probe of 0003:12D1:109B.0003 failed with error -22
...
When encountering such a situation, fix it with the correct report descriptor.

Signed-off-by: Miao Li <limiao@kylinos.cn>
Signed-off-by: Jiri Kosina <jkosina@suse.com>

authored by

Miao Li and committed by
Jiri Kosina
e93faaca 82a4fc46

+93
+7
drivers/hid/Kconfig
··· 1435 1435 1436 1436 If in doubt, say "N". 1437 1437 1438 + config HID_HUAWEI 1439 + tristate "Huawei HID devices support" 1440 + depends on USB_HID 1441 + help 1442 + Support for huawei cd30 keyboard or other hid devices 1443 + that need fix-ups to work properly. 1444 + 1438 1445 endmenu 1439 1446 1440 1447 source "drivers/hid/bpf/Kconfig"
+1
drivers/hid/Makefile
··· 152 152 obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o 153 153 obj-$(CONFIG_HID_VIEWSONIC) += hid-viewsonic.o 154 154 obj-$(CONFIG_HID_VRC2) += hid-vrc2.o 155 + obj-$(CONFIG_HID_HUAWEI) += hid-huawei.o 155 156 156 157 wacom-objs := wacom_wac.o wacom_sys.o 157 158 obj-$(CONFIG_HID_WACOM) += wacom.o
+82
drivers/hid/hid-huawei.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * HID driver for some huawei "special" devices 4 + * 5 + * Copyright (c) 2026 Miao Li <limiao@kylinos.cn> 6 + */ 7 + 8 + #include <linux/device.h> 9 + #include <linux/hid.h> 10 + #include <linux/module.h> 11 + #include <linux/usb.h> 12 + 13 + #include "hid-ids.h" 14 + 15 + static const __u8 huawei_cd30_kbd_rdesc_fixed[] = { 16 + 0x05, 0x01, /* Usage Page (Generic Desktop) */ 17 + 0x09, 0x80, /* Usage (System Control) */ 18 + 0xa1, 0x01, /* Collection (Application) */ 19 + 0x85, 0x01, /* Report ID (1) */ 20 + 0x19, 0x81, /* Usage Minimum (System Power Down) */ 21 + 0x29, 0x83, /* Usage Maximum (System Wake Up) */ 22 + 0x15, 0x00, /* Logical Minimum (0) */ 23 + 0x25, 0x01, /* Logical Maximum (1) */ 24 + 0x75, 0x01, /* Report Size (1 bit) */ 25 + 0x95, 0x03, /* Report Count (3) */ 26 + 0x81, 0x02, /* Input (Data,Var,Abs) */ 27 + 0x95, 0x05, /* Report Count (5) */ 28 + 0x81, 0x01, /* Input (Cnst,Ary,Abs) */ 29 + 0xc0, /* End Collection */ 30 + 0x05, 0x0c, /* Usage Page (Consumer) */ 31 + 0x09, 0x01, /* Usage (Consumer Control) */ 32 + 0xa1, 0x01, /* Collection (Application) */ 33 + 0x85, 0x02, /* Report ID (2) */ 34 + 0x19, 0x00, /* Usage Minimum (0) */ 35 + 0x2a, 0x3c, 0x02, /* Usage Maximum (0x023C) */ 36 + 0x15, 0x00, /* Logical Minimum (0) */ 37 + 0x26, 0x3c, 0x02, /* Logical Maximum (0x023C) */ 38 + 0x95, 0x01, /* Report Count (1) */ 39 + 0x75, 0x10, /* Report Size (16 bits) */ 40 + 0x81, 0x00, /* Input (Data,Ary,Abs) */ 41 + 0xc0 /* End Collection */ 42 + }; 43 + 44 + static const __u8 *huawei_report_fixup(struct hid_device *hdev, __u8 *rdesc, 45 + unsigned int *rsize) 46 + { 47 + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 48 + 49 + switch (hdev->product) { 50 + case USB_DEVICE_ID_HUAWEI_CD30KBD: 51 + if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { 52 + if (*rsize != sizeof(huawei_cd30_kbd_rdesc_fixed) || 53 + memcmp(huawei_cd30_kbd_rdesc_fixed, rdesc, 54 + sizeof(huawei_cd30_kbd_rdesc_fixed)) != 0) { 55 + hid_info(hdev, "Replacing Huawei cd30 keyboard report descriptor.\n"); 56 + *rsize = sizeof(huawei_cd30_kbd_rdesc_fixed); 57 + return huawei_cd30_kbd_rdesc_fixed; 58 + } 59 + } 60 + break; 61 + } 62 + 63 + return rdesc; 64 + } 65 + 66 + static const struct hid_device_id huawei_devices[] = { 67 + /* HUAWEI cd30 keyboard */ 68 + { HID_USB_DEVICE(USB_VENDOR_ID_HUAWEI, USB_DEVICE_ID_HUAWEI_CD30KBD)}, 69 + { } 70 + }; 71 + MODULE_DEVICE_TABLE(hid, huawei_devices); 72 + 73 + static struct hid_driver huawei_driver = { 74 + .name = "huawei", 75 + .id_table = huawei_devices, 76 + .report_fixup = huawei_report_fixup, 77 + }; 78 + module_hid_driver(huawei_driver); 79 + 80 + MODULE_LICENSE("GPL"); 81 + MODULE_AUTHOR("Miao Li <limiao@kylinos.cn>"); 82 + MODULE_DESCRIPTION("HID driver for some huawei \"special\" devices");
+3
drivers/hid/hid-ids.h
··· 1587 1587 #define USB_VENDOR_ID_JIELI_SDK_DEFAULT 0x4c4a 1588 1588 #define USB_DEVICE_ID_JIELI_SDK_4155 0x4155 1589 1589 1590 + #define USB_VENDOR_ID_HUAWEI 0x12d1 1591 + #define USB_DEVICE_ID_HUAWEI_CD30KBD 0x109b 1592 + 1590 1593 #endif