summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorkevlo <kevlo@FreeBSD.org>2007-05-08 03:25:05 +0000
committerkevlo <kevlo@FreeBSD.org>2007-05-08 03:25:05 +0000
commit872320ec7590f3fe30f5abbbbcf2262b10c3cac4 (patch)
tree7c8d05d4c85bcfa8d71e4d0e4484d1d321836528 /sys/dev
parentd4d5d36cfcdb27651bcdacae4415c01475b6ca78 (diff)
downloadFreeBSD-src-872320ec7590f3fe30f5abbbbcf2262b10c3cac4.zip
FreeBSD-src-872320ec7590f3fe30f5abbbbcf2262b10c3cac4.tar.gz
Do not set address early. It fix problems when SET_ADDR_FAILED happens
on the hubs. Reviewed by: imp
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/usb_subr.c51
1 files changed, 27 insertions, 24 deletions
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 4c5d5ca..1512e85 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1085,11 +1085,12 @@ usbd_new_device(device_t parent, usbd_bus_handle bus, int depth,
return (err);
}
- /* Set the address. Do this early; some devices need that. */
+ dd = &dev->ddesc;
/* Try a few times in case the device is slow (i.e. outside specs.) */
DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
for (i = 0; i < 15; i++) {
- err = usbd_set_address(dev, addr);
+ /* Get the first 8 bytes of the device descriptor. */
+ err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
if (!err)
break;
usbd_delay_ms(dev, 200);
@@ -1098,30 +1099,8 @@ usbd_new_device(device_t parent, usbd_bus_handle bus, int depth,
"failed - trying a port reset\n", addr));
usbd_reset_port(up->parent, port, &ps);
}
- }
- if (err) {
- DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
- err = USBD_SET_ADDR_FAILED;
- usbd_remove_device(dev, up);
- return (err);
- }
- /* Allow device time to set new address */
- usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
- dev->address = addr; /* New device address now */
- bus->devices[addr] = dev;
- /* Re-establish the default pipe with the new address. */
- usbd_kill_pipe(dev->default_pipe);
- err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
- &dev->default_pipe);
- if (err) {
- usbd_remove_device(dev, up);
- return (err);
}
-
- dd = &dev->ddesc;
- /* Get the first 8 bytes of the device descriptor. */
- err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
if (err) {
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
"failed\n", addr));
@@ -1179,6 +1158,30 @@ usbd_new_device(device_t parent, usbd_bus_handle bus, int depth,
return (err);
}
+ /* Set the address */
+ DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
+ err = usbd_set_address(dev, addr);
+ if (err) {
+ DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
+ err = USBD_SET_ADDR_FAILED;
+ usbd_remove_device(dev, up);
+ return (err);
+ }
+
+ /* Allow device time to set new address */
+ usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
+ dev->address = addr; /* New device address now */
+ bus->devices[addr] = dev;
+
+ /* Re-establish the default pipe with the new address. */
+ usbd_kill_pipe(dev->default_pipe);
+ err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+ &dev->default_pipe);
+ if (err) {
+ usbd_remove_device(dev, up);
+ return (err);
+ }
+
/* Assume 100mA bus powered for now. Changed when configured. */
dev->power = USB_MIN_POWER;
dev->self_powered = 0;
OpenPOWER on IntegriCloud