|
@@ -905,14 +905,25 @@ void usb_release_bos_descriptor(struct usb_device *dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static const __u8 bos_desc_len[256] = {
|
|
|
+ [USB_CAP_TYPE_WIRELESS_USB] = USB_DT_USB_WIRELESS_CAP_SIZE,
|
|
|
+ [USB_CAP_TYPE_EXT] = USB_DT_USB_EXT_CAP_SIZE,
|
|
|
+ [USB_SS_CAP_TYPE] = USB_DT_USB_SS_CAP_SIZE,
|
|
|
+ [USB_SSP_CAP_TYPE] = USB_DT_USB_SSP_CAP_SIZE(1),
|
|
|
+ [CONTAINER_ID_TYPE] = USB_DT_USB_SS_CONTN_ID_SIZE,
|
|
|
+ [USB_PTM_CAP_TYPE] = USB_DT_USB_PTM_ID_SIZE,
|
|
|
+};
|
|
|
+
|
|
|
/* Get BOS descriptor set */
|
|
|
int usb_get_bos_descriptor(struct usb_device *dev)
|
|
|
{
|
|
|
struct device *ddev = &dev->dev;
|
|
|
struct usb_bos_descriptor *bos;
|
|
|
struct usb_dev_cap_header *cap;
|
|
|
+ struct usb_ssp_cap_descriptor *ssp_cap;
|
|
|
unsigned char *buffer;
|
|
|
- int length, total_len, num, i;
|
|
|
+ int length, total_len, num, i, ssac;
|
|
|
+ __u8 cap_type;
|
|
|
int ret;
|
|
|
|
|
|
bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
|
|
@@ -965,7 +976,13 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
|
|
dev->bos->desc->bNumDeviceCaps = i;
|
|
|
break;
|
|
|
}
|
|
|
+ cap_type = cap->bDevCapabilityType;
|
|
|
length = cap->bLength;
|
|
|
+ if (bos_desc_len[cap_type] && length < bos_desc_len[cap_type]) {
|
|
|
+ dev->bos->desc->bNumDeviceCaps = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
total_len -= length;
|
|
|
|
|
|
if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
|
|
@@ -973,7 +990,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- switch (cap->bDevCapabilityType) {
|
|
|
+ switch (cap_type) {
|
|
|
case USB_CAP_TYPE_WIRELESS_USB:
|
|
|
/* Wireless USB cap descriptor is handled by wusb */
|
|
|
break;
|
|
@@ -986,8 +1003,11 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
|
|
(struct usb_ss_cap_descriptor *)buffer;
|
|
|
break;
|
|
|
case USB_SSP_CAP_TYPE:
|
|
|
- dev->bos->ssp_cap =
|
|
|
- (struct usb_ssp_cap_descriptor *)buffer;
|
|
|
+ ssp_cap = (struct usb_ssp_cap_descriptor *)buffer;
|
|
|
+ ssac = (le32_to_cpu(ssp_cap->bmAttributes) &
|
|
|
+ USB_SSP_SUBLINK_SPEED_ATTRIBS) + 1;
|
|
|
+ if (length >= USB_DT_USB_SSP_CAP_SIZE(ssac))
|
|
|
+ dev->bos->ssp_cap = ssp_cap;
|
|
|
break;
|
|
|
case CONTAINER_ID_TYPE:
|
|
|
dev->bos->ss_id =
|