aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/usbtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc/usbtest.c')
-rw-r--r--drivers/usb/misc/usbtest.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index e7235d5cce85..1c78e747f72b 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -606,6 +606,28 @@ static int is_good_config(struct usbtest_dev *tdev, int len)
606 return 0; 606 return 0;
607} 607}
608 608
609static int is_good_ext(struct usbtest_dev *tdev, u8 *buf)
610{
611 struct usb_ext_cap_descriptor *ext;
612 u32 attr;
613
614 ext = (struct usb_ext_cap_descriptor *) buf;
615
616 if (ext->bLength != USB_DT_USB_EXT_CAP_SIZE) {
617 ERROR(tdev, "bogus usb 2.0 extension descriptor length\n");
618 return 0;
619 }
620
621 attr = le32_to_cpu(ext->bmAttributes);
622 /* bits[1:4] is used and others are reserved */
623 if (attr & ~0x1e) { /* reserved == 0 */
624 ERROR(tdev, "reserved bits set\n");
625 return 0;
626 }
627
628 return 1;
629}
630
609/* sanity test for standard requests working with usb_control_mesg() and some 631/* sanity test for standard requests working with usb_control_mesg() and some
610 * of the utility functions which use it. 632 * of the utility functions which use it.
611 * 633 *
@@ -694,12 +716,67 @@ static int ch9_postconfig(struct usbtest_dev *dev)
694 * 3.0 spec 716 * 3.0 spec
695 */ 717 */
696 if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0300) { 718 if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0300) {
719 struct usb_bos_descriptor *bos = NULL;
720 struct usb_dev_cap_header *header = NULL;
721 unsigned total, num, length;
722 u8 *buf;
723
697 retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf, 724 retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf,
698 sizeof(*udev->bos->desc)); 725 sizeof(*udev->bos->desc));
699 if (retval != sizeof(*udev->bos->desc)) { 726 if (retval != sizeof(*udev->bos->desc)) {
700 dev_err(&iface->dev, "bos descriptor --> %d\n", retval); 727 dev_err(&iface->dev, "bos descriptor --> %d\n", retval);
701 return (retval < 0) ? retval : -EDOM; 728 return (retval < 0) ? retval : -EDOM;
702 } 729 }
730
731 bos = (struct usb_bos_descriptor *)dev->buf;
732 total = le16_to_cpu(bos->wTotalLength);
733 num = bos->bNumDeviceCaps;
734
735 if (total > TBUF_SIZE)
736 total = TBUF_SIZE;
737
738 /*
739 * get generic device-level capability descriptors [9.6.2]
740 * in USB 3.0 spec
741 */
742 retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf,
743 total);
744 if (retval != total) {
745 dev_err(&iface->dev, "bos descriptor set --> %d\n",
746 retval);
747 return (retval < 0) ? retval : -EDOM;
748 }
749
750 length = sizeof(*udev->bos->desc);
751 buf = dev->buf;
752 for (i = 0; i < num; i++) {
753 buf += length;
754 if (buf + sizeof(struct usb_dev_cap_header) >
755 dev->buf + total)
756 break;
757
758 header = (struct usb_dev_cap_header *)buf;
759 length = header->bLength;
760
761 if (header->bDescriptorType !=
762 USB_DT_DEVICE_CAPABILITY) {
763 dev_warn(&udev->dev, "not device capability descriptor, skip\n");
764 continue;
765 }
766
767 switch (header->bDevCapabilityType) {
768 case USB_CAP_TYPE_EXT:
769 if (buf + USB_DT_USB_EXT_CAP_SIZE >
770 dev->buf + total ||
771 !is_good_ext(dev, buf)) {
772 dev_err(&iface->dev, "bogus usb 2.0 extension descriptor\n");
773 return -EDOM;
774 }
775 break;
776 default:
777 break;
778 }
779 }
703 } 780 }
704 781
705 /* there's always [9.4.3] at least one config descriptor [9.6.3] */ 782 /* there's always [9.4.3] at least one config descriptor [9.6.3] */