usb: gadget: Update config for SuperSpeedPlus
[deliverable/linux.git] / drivers / usb / gadget / composite.c
index 8b14c2a13ac51abc9d3f433a0261c599ec8cdaf6..560330f5457c02f589c33e5de2f8a119e8db8768 100644 (file)
@@ -237,6 +237,8 @@ int usb_add_function(struct usb_configuration *config,
                config->highspeed = true;
        if (!config->superspeed && function->ss_descriptors)
                config->superspeed = true;
+       if (!config->superspeed_plus && function->ssp_descriptors)
+               config->superspeed_plus = true;
 
 done:
        if (value)
@@ -597,6 +599,48 @@ static int bos_desc(struct usb_composite_dev *cdev)
        ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
        ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
 
+       /* The SuperSpeedPlus USB Device Capability descriptor */
+       if (gadget_is_superspeed_plus(cdev->gadget)) {
+               struct usb_ssp_cap_descriptor *ssp_cap;
+
+               ssp_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
+               bos->bNumDeviceCaps++;
+
+               /*
+                * Report typical values.
+                */
+
+               le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SSP_CAP_SIZE(1));
+               ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(1);
+               ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
+               ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE;
+
+               /* SSAC = 1 (2 attributes) */
+               ssp_cap->bmAttributes = cpu_to_le32(1);
+
+               /* Min RX/TX Lane Count = 1 */
+               ssp_cap->wFunctionalitySupport = (1 << 8) | (1 << 12);
+
+               /*
+                * bmSublinkSpeedAttr[0]:
+                *   ST  = Symmetric, RX
+                *   LSE =  3 (Gbps)
+                *   LP  =  1 (SuperSpeedPlus)
+                *   LSM = 10 (10 Gbps)
+                */
+               ssp_cap->bmSublinkSpeedAttr[0] =
+                       (3 << 4) | (1 << 14) | (0xa << 16);
+               /*
+                * bmSublinkSpeedAttr[1] =
+                *   ST  = Symmetric, TX
+                *   LSE =  3 (Gbps)
+                *   LP  =  1 (SuperSpeedPlus)
+                *   LSM = 10 (10 Gbps)
+                */
+               ssp_cap->bmSublinkSpeedAttr[1] =
+                       (3 << 4) | (1 << 14) | (0xa << 16) | (1 << 7);
+       }
+
        return le16_to_cpu(bos->wTotalLength);
 }
 
@@ -1499,7 +1543,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                                cdev->gadget->ep0->maxpacket;
                        if (gadget_is_superspeed(gadget)) {
                                if (gadget->speed >= USB_SPEED_SUPER) {
-                                       cdev->desc.bcdUSB = cpu_to_le16(0x0300);
+                                       cdev->desc.bcdUSB = cpu_to_le16(0x0310);
                                        cdev->desc.bMaxPacketSize0 = 9;
                                } else {
                                        cdev->desc.bcdUSB = cpu_to_le16(0x0210);
This page took 0.027989 seconds and 5 git commands to generate.