]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/usb/gadget/composite.c
Merge tag 'usb-for-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi...
[mirror_ubuntu-artful-kernel.git] / drivers / usb / gadget / composite.c
index 45b554032332e882e9bc99cb5489044053bd663c..dd74c99d6ce15f6a961d095f82c4a29bb560dc50 100644 (file)
@@ -610,7 +610,6 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
 static int bos_desc(struct usb_composite_dev *cdev)
 {
        struct usb_ext_cap_descriptor   *usb_ext;
-       struct usb_ss_cap_descriptor    *ss_cap;
        struct usb_dcd_config_params    dcd_config_params;
        struct usb_bos_descriptor       *bos = cdev->req->buf;
 
@@ -636,29 +635,35 @@ static int bos_desc(struct usb_composite_dev *cdev)
         * The Superspeed USB Capability descriptor shall be implemented by all
         * SuperSpeed devices.
         */
-       ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
-       bos->bNumDeviceCaps++;
-       le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
-       ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
-       ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
-       ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
-       ss_cap->bmAttributes = 0; /* LTM is not supported yet */
-       ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
-                               USB_FULL_SPEED_OPERATION |
-                               USB_HIGH_SPEED_OPERATION |
-                               USB_5GBPS_OPERATION);
-       ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
-
-       /* Get Controller configuration */
-       if (cdev->gadget->ops->get_config_params)
-               cdev->gadget->ops->get_config_params(&dcd_config_params);
-       else {
-               dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
-               dcd_config_params.bU2DevExitLat =
-                       cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+       if (gadget_is_superspeed(cdev->gadget)) {
+               struct usb_ss_cap_descriptor *ss_cap;
+
+               ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
+               bos->bNumDeviceCaps++;
+               le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
+               ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
+               ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
+               ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
+               ss_cap->bmAttributes = 0; /* LTM is not supported yet */
+               ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
+                                                     USB_FULL_SPEED_OPERATION |
+                                                     USB_HIGH_SPEED_OPERATION |
+                                                     USB_5GBPS_OPERATION);
+               ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
+
+               /* Get Controller configuration */
+               if (cdev->gadget->ops->get_config_params) {
+                       cdev->gadget->ops->get_config_params(
+                               &dcd_config_params);
+               } else {
+                       dcd_config_params.bU1devExitLat =
+                               USB_DEFAULT_U1_DEV_EXIT_LAT;
+                       dcd_config_params.bU2DevExitLat =
+                               cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+               }
+               ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
+               ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
        }
-       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)) {
@@ -1602,7 +1607,10 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                                        cdev->desc.bcdUSB = cpu_to_le16(0x0210);
                                }
                        } else {
-                               cdev->desc.bcdUSB = cpu_to_le16(0x0200);
+                               if (gadget->lpm_capable)
+                                       cdev->desc.bcdUSB = cpu_to_le16(0x0201);
+                               else
+                                       cdev->desc.bcdUSB = cpu_to_le16(0x0200);
                        }
 
                        value = min(w_length, (u16) sizeof cdev->desc);
@@ -1633,7 +1641,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                                value = min(w_length, (u16) value);
                        break;
                case USB_DT_BOS:
-                       if (gadget_is_superspeed(gadget)) {
+                       if (gadget_is_superspeed(gadget) ||
+                           gadget->lpm_capable) {
                                value = bos_desc(cdev);
                                value = min(w_length, (u16) value);
                        }