diff options
Diffstat (limited to 'sys/dev/usb/usb_subr.c')
-rw-r--r-- | sys/dev/usb/usb_subr.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index c251f8cd900..6f485ffa0c7 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usb_subr.c,v 1.30 2004/11/02 21:28:55 dlg Exp $ */ +/* $OpenBSD: usb_subr.c,v 1.31 2004/11/08 22:01:02 dlg Exp $ */ /* $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */ @@ -87,6 +87,8 @@ Static int usbd_submatch(device_ptr_t, struct cfdata *cf, void *); Static int usbd_print(void *aux, const char *pnp); Static int usbd_submatch(device_ptr_t, void *, void *); #endif +Static usbd_status usbd_new_device2(device_ptr_t, usbd_bus_handle, int, int, + int, struct usbd_port *); Static void usbd_free_iface_data(usbd_device_handle dev, int ifcno); Static void usbd_kill_pipe(usbd_pipe_handle); Static usbd_status usbd_probe_and_attach(device_ptr_t parent, @@ -132,6 +134,7 @@ Static const char * const usbd_error_strs[] = { "SHORT_XFER", "STALLED", "INTERRUPTED", + "NEED_RESET", "XXX", }; @@ -918,6 +921,13 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev, uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber; dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch); + if (dev->address == USB_START_ADDR) { +#if defined(__FreeBSD__) + device_delete_child(parent, bdev); +#endif + return (USBD_NEED_RESET); + } + if (dv != NULL) { dev->subdevs[found++] = dv; dev->subdevs[found] = 0; @@ -987,7 +997,7 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev, * and attach a driver. */ usbd_status -usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, +usbd_new_device2(device_ptr_t parent, usbd_bus_handle bus, int depth, int speed, int port, struct usbd_port *up) { usbd_device_handle dev; @@ -1132,6 +1142,11 @@ usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, err = usbd_probe_and_attach(parent, dev, port, addr); if (err) { + if (err == USBD_NEED_RESET) { + DPRINTF(("usbd_new_device2: device needs reset\n")); + /* must set address back to what it was */ + dev->address = addr; + } usbd_remove_device(dev, up); return (err); } @@ -1140,6 +1155,27 @@ usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, } usbd_status +usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, + int speed, int ports, struct usbd_port *up) +{ + int retry = 0; + usbd_status err; + + do { + if (retry > 0) + DPRINTF(("usbd_new_device: re-enumerating device\n")); + err = usbd_new_device2(parent, bus, depth, speed, ports, up); + } while ((err == USBD_NEED_RESET) && (retry++ < 5)); + + if (retry == 5) { + DPRINTF(("usbd_new_device: giving up after 5 tries\n")); + return (USBD_NOT_CONFIGURED); + } + + return (err); +} + +usbd_status usbd_reload_device_desc(usbd_device_handle dev) { usbd_status err; |