summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-03-03 11:32:47 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2020-03-26 07:21:15 +0100
commit6d1d95a386ed0fefe100ee7e8f000216002aa356 (patch)
tree55002a3d5874acd3f809aa01932fd19c67d50410
parentfb75becf283143795f775d7ce833f73b571f5a6e (diff)
downloadbarebox-6d1d95a386ed0fefe100ee7e8f000216002aa356.tar.gz
usb: factor out a usb_setup_descriptor() function
This factors out a usb_setup_descriptor() function with the goal to make the code better comparable to the corresponding U-Boot code. This also incorporates this U-Boot commit: | commit 2b338ef41127351089254b748de5cefd95c3e800 | Author: Hans de Goede <hdegoede@redhat.com> | Date: Tue May 5 23:56:04 2015 +0200 | | usb: Fix maxpacketsize for first descriptor read for low-speed usb devs | | This fixes descriptor reading of lowspeed devices through ohci not working. | | Signed-off-by: Hans de Goede <hdegoede@redhat.com> | Acked-by: Marek Vasut <marex@denx.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/usb/core/usb.c155
1 files changed, 103 insertions, 52 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index e5c80aa..0ed897f 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -272,6 +272,108 @@ static int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int c
return 1;
}
+static int usb_get_descriptor(struct usb_device *dev, unsigned char type,
+ unsigned char index, void *buf, int size)
+{
+ int res;
+ res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ (type << 8) + index, 0,
+ buf, size, USB_CNTL_TIMEOUT);
+ return res;
+}
+
+static int get_descriptor_len(struct usb_device *dev, int len, int expect_len)
+{
+ int err;
+
+ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, dev->descriptor, len);
+ if (err < expect_len) {
+ if (err < 0) {
+ dev_err(&dev->dev, "unable to get device descriptor (error=%d)\n",
+ err);
+ return err;
+ } else {
+ dev_err(&dev->dev, "USB device descriptor short read (expected %i, got %i)\n",
+ expect_len, err);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int usb_setup_descriptor(struct usb_device *dev, bool do_read)
+{
+ /*
+ * This is a Windows scheme of initialization sequence, with double
+ * reset of the device (Linux uses the same sequence)
+ * Some equipment is said to work only with such init sequence; this
+ * patch is based on the work by Alan Stern:
+ * http://sourceforge.net/mailarchive/forum.php?
+ * thread_id=5729457&forum_id=5398
+ */
+
+ /*
+ * send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is
+ * only 18 bytes long, this will terminate with a short packet. But if
+ * the maxpacket size is 8 or 16 the device may be waiting to transmit
+ * some more, or keeps on retransmitting the 8 byte header.
+ */
+
+ if (dev->speed == USB_SPEED_LOW) {
+ dev->descriptor->bMaxPacketSize0 = 8;
+ dev->maxpacketsize = PACKET_SIZE_8;
+ } else {
+ dev->descriptor->bMaxPacketSize0 = 64;
+ dev->maxpacketsize = PACKET_SIZE_64;
+ }
+
+ if (do_read && dev->speed == USB_SPEED_FULL) {
+ int err;
+
+ /*
+ * Validate we've received only at least 8 bytes, not that
+ * we've received the entire descriptor. The reasoning is:
+ * - The code only uses fields in the first 8 bytes, so
+ * that's all we need to have fetched at this stage.
+ * - The smallest maxpacket size is 8 bytes. Before we know
+ * the actual maxpacket the device uses, the USB controller
+ * may only accept a single packet. Consequently we are only
+ * guaranteed to receive 1 packet (at least 8 bytes) even in
+ * a non-error case.
+ *
+ * At least the DWC2 controller needs to be programmed with
+ * the number of packets in addition to the number of bytes.
+ * A request for 64 bytes of data with the maxpacket guessed
+ * as 64 (above) yields a request for 1 packet.
+ */
+ err = get_descriptor_len(dev, 64, 8);
+ if (err)
+ return err;
+ }
+
+ dev->epmaxpacketin[0] = dev->descriptor->bMaxPacketSize0;
+ dev->epmaxpacketout[0] = dev->descriptor->bMaxPacketSize0;
+
+ switch (dev->descriptor->bMaxPacketSize0) {
+ case 8:
+ dev->maxpacketsize = PACKET_SIZE_8;
+ break;
+ case 16:
+ dev->maxpacketsize = PACKET_SIZE_16;
+ break;
+ case 32:
+ dev->maxpacketsize = PACKET_SIZE_32;
+ break;
+ case 64:
+ dev->maxpacketsize = PACKET_SIZE_64;
+ break;
+ }
+
+ return 0;
+}
+
/**
* set address of a device to the value in dev->devnum.
* This can only be done by addressing the device via the default address (0)
@@ -289,17 +391,6 @@ static int usb_set_address(struct usb_device *dev)
return res;
}
-static int usb_get_descriptor(struct usb_device *dev, unsigned char type,
- unsigned char index, void *buf, int size)
-{
- int res;
- res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (type << 8) + index, 0,
- buf, size, USB_CNTL_TIMEOUT);
- return res;
-}
-
/*
* By the time we get here, the device is in the default state. We need to
* identify the thing and get the ball rolling..
@@ -324,53 +415,13 @@ int usb_new_device(struct usb_device *dev)
buf = dma_alloc(USB_BUFSIZ);
- /* This is a Windows scheme of initialization sequence, with double
- * reset of the device (Linux uses the same sequence)
- * Some equipment is said to work only with such init sequence; this
- * patch is based on the work by Alan Stern:
- * http://sourceforge.net/mailarchive/forum.php?
- * thread_id=5729457&forum_id=5398
- */
-
- /* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is
- * only 18 bytes long, this will terminate with a short packet. But if
- * the maxpacket size is 8 or 16 the device may be waiting to transmit
- * some more, or keeps on retransmitting the 8 byte header. */
-
desc = buf;
- dev->descriptor->bMaxPacketSize0 = 64; /* Start off at 64 bytes */
- /* Default to 64 byte max packet size */
- dev->maxpacketsize = PACKET_SIZE_64;
- dev->epmaxpacketin[0] = 64;
- dev->epmaxpacketout[0] = 64;
if (parent)
dev->level = parent->level + 1;
- err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64);
- if (err < 0) {
- dev_dbg(&dev->dev, "%s: usb_get_descriptor() failed with %d\n", __func__, err);
- goto err_out;
- }
-
- dev->descriptor->bMaxPacketSize0 = desc->bMaxPacketSize0;
+ usb_setup_descriptor(dev, true);
- dev->epmaxpacketin[0] = dev->descriptor->bMaxPacketSize0;
- dev->epmaxpacketout[0] = dev->descriptor->bMaxPacketSize0;
- switch (dev->descriptor->bMaxPacketSize0) {
- case 8:
- dev->maxpacketsize = PACKET_SIZE_8;
- break;
- case 16:
- dev->maxpacketsize = PACKET_SIZE_16;
- break;
- case 32:
- dev->maxpacketsize = PACKET_SIZE_32;
- break;
- case 64:
- dev->maxpacketsize = PACKET_SIZE_64;
- break;
- }
dev->devnum = ++dev_index;
err = usb_set_address(dev); /* set address */