usb: gadget: composite: fix OS descriptors w_value logic
authorPeter Korsgaard <peter@korsgaard.com>
Thu, 4 Apr 2024 10:06:35 +0000 (12:06 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Apr 2024 23:11:48 +0000 (16:11 -0700)
The OS descriptors logic had the high/low byte of w_value inverted, causing
the extended properties to not be accessible for interface != 0.

>From the Microsoft documentation:
https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-os-1-0-descriptors-specification

OS_Desc_CompatID.doc (w_index = 0x4):

- wValue:

  High Byte = InterfaceNumber.  InterfaceNumber is set to the number of the
  interface or function that is associated with the descriptor, typically
  0x00.  Because a device can have only one extended compat ID descriptor,
  it should ignore InterfaceNumber, regardless of the value, and simply
  return the descriptor.

  Low Byte = 0.  PageNumber is used to retrieve descriptors that are larger
  than 64 KB.  The header section is 16 bytes, so PageNumber is set to 0 for
  this request.

We currently do not support >64KB compat ID descriptors, so verify that the
low byte is 0.

OS_Desc_Ext_Prop.doc (w_index = 0x5):

- wValue:

  High byte = InterfaceNumber.  The high byte of wValue is set to the number
  of the interface or function that is associated with the descriptor.

  Low byte = PageNumber.  The low byte of wValue is used to retrieve
  descriptors that are larger than 64 KB.  The header section is 10 bytes, so
  PageNumber is set to 0 for this request.

We also don't support >64KB extended properties, so verify that the low byte
is 0 and use the high byte for the interface number.

Fixes: 37a3a533429e ("usb: gadget: OS Feature Descriptors support")
Cc: stable <stable@kernel.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
Link: https://lore.kernel.org/r/20240404100635.3215340-1-peter@korsgaard.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/composite.c

index 0ace45b66a31c417f7e6da9f811c3d8b5c736246..0e151b54aae82a3677dbbd0487d91e403f83e7b5 100644 (file)
@@ -2112,7 +2112,7 @@ unknown:
                        buf[5] = 0x01;
                        switch (ctrl->bRequestType & USB_RECIP_MASK) {
                        case USB_RECIP_DEVICE:
-                               if (w_index != 0x4 || (w_value >> 8))
+                               if (w_index != 0x4 || (w_value & 0xff))
                                        break;
                                buf[6] = w_index;
                                /* Number of ext compat interfaces */
@@ -2128,9 +2128,9 @@ unknown:
                                }
                                break;
                        case USB_RECIP_INTERFACE:
-                               if (w_index != 0x5 || (w_value >> 8))
+                               if (w_index != 0x5 || (w_value & 0xff))
                                        break;
-                               interface = w_value & 0xFF;
+                               interface = w_value >> 8;
                                if (interface >= MAX_CONFIG_INTERFACES ||
                                    !os_desc_cfg->interface[interface])
                                        break;