diff options
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/usb_port.h | 5 | ||||
-rw-r--r-- | sys/dev/usb/usb_subr.c | 40 | ||||
-rw-r--r-- | sys/dev/usb/usbdi.h | 3 |
3 files changed, 44 insertions, 4 deletions
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h index 3342c7999d0..c830e6e1820 100644 --- a/sys/dev/usb/usb_port.h +++ b/sys/dev/usb/usb_port.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usb_port.h,v 1.51 2004/10/05 02:01:18 jsg Exp $ */ +/* $OpenBSD: usb_port.h,v 1.52 2004/11/08 22:01:02 dlg Exp $ */ /* $NetBSD: usb_port.h,v 1.62 2003/02/15 18:33:30 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.21 1999/11/17 22:33:47 n_hibma Exp $ */ @@ -175,6 +175,7 @@ void __CONCAT(dname,_attach)(struct device *parent, struct device *self, void *a /* Returns from attach */ #define USB_ATTACH_ERROR_RETURN return #define USB_ATTACH_SUCCESS_RETURN return +#define USB_ATTACH_NEED_RESET return #define USB_ATTACH_SETUP printf("\n") @@ -371,6 +372,7 @@ __CONCAT(dname,_attach)(parent, self, aux) \ /* Returns from attach */ #define USB_ATTACH_ERROR_RETURN return #define USB_ATTACH_SUCCESS_RETURN return +#define USB_ATTACH_NEED_RESET return #define USB_ATTACH_SETUP printf("\n") @@ -495,6 +497,7 @@ __CONCAT(dname,_attach)(device_t self) /* Returns from attach */ #define USB_ATTACH_ERROR_RETURN return ENXIO #define USB_ATTACH_SUCCESS_RETURN return 0 +#define USB_ATTACH_NEED_RESET return EAGAIN #define USB_ATTACH_SETUP \ sc->sc_dev = self; \ 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; diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 2df02e6e854..59dd476ad0c 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdi.h,v 1.21 2003/07/08 13:19:09 nate Exp $ */ +/* $OpenBSD: usbdi.h,v 1.22 2004/11/08 22:01:02 dlg Exp $ */ /* $NetBSD: usbdi.h,v 1.62 2002/07/11 21:14:35 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $ */ @@ -67,6 +67,7 @@ typedef enum { /* keep in sync with usbd_status_msgs */ USBD_SHORT_XFER, /* 16 */ USBD_STALLED, /* 17 */ USBD_INTERRUPTED, /* 18 */ + USBD_NEED_RESET, /* 19 */ USBD_ERROR_MAX /* must be last */ } usbd_status; |