From 0b67a6be14be5fb050b0358022c497d0619ebc40 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 28 Apr 2017 12:55:14 +0400 Subject: usb: gadget: composite: Exclude SS Dev Cap Desc Don't send the SuperSpeed USB Device Capability descriptor if the gadget is not capable of SuperSpeed. Signed-off-by: John Youn Signed-off-by: Sevak Arakelyan Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 51 +++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'drivers/usb/gadget/composite.c') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 49d685ad0da9..abec93ab81ee 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -607,7 +607,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; @@ -633,29 +632,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)) { -- cgit v1.2.3 From a9548c55295a4268f9187e1ec93264a0682fa745 Mon Sep 17 00:00:00 2001 From: John Youn Date: Fri, 28 Apr 2017 12:55:20 +0400 Subject: usb: gadget: Allow a non-SuperSpeed gadget to support LPM This commit allows a gadget that does not support SuperSpeed to indicate that it supports LPM. It does this by setting the 'lpm_capable' flag in the gadget structure. If a gadget sets this, the composite gadget framework will set the bcdUSB to 0x0201 to indicate that this supports BOS descriptors, and also return a USB 2.0 Extension descriptor as part of the BOS descriptor set. See USB 2.0 LPM ECN Section 3. Signed-off-by: John Youn Signed-off-by: Sevak Arakelyan Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 8 ++++++-- include/linux/usb/gadget.h | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/usb/gadget/composite.c') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index abec93ab81ee..d62f53d7f418 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1608,7 +1608,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); @@ -1639,7 +1642,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); } diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index fbc22a39e7bc..3ee5f2a7c0b4 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -352,6 +352,8 @@ struct usb_gadget_ops { * @deactivated: True if gadget is deactivated - in deactivated state it cannot * be connected. * @connected: True if gadget is connected. + * @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag + * indicates that it supports LPM as per the LPM ECN & errata. * * Gadgets have a mostly-portable "gadget driver" implementing device * functions, handling all usb configurations and interfaces. Gadget @@ -404,6 +406,7 @@ struct usb_gadget { unsigned is_selfpowered:1; unsigned deactivated:1; unsigned connected:1; + unsigned lpm_capable:1; }; #define work_to_gadget(w) (container_of((w), struct usb_gadget, work)) -- cgit v1.2.3