]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: core: new quirk to handle devices with zero configurations
authorJie Deng <dengjie03@kylinos.cn>
Fri, 27 Feb 2026 08:49:31 +0000 (16:49 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 11 Mar 2026 15:17:19 +0000 (16:17 +0100)
Some USB devices incorrectly report bNumConfigurations as 0 in their
device descriptor, which causes the USB core to reject them during
enumeration.
logs:
usb 1-2: device descriptor read/64, error -71
usb 1-2: no configurations
usb 1-2: can't read configurations, error -22

However, these devices actually work correctly when
treated as having a single configuration.

Add a new quirk USB_QUIRK_FORCE_ONE_CONFIG to handle such devices.
When this quirk is set, assume the device has 1 configuration instead
of failing with -EINVAL.

This quirk is applied to the device with VID:PID 5131:2007 which
exhibits this behavior.

Signed-off-by: Jie Deng <dengjie03@kylinos.cn>
Link: https://patch.msgid.link/20260227084931.1527461-1-dengjie03@kylinos.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/admin-guide/kernel-parameters.txt
drivers/usb/core/config.c
drivers/usb/core/quirks.c
include/linux/usb/quirks.h

index cb850e5290c2ba9404a4bcbeb07d89c439e287c4..7d907efe9f49403e71eb02c774b27872c0627eaa 100644 (file)
@@ -8183,6 +8183,9 @@ Kernel parameters
                                p = USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT
                                        (Reduce timeout of the SET_ADDRESS
                                        request from 5000 ms to 500 ms);
+                               q = USB_QUIRK_FORCE_ONE_CONFIG (Device
+                                       claims zero configurations,
+                                       forcing to 1);
                        Example: quirks=0781:5580:bk,0a5c:5834:gij
 
        usbhid.mousepoll=
index 1cd5fa61dc76c10550afc68c3757b8b6952c9ae3..6a1fd967e0a643a823b9c74691dae41f469c96cd 100644 (file)
@@ -927,7 +927,11 @@ int usb_get_configuration(struct usb_device *dev)
                dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
        }
 
-       if (ncfg < 1) {
+       if (ncfg < 1 && dev->quirks & USB_QUIRK_FORCE_ONE_CONFIG) {
+               dev_info(ddev, "Device claims zero configurations, forcing to 1\n");
+               dev->descriptor.bNumConfigurations = 1;
+               ncfg = 1;
+       } else if (ncfg < 1) {
                dev_err(ddev, "no configurations\n");
                return -EINVAL;
        }
index e347236d83e8d5888ab3800ff066ac212f1fc7cc..7bd408db05f4ba67cbee9f9c3d9f7a6f258da37d 100644 (file)
@@ -140,6 +140,8 @@ static int quirks_param_set(const char *value, const struct kernel_param *kp)
                        case 'p':
                                flags |= USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT;
                                break;
+                       case 'q':
+                               flags |= USB_QUIRK_FORCE_ONE_CONFIG;
                        /* Ignore unrecognized flag characters */
                        }
                }
@@ -589,6 +591,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* VCOM device */
        { USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },
 
+       /* Noji-MCS SmartCard Reader */
+       { USB_DEVICE(0x5131, 0x2007), .driver_info = USB_QUIRK_FORCE_ONE_CONFIG },
+
        /* INTEL VALUE SSD */
        { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
 
index 2f7bd2fdc6164b7d0ff3fd56b4f1ba7b5f496e05..b3cc7beab4a3ceb695d8e404ff2e646545d2c230 100644 (file)
@@ -78,4 +78,7 @@
 /* skip BOS descriptor request */
 #define USB_QUIRK_NO_BOS                       BIT(17)
 
+/* Device claims zero configurations, forcing to 1 */
+#define USB_QUIRK_FORCE_ONE_CONFIG             BIT(18)
+
 #endif /* __LINUX_USB_QUIRKS_H */