usb: gadget: composite: Count configs for SuperSpeedPlus
[deliverable/linux.git] / drivers / usb / gadget / composite.c
index 8b14c2a13ac51abc9d3f433a0261c599ec8cdaf6..44ad7aa6f8f1beaaa104578336bbce6cf6c5007d 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)
@@ -509,18 +511,24 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
        unsigned                        count = 0;
        int                             hs = 0;
        int                             ss = 0;
+       int                             ssp = 0;
 
        if (gadget_is_dualspeed(gadget)) {
                if (gadget->speed == USB_SPEED_HIGH)
                        hs = 1;
                if (gadget->speed == USB_SPEED_SUPER)
                        ss = 1;
+               if (gadget->speed == USB_SPEED_SUPER_PLUS)
+                       ssp = 1;
                if (type == USB_DT_DEVICE_QUALIFIER)
                        hs = !hs;
        }
        list_for_each_entry(c, &cdev->configs, list) {
                /* ignore configs that won't work at this speed */
-               if (ss) {
+               if (ssp) {
+                       if (!c->superspeed_plus)
+                               continue;
+               } else if (ss) {
                        if (!c->superspeed)
                                continue;
                } else if (hs) {
@@ -597,6 +605,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 +1549,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.027404 seconds and 5 git commands to generate.