config->fullspeed = 1;
if (!config->highspeed && function->hs_descriptors)
config->highspeed = 1;
+ if (!config->superspeed && function->ss_descriptors)
+ config->superspeed = 1;
done:
if (value)
/* add each function's descriptors */
list_for_each_entry(f, &config->functions, list) {
- if (speed == USB_SPEED_HIGH)
+ if (speed == USB_SPEED_SUPER)
+ descriptors = f->ss_descriptors;
+ else if (speed == USB_SPEED_HIGH)
descriptors = f->hs_descriptors;
else
descriptors = f->descriptors;
struct usb_configuration *c;
struct list_head *pos;
- if (gadget_is_dualspeed(gadget)) {
+ if (gadget_is_superspeed(gadget)) {
+ speed = gadget->speed;
+ } else if (gadget_is_dualspeed(gadget)) {
if (gadget->speed == USB_SPEED_HIGH)
hs = 1;
if (type == USB_DT_OTHER_SPEED_CONFIG)
continue;
check_config:
- if (speed == USB_SPEED_HIGH) {
+ if (speed == USB_SPEED_SUPER) {
+ if (!c->superspeed)
+ continue;
+ } else if (speed == USB_SPEED_HIGH) {
if (!c->highspeed)
continue;
} else {
struct usb_gadget *gadget = cdev->gadget;
unsigned count = 0;
int hs = 0;
+ int ss = 0;
struct usb_configuration *c;
+ if (gadget->speed == USB_SPEED_SUPER)
+ ss = 1;
+
if (gadget_is_dualspeed(gadget)) {
if (gadget->speed == USB_SPEED_HIGH)
hs = 1;
}
list_for_each_entry(c, &cdev->configs, list) {
/* ignore configs that won't work at this speed */
- if (hs) {
+ if (ss) {
+ if (!c->superspeed)
+ continue;
+ } else if (hs) {
if (!c->highspeed)
continue;
} else {
case USB_SPEED_HIGH:
speed = "high";
break;
+ case USB_SPEED_SUPER:
+ speed = "super";
+ break;
default:
speed = "?";
break;
* function's setup callback instead of the current
* configuration's setup callback.
*/
- if (gadget->speed == USB_SPEED_HIGH)
+ if (gadget->speed == USB_SPEED_SUPER)
+ descriptors = f->ss_descriptors;
+ else if (gadget->speed == USB_SPEED_HIGH)
descriptors = f->hs_descriptors;
else
descriptors = f->descriptors;
list_del(&config->list);
config->cdev = NULL;
} else {
- debug("cfg %d/%p speeds:%s%s\n",
+ debug("cfg %d/%p speeds:%s%s%s\n",
config->bConfigurationValue, config,
+ config->superspeed ? " super" : "",
config->highspeed ? " high" : "",
config->fullspeed
? (gadget_is_dualspeed(cdev->gadget)
static int bos_desc(struct usb_composite_dev *cdev)
{
struct usb_ext_cap_descriptor *usb_ext;
+ struct usb_dcd_config_params dcd_config_params;
struct usb_bos_descriptor *bos = cdev->req->buf;
bos->bLength = USB_DT_BOS_SIZE;
USB_HIGH_SPEED_OPERATION |
USB_5GBPS_OPERATION);
ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
- ss_cap->bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
- ss_cap->bU2DevExitLat =
- cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+
+ /* 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;
}
return le16_to_cpu(bos->wTotalLength);
}
cdev->desc.bNumConfigurations =
count_configs(cdev, USB_DT_DEVICE);
- /*
- * If the speed is Super speed, then the supported
- * max packet size is 512 and it should be sent as
- * exponent of 2. So, 9(2^9=512) should be filled in
- * bMaxPacketSize0. Also fill USB version as 3.0
- * if speed is Super speed.
- */
- if (cdev->gadget->speed == USB_SPEED_SUPER) {
+ cdev->desc.bMaxPacketSize0 =
+ cdev->gadget->ep0->maxpacket;
+ if (gadget->speed >= USB_SPEED_SUPER) {
+ cdev->desc.bcdUSB = cpu_to_le16(0x0310);
cdev->desc.bMaxPacketSize0 = 9;
- cdev->desc.bcdUSB = cpu_to_le16(0x0300);
} else {
- cdev->desc.bMaxPacketSize0 =
- cdev->gadget->ep0->maxpacket;
+ cdev->desc.bcdUSB = cpu_to_le16(0x0200);
}
value = min(w_length, (u16) sizeof cdev->desc);
memcpy(req->buf, &cdev->desc, value);
break;
case USB_DT_DEVICE_QUALIFIER:
- if (!gadget_is_dualspeed(gadget))
+ if (!gadget_is_dualspeed(gadget) ||
+ gadget->speed >= USB_SPEED_SUPER)
break;
device_qual(cdev);
value = min_t(int, w_length,
sizeof(struct usb_qualifier_descriptor));
break;
case USB_DT_OTHER_SPEED_CONFIG:
- if (!gadget_is_dualspeed(gadget))
+ if (!gadget_is_dualspeed(gadget) ||
+ gadget->speed >= USB_SPEED_SUPER)
break;
case USB_DT_CONFIG:
value = min(w_length, (u16) value);
break;
case USB_DT_BOS:
- if (gadget_is_superspeed(cdev->gadget))
+ /*
+ * Super speed connection should support BOS, and
+ * USB compliance test (USB 2.0 Command Verifier)
+ * also issues this request, return for now for
+ * USB 2.0 connection.
+ */
+ if (gadget->speed >= USB_SPEED_SUPER) {
value = bos_desc(cdev);
- if (value >= 0)
value = min(w_length, (u16)value);
+ }
break;
default:
goto unknown;
}
static struct usb_gadget_driver composite_driver = {
- .speed = USB_SPEED_HIGH,
+ .speed = USB_SPEED_SUPER,
.bind = composite_bind,
.unbind = composite_unbind,