diff options
Diffstat (limited to 'drivers/usb/core/config.c')
-rw-r--r-- | drivers/usb/core/config.c | 111 |
1 files changed, 107 insertions, 4 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 26678cadfb21..f4bdd0ce8d56 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c | |||
@@ -124,9 +124,9 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, | |||
124 | 124 | ||
125 | if (usb_endpoint_xfer_isoc(&ep->desc)) | 125 | if (usb_endpoint_xfer_isoc(&ep->desc)) |
126 | max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * | 126 | max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * |
127 | le16_to_cpu(ep->desc.wMaxPacketSize); | 127 | usb_endpoint_maxp(&ep->desc); |
128 | else if (usb_endpoint_xfer_int(&ep->desc)) | 128 | else if (usb_endpoint_xfer_int(&ep->desc)) |
129 | max_tx = le16_to_cpu(ep->desc.wMaxPacketSize) * | 129 | max_tx = usb_endpoint_maxp(&ep->desc) * |
130 | (desc->bMaxBurst + 1); | 130 | (desc->bMaxBurst + 1); |
131 | else | 131 | else |
132 | max_tx = 999999; | 132 | max_tx = 999999; |
@@ -241,7 +241,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, | |||
241 | cfgno, inum, asnum, d->bEndpointAddress); | 241 | cfgno, inum, asnum, d->bEndpointAddress); |
242 | endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; | 242 | endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; |
243 | endpoint->desc.bInterval = 1; | 243 | endpoint->desc.bInterval = 1; |
244 | if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8) | 244 | if (usb_endpoint_maxp(&endpoint->desc) > 8) |
245 | endpoint->desc.wMaxPacketSize = cpu_to_le16(8); | 245 | endpoint->desc.wMaxPacketSize = cpu_to_le16(8); |
246 | } | 246 | } |
247 | 247 | ||
@@ -254,7 +254,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, | |||
254 | && usb_endpoint_xfer_bulk(d)) { | 254 | && usb_endpoint_xfer_bulk(d)) { |
255 | unsigned maxp; | 255 | unsigned maxp; |
256 | 256 | ||
257 | maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff; | 257 | maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff; |
258 | if (maxp != 512) | 258 | if (maxp != 512) |
259 | dev_warn(ddev, "config %d interface %d altsetting %d " | 259 | dev_warn(ddev, "config %d interface %d altsetting %d " |
260 | "bulk endpoint 0x%X has invalid maxpacket %d\n", | 260 | "bulk endpoint 0x%X has invalid maxpacket %d\n", |
@@ -755,3 +755,106 @@ err2: | |||
755 | dev_err(ddev, "out of memory\n"); | 755 | dev_err(ddev, "out of memory\n"); |
756 | return result; | 756 | return result; |
757 | } | 757 | } |
758 | |||
759 | void usb_release_bos_descriptor(struct usb_device *dev) | ||
760 | { | ||
761 | if (dev->bos) { | ||
762 | kfree(dev->bos->desc); | ||
763 | kfree(dev->bos); | ||
764 | dev->bos = NULL; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | /* Get BOS descriptor set */ | ||
769 | int usb_get_bos_descriptor(struct usb_device *dev) | ||
770 | { | ||
771 | struct device *ddev = &dev->dev; | ||
772 | struct usb_bos_descriptor *bos; | ||
773 | struct usb_dev_cap_header *cap; | ||
774 | unsigned char *buffer; | ||
775 | int length, total_len, num, i; | ||
776 | int ret; | ||
777 | |||
778 | bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL); | ||
779 | if (!bos) | ||
780 | return -ENOMEM; | ||
781 | |||
782 | /* Get BOS descriptor */ | ||
783 | ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE); | ||
784 | if (ret < USB_DT_BOS_SIZE) { | ||
785 | dev_err(ddev, "unable to get BOS descriptor\n"); | ||
786 | if (ret >= 0) | ||
787 | ret = -ENOMSG; | ||
788 | kfree(bos); | ||
789 | return ret; | ||
790 | } | ||
791 | |||
792 | length = bos->bLength; | ||
793 | total_len = le16_to_cpu(bos->wTotalLength); | ||
794 | num = bos->bNumDeviceCaps; | ||
795 | kfree(bos); | ||
796 | if (total_len < length) | ||
797 | return -EINVAL; | ||
798 | |||
799 | dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_KERNEL); | ||
800 | if (!dev->bos) | ||
801 | return -ENOMEM; | ||
802 | |||
803 | /* Now let's get the whole BOS descriptor set */ | ||
804 | buffer = kzalloc(total_len, GFP_KERNEL); | ||
805 | if (!buffer) { | ||
806 | ret = -ENOMEM; | ||
807 | goto err; | ||
808 | } | ||
809 | dev->bos->desc = (struct usb_bos_descriptor *)buffer; | ||
810 | |||
811 | ret = usb_get_descriptor(dev, USB_DT_BOS, 0, buffer, total_len); | ||
812 | if (ret < total_len) { | ||
813 | dev_err(ddev, "unable to get BOS descriptor set\n"); | ||
814 | if (ret >= 0) | ||
815 | ret = -ENOMSG; | ||
816 | goto err; | ||
817 | } | ||
818 | total_len -= length; | ||
819 | |||
820 | for (i = 0; i < num; i++) { | ||
821 | buffer += length; | ||
822 | cap = (struct usb_dev_cap_header *)buffer; | ||
823 | length = cap->bLength; | ||
824 | |||
825 | if (total_len < length) | ||
826 | break; | ||
827 | total_len -= length; | ||
828 | |||
829 | if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { | ||
830 | dev_warn(ddev, "descriptor type invalid, skip\n"); | ||
831 | continue; | ||
832 | } | ||
833 | |||
834 | switch (cap->bDevCapabilityType) { | ||
835 | case USB_CAP_TYPE_WIRELESS_USB: | ||
836 | /* Wireless USB cap descriptor is handled by wusb */ | ||
837 | break; | ||
838 | case USB_CAP_TYPE_EXT: | ||
839 | dev->bos->ext_cap = | ||
840 | (struct usb_ext_cap_descriptor *)buffer; | ||
841 | break; | ||
842 | case USB_SS_CAP_TYPE: | ||
843 | dev->bos->ss_cap = | ||
844 | (struct usb_ss_cap_descriptor *)buffer; | ||
845 | break; | ||
846 | case CONTAINER_ID_TYPE: | ||
847 | dev->bos->ss_id = | ||
848 | (struct usb_ss_container_id_descriptor *)buffer; | ||
849 | break; | ||
850 | default: | ||
851 | break; | ||
852 | } | ||
853 | } | ||
854 | |||
855 | return 0; | ||
856 | |||
857 | err: | ||
858 | usb_release_bos_descriptor(dev); | ||
859 | return ret; | ||
860 | } | ||