svn commit: r248246 - head/sys/dev/usb

Hans Petter Selasky hselasky at FreeBSD.org
Wed Mar 13 15:38:03 UTC 2013


Author: hselasky
Date: Wed Mar 13 15:38:01 2013
New Revision: 248246
URL: http://svnweb.freebsd.org/changeset/base/248246

Log:
  - Make quirk for reading device descriptor from broken USB devices.
  Else they won't enumerate at all:
  hw.usb.full_ddesc=1
  - Reduce the USB descriptor read timeout from 1000ms to
  500ms. Typical value for LOW speed devices is 50-100ms.
  - Enumerate USB device a maximum of 3 times when a port
  connection change event is detected, before giving up.
  
  MFC after:	1 month

Modified:
  head/sys/dev/usb/usb_device.c
  head/sys/dev/usb/usb_request.c

Modified: head/sys/dev/usb/usb_device.c
==============================================================================
--- head/sys/dev/usb/usb_device.c	Wed Mar 13 15:20:18 2013	(r248245)
+++ head/sys/dev/usb/usb_device.c	Wed Mar 13 15:38:01 2013	(r248246)
@@ -1698,10 +1698,14 @@ usb_alloc_device(device_t parent_dev, st
 	err = usbd_setup_device_desc(udev, NULL);
 
 	if (err != 0) {
-		/* XXX try to re-enumerate the device */
+		/* try to enumerate two more times */
 		err = usbd_req_re_enumerate(udev, NULL);
-		if (err)
-			goto done;
+		if (err != 0) {
+			err = usbd_req_re_enumerate(udev, NULL);
+			if (err != 0) {
+				goto done;
+			}
+		}
 	}
 
 	/*

Modified: head/sys/dev/usb/usb_request.c
==============================================================================
--- head/sys/dev/usb/usb_request.c	Wed Mar 13 15:20:18 2013	(r248245)
+++ head/sys/dev/usb/usb_request.c	Wed Mar 13 15:38:01 2013	(r248246)
@@ -76,6 +76,11 @@ static int usb_no_cs_fail;
 SYSCTL_INT(_hw_usb, OID_AUTO, no_cs_fail, CTLFLAG_RW,
     &usb_no_cs_fail, 0, "USB clear stall failures are ignored, if set");
 
+static int usb_full_ddesc;
+
+SYSCTL_INT(_hw_usb, OID_AUTO, full_ddesc, CTLFLAG_RW,
+    &usb_full_ddesc, 0, "USB always read complete device descriptor, if set");
+
 #ifdef USB_DEBUG
 #ifdef USB_REQ_DEBUG
 /* The following structures are used in connection to fault injection. */
@@ -1002,7 +1007,7 @@ usbd_req_get_desc(struct usb_device *ude
 		USETW(req.wLength, min_len);
 
 		err = usbd_do_request_flags(udev, mtx, &req,
-		    desc, 0, NULL, 1000);
+		    desc, 0, NULL, 500 /* ms */);
 
 		if (err) {
 			if (!retries) {
@@ -1887,32 +1892,41 @@ usbd_setup_device_desc(struct usb_device
 	 */
 	switch (udev->speed) {
 	case USB_SPEED_FULL:
-	case USB_SPEED_LOW:
+		if (usb_full_ddesc != 0) {
+			/* get full device descriptor */
+			err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+			if (err == 0)
+				break;
+		}
+
+		/* get partial device descriptor, some devices crash on this */
 		err = usbd_req_get_desc(udev, mtx, NULL, &udev->ddesc,
 		    USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
-		if (err != 0) {
-			DPRINTFN(0, "getting device descriptor "
-			    "at addr %d failed, %s\n", udev->address,
-			    usbd_errstr(err));
-			return (err);
-		}
+		if (err != 0)
+			break;
+
+		/* get the full device descriptor */
+		err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
 		break;
+
 	default:
 		DPRINTF("Minimum MaxPacketSize is large enough "
-		    "to hold the complete device descriptor\n");
-		break;
-	}
+		    "to hold the complete device descriptor or "
+		    "only once MaxPacketSize choice\n");
 
-	/* get the full device descriptor */
-	err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
-
-	/* try one more time, if error */
-	if (err)
+		/* get the full device descriptor */
 		err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
 
-	if (err) {
-		DPRINTF("addr=%d, getting full desc failed\n",
-		    udev->address);
+		/* try one more time, if error */
+		if (err != 0)
+			err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+		break;
+	}
+
+	if (err != 0) {
+		DPRINTFN(0, "getting device descriptor "
+		    "at addr %d failed, %s\n", udev->address,
+		    usbd_errstr(err));
 		return (err);
 	}
 


More information about the svn-src-all mailing list