diff options
Diffstat (limited to 'drivers/usb/misc/usbtest.c')
-rw-r--r-- | drivers/usb/misc/usbtest.c | 172 |
1 files changed, 163 insertions, 9 deletions
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index aa28ac8c760..b4152820d65 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -120,7 +120,7 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) struct usb_host_endpoint *e; e = alt->endpoint + ep; - switch (e->desc.bmAttributes) { + switch (usb_endpoint_type(&e->desc)) { case USB_ENDPOINT_XFER_BULK: break; case USB_ENDPOINT_XFER_ISOC: @@ -437,7 +437,7 @@ alloc_sglist(int nents, int max, int vary) if (max == 0) return NULL; - sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL); + sg = kmalloc_array(nents, sizeof(*sg), GFP_KERNEL); if (!sg) return NULL; sg_init_table(sg, nents); @@ -573,7 +573,7 @@ static int is_good_config(struct usbtest_dev *tdev, int len) { struct usb_config_descriptor *config; - if (len < sizeof *config) + if (len < sizeof(*config)) return 0; config = (struct usb_config_descriptor *) tdev->buf; @@ -606,6 +606,76 @@ static int is_good_config(struct usbtest_dev *tdev, int len) 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; +} + +static int is_good_ss_cap(struct usbtest_dev *tdev, u8 *buf) +{ + struct usb_ss_cap_descriptor *ss; + + ss = (struct usb_ss_cap_descriptor *) buf; + + if (ss->bLength != USB_DT_USB_SS_CAP_SIZE) { + ERROR(tdev, "bogus superspeed device capability descriptor length\n"); + return 0; + } + + /* + * only bit[1] of bmAttributes is used for LTM and others are + * reserved + */ + if (ss->bmAttributes & ~0x02) { /* reserved == 0 */ + ERROR(tdev, "reserved bits set in bmAttributes\n"); + return 0; + } + + /* bits[0:3] of wSpeedSupported is used and others are reserved */ + if (le16_to_cpu(ss->wSpeedSupported) & ~0x0f) { /* reserved == 0 */ + ERROR(tdev, "reserved bits set in wSpeedSupported\n"); + return 0; + } + + return 1; +} + +static int is_good_con_id(struct usbtest_dev *tdev, u8 *buf) +{ + struct usb_ss_container_id_descriptor *con_id; + + con_id = (struct usb_ss_container_id_descriptor *) buf; + + if (con_id->bLength != USB_DT_USB_SS_CONTN_ID_SIZE) { + ERROR(tdev, "bogus container id descriptor length\n"); + return 0; + } + + if (con_id->bReserved) { /* reserved == 0 */ + ERROR(tdev, "reserved bits set\n"); + return 0; + } + + return 1; +} + /* sanity test for standard requests working with usb_control_mesg() and some * of the utility functions which use it. * @@ -683,12 +753,96 @@ static int ch9_postconfig(struct usbtest_dev *dev) /* there's always [9.4.3] a device descriptor [9.6.1] */ retval = usb_get_descriptor(udev, USB_DT_DEVICE, 0, - dev->buf, sizeof udev->descriptor); - if (retval != sizeof udev->descriptor) { + dev->buf, sizeof(udev->descriptor)); + if (retval != sizeof(udev->descriptor)) { dev_err(&iface->dev, "dev descriptor --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } + /* + * there's always [9.4.3] a bos device descriptor [9.6.2] in USB + * 3.0 spec + */ + 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, + sizeof(*udev->bos->desc)); + if (retval != sizeof(*udev->bos->desc)) { + dev_err(&iface->dev, "bos descriptor --> %d\n", retval); + 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; + case USB_SS_CAP_TYPE: + if (buf + USB_DT_USB_SS_CAP_SIZE > + dev->buf + total || + !is_good_ss_cap(dev, buf)) { + dev_err(&iface->dev, "bogus superspeed device capability descriptor\n"); + return -EDOM; + } + break; + case CONTAINER_ID_TYPE: + if (buf + USB_DT_USB_SS_CONTN_ID_SIZE > + dev->buf + total || + !is_good_con_id(dev, buf)) { + dev_err(&iface->dev, "bogus container id descriptor\n"); + return -EDOM; + } + break; + default: + break; + } + } + } + /* there's always [9.4.3] at least one config descriptor [9.6.3] */ for (i = 0; i < udev->descriptor.bNumConfigurations; i++) { retval = usb_get_descriptor(udev, USB_DT_CONFIG, i, @@ -954,7 +1108,7 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) * device, but some are chosen to trigger protocol stalls * or short reads. */ - memset(&req, 0, sizeof req); + memset(&req, 0, sizeof(req)); req.bRequest = USB_REQ_GET_DESCRIPTOR; req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE; @@ -1074,7 +1228,7 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) if (!u) goto cleanup; - reqp = kmalloc(sizeof *reqp, GFP_KERNEL); + reqp = kmalloc(sizeof(*reqp), GFP_KERNEL); if (!reqp) goto cleanup; reqp->setup = req; @@ -1667,13 +1821,13 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, if (param->sglen > 10) return -EDOM; - memset(&context, 0, sizeof context); + memset(&context, 0, sizeof(context)); context.count = param->iterations * param->sglen; context.dev = dev; init_completion(&context.done); spin_lock_init(&context.lock); - memset(urbs, 0, sizeof urbs); + memset(urbs, 0, sizeof(urbs)); udev = testdev_to_usbdev(dev); dev_info(&dev->intf->dev, "... iso period %d %sframes, wMaxPacket %04x\n", |