Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

USB: core: Unite old scheme and new scheme descriptor reads

In preparation for reworking the usb_get_device_descriptor() routine,
it is desirable to unite the two different code paths responsible for
initially determining endpoint 0's maximum packet size in a newly
discovered USB device. Making this determination presents a
chicken-and-egg sort of problem, in that the only way to learn the
maxpacket value is to get it from the device descriptor retrieved from
the device, but communicating with the device to retrieve a descriptor
requires us to know beforehand the ep0 maxpacket size.

In practice this problem is solved in two different ways, referred to
in hub.c as the "old scheme" and the "new scheme". The old scheme
(which is the approach recommended by the USB-2 spec) involves asking
the device to send just the first eight bytes of its device
descriptor. Such a transfer uses packets containing no more than
eight bytes each, and every USB device must have an ep0 maxpacket size
>= 8, so this should succeed. Since the bMaxPacketSize0 field of the
device descriptor lies within the first eight bytes, this is all we
need.

The new scheme is an imitation of the technique used in an early
Windows USB implementation, giving it the happy advantage of working
with a wide variety of devices (some of them at the time would not
work with the old scheme, although that's probably less true now). It
involves making an initial guess of the ep0 maxpacket size, asking the
device to send up to 64 bytes worth of its device descriptor (which is
only 18 bytes long), and then resetting the device to clear any error
condition that might have resulted from the guess being wrong. The
initial guess is determined by the connection speed; it should be
correct in all cases other than full speed, for which the allowed
values are 8, 16, 32, and 64 (in this case the initial guess is 64).

The reason for this patch is that the old- and new-scheme parts of
hub_port_init() use different code paths, one involving
usb_get_device_descriptor() and one not, for their initial reads of
the device descriptor. Since these reads have essentially the same
purpose and are made under essentially the same circumstances, this is
illogical. It makes more sense to have both of them use a common
subroutine.

This subroutine does basically what the new scheme's code did, because
that approach is more general than the one used by the old scheme. It
only needs to know how many bytes to transfer and whether or not it is
being called for the first iteration of a retry loop (in case of
certain time-out errors). There are two main differences from the
former code:

We initialize the bDescriptorType field of the transfer buffer
to 0 before performing the transfer, to avoid possibly
accessing an uninitialized value afterward.

We read the device descriptor into a temporary buffer rather
than storing it directly into udev->descriptor, which the old
scheme implementation used to do.

Since the whole point of this first read of the device descriptor is
to determine the bMaxPacketSize0 value, that is what the new routine
returns (or an error code). The value is stored in a local variable
rather than in udev->descriptor. As a side effect, this necessitates
moving a section of code that checks the bcdUSB field for SuperSpeed
devices until after the full device descriptor has been retrieved.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: Oliver Neukum <oneukum@suse.com>
Link: https://lore.kernel.org/r/495cb5d4-f956-4f4a-a875-1e67e9489510@rowland.harvard.edu
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
85d07c55 af6248af

+94 -79
+94 -79
drivers/usb/core/hub.c
··· 4741 4741 return hcd->driver->enable_device(hcd, udev); 4742 4742 } 4743 4743 4744 + /* 4745 + * Get the bMaxPacketSize0 value during initialization by reading the 4746 + * device's device descriptor. Since we don't already know this value, 4747 + * the transfer is unsafe and it ignores I/O errors, only testing for 4748 + * reasonable received values. 4749 + * 4750 + * For "old scheme" initialization, size will be 8 so we read just the 4751 + * start of the device descriptor, which should work okay regardless of 4752 + * the actual bMaxPacketSize0 value. For "new scheme" initialization, 4753 + * size will be 64 (and buf will point to a sufficiently large buffer), 4754 + * which might not be kosher according to the USB spec but it's what 4755 + * Windows does and what many devices expect. 4756 + * 4757 + * Returns: bMaxPacketSize0 or a negative error code. 4758 + */ 4759 + static int get_bMaxPacketSize0(struct usb_device *udev, 4760 + struct usb_device_descriptor *buf, int size, bool first_time) 4761 + { 4762 + int i, rc; 4763 + 4764 + /* 4765 + * Retry on all errors; some devices are flakey. 4766 + * 255 is for WUSB devices, we actually need to use 4767 + * 512 (WUSB1.0[4.8.1]). 4768 + */ 4769 + for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) { 4770 + /* Start with invalid values in case the transfer fails */ 4771 + buf->bDescriptorType = buf->bMaxPacketSize0 = 0; 4772 + rc = usb_control_msg(udev, usb_rcvaddr0pipe(), 4773 + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, 4774 + USB_DT_DEVICE << 8, 0, 4775 + buf, size, 4776 + initial_descriptor_timeout); 4777 + switch (buf->bMaxPacketSize0) { 4778 + case 8: case 16: case 32: case 64: case 255: 4779 + if (buf->bDescriptorType == USB_DT_DEVICE) { 4780 + rc = buf->bMaxPacketSize0; 4781 + break; 4782 + } 4783 + fallthrough; 4784 + default: 4785 + if (rc >= 0) 4786 + rc = -EPROTO; 4787 + break; 4788 + } 4789 + 4790 + /* 4791 + * Some devices time out if they are powered on 4792 + * when already connected. They need a second 4793 + * reset, so return early. But only on the first 4794 + * attempt, lest we get into a time-out/reset loop. 4795 + */ 4796 + if (rc > 0 || (rc == -ETIMEDOUT && first_time && 4797 + udev->speed > USB_SPEED_FULL)) 4798 + break; 4799 + } 4800 + return rc; 4801 + } 4802 + 4803 + #define GET_DESCRIPTOR_BUFSIZE 64 4804 + 4744 4805 /* Reset device, (re)assign address, get device descriptor. 4745 4806 * Device connection must be stable, no more debouncing needed. 4746 4807 * Returns device in USB_STATE_ADDRESS, except on error. ··· 4826 4765 int devnum = udev->devnum; 4827 4766 const char *driver_name; 4828 4767 bool do_new_scheme; 4768 + int maxp0; 4769 + struct usb_device_descriptor *buf; 4770 + 4771 + buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); 4772 + if (!buf) 4773 + return -ENOMEM; 4829 4774 4830 4775 /* root hub ports have a slightly longer reset period 4831 4776 * (from USB 2.0 spec, section 7.1.7.5) ··· 4951 4884 } 4952 4885 4953 4886 if (do_new_scheme) { 4954 - struct usb_device_descriptor *buf; 4955 - int r = 0; 4956 - 4957 4887 retval = hub_enable_device(udev); 4958 4888 if (retval < 0) { 4959 4889 dev_err(&udev->dev, ··· 4959 4895 goto fail; 4960 4896 } 4961 4897 4962 - #define GET_DESCRIPTOR_BUFSIZE 64 4963 - buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); 4964 - if (!buf) { 4965 - retval = -ENOMEM; 4966 - continue; 4967 - } 4968 - 4969 - /* Retry on all errors; some devices are flakey. 4970 - * 255 is for WUSB devices, we actually need to use 4971 - * 512 (WUSB1.0[4.8.1]). 4972 - */ 4973 - for (operations = 0; operations < GET_MAXPACKET0_TRIES; 4974 - ++operations) { 4975 - buf->bMaxPacketSize0 = 0; 4976 - r = usb_control_msg(udev, usb_rcvaddr0pipe(), 4977 - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, 4978 - USB_DT_DEVICE << 8, 0, 4979 - buf, GET_DESCRIPTOR_BUFSIZE, 4980 - initial_descriptor_timeout); 4981 - switch (buf->bMaxPacketSize0) { 4982 - case 8: case 16: case 32: case 64: case 255: 4983 - if (buf->bDescriptorType == 4984 - USB_DT_DEVICE) { 4985 - r = 0; 4986 - break; 4987 - } 4988 - fallthrough; 4989 - default: 4990 - if (r == 0) 4991 - r = -EPROTO; 4992 - break; 4993 - } 4994 - /* 4995 - * Some devices time out if they are powered on 4996 - * when already connected. They need a second 4997 - * reset. But only on the first attempt, 4998 - * lest we get into a time out/reset loop 4999 - */ 5000 - if (r == 0 || (r == -ETIMEDOUT && 5001 - retries == 0 && 5002 - udev->speed > USB_SPEED_FULL)) 5003 - break; 5004 - } 5005 - udev->descriptor.bMaxPacketSize0 = 5006 - buf->bMaxPacketSize0; 5007 - kfree(buf); 4898 + maxp0 = get_bMaxPacketSize0(udev, buf, 4899 + GET_DESCRIPTOR_BUFSIZE, retries == 0); 5008 4900 5009 4901 retval = hub_port_reset(hub, port1, udev, delay, false); 5010 4902 if (retval < 0) /* error or disconnect */ ··· 4971 4951 retval = -ENODEV; 4972 4952 goto fail; 4973 4953 } 4974 - if (r) { 4975 - if (r != -ENODEV) 4954 + if (maxp0 < 0) { 4955 + if (maxp0 != -ENODEV) 4976 4956 dev_err(&udev->dev, "device descriptor read/64, error %d\n", 4977 - r); 4978 - retval = -EMSGSIZE; 4957 + maxp0); 4958 + retval = maxp0; 4979 4959 continue; 4980 4960 } 4981 - #undef GET_DESCRIPTOR_BUFSIZE 4982 4961 } 4983 4962 4984 4963 /* ··· 5023 5004 break; 5024 5005 } 5025 5006 5026 - retval = usb_get_device_descriptor(udev, 8); 5027 - if (retval < 8) { 5007 + /* !do_new_scheme || wusb */ 5008 + maxp0 = get_bMaxPacketSize0(udev, buf, 8, retries == 0); 5009 + if (maxp0 < 0) { 5010 + retval = maxp0; 5028 5011 if (retval != -ENODEV) 5029 5012 dev_err(&udev->dev, 5030 5013 "device descriptor read/8, error %d\n", 5031 5014 retval); 5032 - if (retval >= 0) 5033 - retval = -EMSGSIZE; 5034 5015 } else { 5035 5016 u32 delay; 5036 - 5037 - retval = 0; 5038 5017 5039 5018 delay = udev->parent->hub_delay; 5040 5019 udev->hub_delay = min_t(u32, delay, ··· 5050 5033 if (retval) 5051 5034 goto fail; 5052 5035 5053 - /* 5054 - * Some superspeed devices have finished the link training process 5055 - * and attached to a superspeed hub port, but the device descriptor 5056 - * got from those devices show they aren't superspeed devices. Warm 5057 - * reset the port attached by the devices can fix them. 5058 - */ 5059 - if ((udev->speed >= USB_SPEED_SUPER) && 5060 - (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { 5061 - dev_err(&udev->dev, "got a wrong device descriptor, " 5062 - "warm reset device\n"); 5063 - hub_port_reset(hub, port1, udev, 5064 - HUB_BH_RESET_TIME, true); 5065 - retval = -EINVAL; 5066 - goto fail; 5067 - } 5068 - 5069 - if (udev->descriptor.bMaxPacketSize0 == 0xff || 5070 - udev->speed >= USB_SPEED_SUPER) 5036 + if (maxp0 == 0xff || udev->speed >= USB_SPEED_SUPER) 5071 5037 i = 512; 5072 5038 else 5073 - i = udev->descriptor.bMaxPacketSize0; 5039 + i = maxp0; 5074 5040 if (usb_endpoint_maxp(&udev->ep0.desc) != i) { 5075 5041 if (udev->speed == USB_SPEED_LOW || 5076 5042 !(i == 8 || i == 16 || i == 32 || i == 64)) { ··· 5079 5079 goto fail; 5080 5080 } 5081 5081 5082 + /* 5083 + * Some superspeed devices have finished the link training process 5084 + * and attached to a superspeed hub port, but the device descriptor 5085 + * got from those devices show they aren't superspeed devices. Warm 5086 + * reset the port attached by the devices can fix them. 5087 + */ 5088 + if ((udev->speed >= USB_SPEED_SUPER) && 5089 + (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { 5090 + dev_err(&udev->dev, "got a wrong device descriptor, warm reset device\n"); 5091 + hub_port_reset(hub, port1, udev, HUB_BH_RESET_TIME, true); 5092 + retval = -EINVAL; 5093 + goto fail; 5094 + } 5095 + 5082 5096 usb_detect_quirks(udev); 5083 5097 5084 5098 if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { ··· 5115 5101 hub_port_disable(hub, port1, 0); 5116 5102 update_devnum(udev, devnum); /* for disconnect processing */ 5117 5103 } 5104 + kfree(buf); 5118 5105 return retval; 5119 5106 } 5120 5107