usb: usbtest: support usb2 extension descriptor test

In Test 9 of usbtest module, it is used for performing chapter 9 tests N
times.

USB2.0 Extension descriptor is one of the generic device-level capbility
descriptors which added in section 9.6.2.1 of USB 3.0 spec.

This patch adds to support getting usb2.0 extension descriptor test
scenario for USB 3.0.

Signed-off-by: Huang Rui <ray.huang@amd.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Huang Rui 2013-10-30 11:27:38 +08:00 committed by Greg Kroah-Hartman
parent c2ec3a732a
commit 82f92672ac
1 changed files with 77 additions and 0 deletions

View File

@ -606,6 +606,28 @@ static int is_good_config(struct usbtest_dev *tdev, int len)
return 0; return 0;
} }
static int is_good_ext(struct usbtest_dev *tdev, u8 *buf)
{
struct usb_ext_cap_descriptor *ext;
u32 attr;
ext = (struct usb_ext_cap_descriptor *) buf;
if (ext->bLength != USB_DT_USB_EXT_CAP_SIZE) {
ERROR(tdev, "bogus usb 2.0 extension descriptor length\n");
return 0;
}
attr = le32_to_cpu(ext->bmAttributes);
/* bits[1:4] is used and others are reserved */
if (attr & ~0x1e) { /* reserved == 0 */
ERROR(tdev, "reserved bits set\n");
return 0;
}
return 1;
}
/* sanity test for standard requests working with usb_control_mesg() and some /* sanity test for standard requests working with usb_control_mesg() and some
* of the utility functions which use it. * of the utility functions which use it.
* *
@ -694,12 +716,67 @@ static int ch9_postconfig(struct usbtest_dev *dev)
* 3.0 spec * 3.0 spec
*/ */
if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0300) { if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0300) {
struct usb_bos_descriptor *bos = NULL;
struct usb_dev_cap_header *header = NULL;
unsigned total, num, length;
u8 *buf;
retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf, retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf,
sizeof(*udev->bos->desc)); sizeof(*udev->bos->desc));
if (retval != sizeof(*udev->bos->desc)) { if (retval != sizeof(*udev->bos->desc)) {
dev_err(&iface->dev, "bos descriptor --> %d\n", retval); dev_err(&iface->dev, "bos descriptor --> %d\n", retval);
return (retval < 0) ? retval : -EDOM; return (retval < 0) ? retval : -EDOM;
} }
bos = (struct usb_bos_descriptor *)dev->buf;
total = le16_to_cpu(bos->wTotalLength);
num = bos->bNumDeviceCaps;
if (total > TBUF_SIZE)
total = TBUF_SIZE;
/*
* get generic device-level capability descriptors [9.6.2]
* in USB 3.0 spec
*/
retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf,
total);
if (retval != total) {
dev_err(&iface->dev, "bos descriptor set --> %d\n",
retval);
return (retval < 0) ? retval : -EDOM;
}
length = sizeof(*udev->bos->desc);
buf = dev->buf;
for (i = 0; i < num; i++) {
buf += length;
if (buf + sizeof(struct usb_dev_cap_header) >
dev->buf + total)
break;
header = (struct usb_dev_cap_header *)buf;
length = header->bLength;
if (header->bDescriptorType !=
USB_DT_DEVICE_CAPABILITY) {
dev_warn(&udev->dev, "not device capability descriptor, skip\n");
continue;
}
switch (header->bDevCapabilityType) {
case USB_CAP_TYPE_EXT:
if (buf + USB_DT_USB_EXT_CAP_SIZE >
dev->buf + total ||
!is_good_ext(dev, buf)) {
dev_err(&iface->dev, "bogus usb 2.0 extension descriptor\n");
return -EDOM;
}
break;
default:
break;
}
}
} }
/* there's always [9.4.3] at least one config descriptor [9.6.3] */ /* there's always [9.4.3] at least one config descriptor [9.6.3] */