diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/misc/usbtest.c | 77 |
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 | ||
609 | static 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] */ |