aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/config.c')
-rw-r--r--drivers/usb/core/config.c111
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
759void 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 */
769int 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
857err:
858 usb_release_bos_descriptor(dev);
859 return ret;
860}