From 2f0eb2ac4b84f94e2f7de6e4ec9b63ce07cfec7a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 18 Sep 2017 06:40:40 -0700 Subject: usb: Handle audio extension endpoint descriptor in usb_parse_config() Normal endpoint descriptor size is 7, but for audio extension it is 9. Handle that correctly when parsing endpoint descriptor. Signed-off-by: Bin Meng --- common/usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/usb.c b/common/usb.c index 09042597573..6cb92ef4f52 100644 --- a/common/usb.c +++ b/common/usb.c @@ -437,12 +437,13 @@ static int usb_parse_config(struct usb_device *dev, } break; case USB_DT_ENDPOINT: - if (head->bLength != USB_DT_ENDPOINT_SIZE) { + if (head->bLength != USB_DT_ENDPOINT_SIZE && + head->bLength != USB_DT_ENDPOINT_AUDIO_SIZE) { printf("ERROR: Invalid USB EP length (%d)\n", head->bLength); break; } - if (index + USB_DT_ENDPOINT_SIZE > + if (index + head->bLength > dev->config.desc.wTotalLength) { puts("USB EP descriptor overflowed buffer!\n"); break; -- cgit v1.3.1 From c008faa77358bb5b313696dd1d5bb8afa03a6ca2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 18 Sep 2017 06:40:42 -0700 Subject: usb: Only get 64 bytes device descriptor for full speed devices Full speed device endpoint 0 can have 8/16/32/64 bMaxPacketSize0. Other speed devices report fixed value per USB spec. So it only makes sense if we send a get device descriptor with 64 bytes to full speed devices. While we are here, update the comment block to be within 80 cols. Signed-off-by: Bin Meng --- common/usb.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'common') diff --git a/common/usb.c b/common/usb.c index 6cb92ef4f52..88cee810fac 100644 --- a/common/usb.c +++ b/common/usb.c @@ -970,23 +970,24 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read) dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; - if (do_read) { + 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. + * 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. + * 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) @@ -1009,7 +1010,7 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read) dev->maxpacketsize = PACKET_SIZE_64; break; default: - printf("usb_new_device: invalid max packet size\n"); + printf("%s: invalid max packet size\n", __func__); return -EIO; } -- cgit v1.3.1 From 932bb668bb2464115f2d08abbed44e58cfce9536 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 18 Sep 2017 06:40:43 -0700 Subject: usb: Read device descriptor after device is addressed for xHCI For xHCI it is not possible to read a device descriptor before it has been assigned an address. That's why usb_setup_descriptor() was called with 'do_read' being false. But we really need try to read the device descriptor before starting any real communication with the default control endpoint. Signed-off-by: Bin Meng --- common/usb.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'common') diff --git a/common/usb.c b/common/usb.c index 88cee810fac..8d27bc70607 100644 --- a/common/usb.c +++ b/common/usb.c @@ -1052,6 +1052,17 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, mdelay(10); /* Let the SET_ADDRESS settle */ + /* + * If we haven't read device descriptor before, read it here + * after device is assigned an address. This is only applicable + * to xHCI so far. + */ + if (!do_read) { + err = usb_setup_descriptor(dev, true); + if (err) + return err; + } + return 0; } -- cgit v1.3.1 From b90203526f2c5bcc05b4a65241ea226b7b9f52d0 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 18 Sep 2017 06:40:45 -0700 Subject: usb: hub: Clear port reset before usb_hub_port_connect_change() During usb_hub_port_connect_change(), a port reset set feature request is issued to the port, and later a port reset clear feature is done to the same port before the function returns. However at the end of usb_scan_port(), we attempt to clear port reset again on a cached port status change variable, which should not be done. Adjust the call to clear port reset to right before the call to usb_hub_port_connect_change(). Signed-off-by: Bin Meng --- common/usb_hub.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/usb_hub.c b/common/usb_hub.c index 86a34776643..a9d21bca5e3 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -489,6 +489,11 @@ static int usb_scan_port(struct usb_device_scan *usb_scan) return 0; } + if (portchange & USB_PORT_STAT_C_RESET) { + debug("port %d reset change\n", i + 1); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); + } + /* A new USB device is ready at this point */ debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1); @@ -543,11 +548,6 @@ static int usb_scan_port(struct usb_device_scan *usb_scan) hub->overcurrent_count[i]); } - if (portchange & USB_PORT_STAT_C_RESET) { - debug("port %d reset change\n", i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); - } - /* * We're done with this device, so let's remove this device from * scanning list -- cgit v1.3.1 From 061895fbe57d29f50bb3c6c8609d56a668d1387d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 18 Sep 2017 06:40:46 -0700 Subject: usb: hub: Clear BH reset status change for a 3.0 hub USB 3.0 hubs report bit[5] in the port status change response as BH reset. The hub shall set the C_BH_PORT_RESET field for this port. Signed-off-by: Bin Meng --- common/usb_hub.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'common') diff --git a/common/usb_hub.c b/common/usb_hub.c index a9d21bca5e3..325d16dfc86 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -494,6 +494,12 @@ static int usb_scan_port(struct usb_device_scan *usb_scan) usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); } + if ((portchange & USB_SS_PORT_STAT_C_BH_RESET) && + usb_hub_is_superspeed(dev)) { + debug("port %d BH reset change\n", i + 1); + usb_clear_port_feature(dev, i + 1, USB_SS_PORT_FEAT_C_BH_RESET); + } + /* A new USB device is ready at this point */ debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1); -- cgit v1.3.1 From 72ac8f3fc29016a31ee309b4d025b487e78906ab Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 27 Sep 2017 21:50:07 -0700 Subject: usb: storage: Fix overwritten in usb_stor_set_max_xfer_blk() The stored 'blk' value is overwritten to 'size / 512' before it can be used in usb_stor_set_max_xfer_blk(). This is not what we want. In fact, when 'size' exceeds the upper limit (USHRT_MAX * 512), we should simply assign 'size' to the upper limit. Reported-by: Coverity (CID: 167250) Signed-off-by: Bin Meng --- common/usb_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/usb_storage.c b/common/usb_storage.c index a57570b73f3..a91b1c0d2f9 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -964,7 +964,7 @@ static void usb_stor_set_max_xfer_blk(struct usb_device *udev, blk = 20; } else { if (size > USHRT_MAX * 512) - blk = USHRT_MAX; + size = USHRT_MAX * 512; blk = size / 512; } #endif -- cgit v1.3.1