Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Jul 2018 09:21:20 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r336887 - stable/10/sys/dev/usb
Message-ID:  <201807300921.w6U9LK50018884@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Mon Jul 30 09:21:19 2018
New Revision: 336887
URL: https://svnweb.freebsd.org/changeset/base/336887

Log:
  MFC r335700:
  Improve the kernel's USB descriptor reading function.
  Some USB devices does not allow a partial descriptor readout.
  
  Found by:	bz@
  Sponsored by:	Mellanox Technologies

Modified:
  stable/10/sys/dev/usb/usb_request.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/usb/usb_request.c
==============================================================================
--- stable/10/sys/dev/usb/usb_request.c	Mon Jul 30 09:20:17 2018	(r336886)
+++ stable/10/sys/dev/usb/usb_request.c	Mon Jul 30 09:21:19 2018	(r336887)
@@ -988,7 +988,7 @@ usbd_req_get_desc(struct usb_device *udev,
     uint8_t retries)
 {
 	struct usb_device_request req;
-	uint8_t *buf;
+	uint8_t *buf = desc;
 	usb_error_t err;
 
 	DPRINTFN(4, "id=%d, type=%d, index=%d, max_len=%d\n",
@@ -1010,6 +1010,32 @@ usbd_req_get_desc(struct usb_device *udev,
 		err = usbd_do_request_flags(udev, mtx, &req,
 		    desc, 0, NULL, 500 /* ms */);
 
+		if (err != 0 && err != USB_ERR_TIMEOUT &&
+		    min_len != max_len) {
+			/* clear descriptor data */
+			memset(desc, 0, max_len);
+
+			/* try to read full descriptor length */
+			USETW(req.wLength, max_len);
+
+			err = usbd_do_request_flags(udev, mtx, &req,
+			    desc, USB_SHORT_XFER_OK, NULL, 500 /* ms */);
+
+			if (err == 0) {
+				/* verify length */
+				if (buf[0] > max_len)
+					buf[0] = max_len;
+				else if (buf[0] < 2)
+					err = USB_ERR_INVAL;
+
+				min_len = buf[0];
+
+				/* enforce descriptor type */
+				buf[1] = type;
+				goto done;
+			}
+		}
+
 		if (err) {
 			if (!retries) {
 				goto done;
@@ -1020,7 +1046,6 @@ usbd_req_get_desc(struct usb_device *udev,
 
 			continue;
 		}
-		buf = desc;
 
 		if (min_len == max_len) {
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201807300921.w6U9LK50018884>