Author: hselasky
Date: Tue Sep 17 12:50:57 2013
New Revision: 255630
URL: http://svnweb.freebsd.org/changeset/base/255630

Log:
  MFC r248246:
  
  - 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.

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

Modified: stable/9/sys/dev/usb/usb_device.c
==============================================================================
--- stable/9/sys/dev/usb/usb_device.c   Tue Sep 17 11:48:47 2013        
(r255629)
+++ stable/9/sys/dev/usb/usb_device.c   Tue Sep 17 12:50:57 2013        
(r255630)
@@ -1673,10 +1673,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: stable/9/sys/dev/usb/usb_request.c
==============================================================================
--- stable/9/sys/dev/usb/usb_request.c  Tue Sep 17 11:48:47 2013        
(r255629)
+++ stable/9/sys/dev/usb/usb_request.c  Tue Sep 17 12:50:57 2013        
(r255630)
@@ -71,6 +71,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. */
@@ -996,7 +1001,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) {
@@ -1881,32 +1886,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);
        }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to