diff options
author | hselasky <hselasky@FreeBSD.org> | 2013-03-13 15:38:01 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2013-03-13 15:38:01 +0000 |
commit | 2dd657bd7aafaa0d84f9879afac81a09b1b6994a (patch) | |
tree | 14ef109da101eccc8fa4e029d607411fe9ea7377 /sys/dev/usb | |
parent | 0b8d7927213de8679fda3f58d460b754fe2f65f0 (diff) | |
download | FreeBSD-src-2dd657bd7aafaa0d84f9879afac81a09b1b6994a.zip FreeBSD-src-2dd657bd7aafaa0d84f9879afac81a09b1b6994a.tar.gz |
- 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
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/usb_device.c | 10 | ||||
-rw-r--r-- | sys/dev/usb/usb_request.c | 52 |
2 files changed, 40 insertions, 22 deletions
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index 1c40815..43378c0 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -1698,10 +1698,14 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, 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; + } + } } /* diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c index 1a366d6..d24a39f 100644 --- a/sys/dev/usb/usb_request.c +++ b/sys/dev/usb/usb_request.c @@ -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 *udev, 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 *udev, struct mtx *mtx) */ 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); } |