diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2004-11-08 22:01:03 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2004-11-08 22:01:03 +0000 |
commit | 5b2e6176bd8b46ac495f1110a2a7c07df3ce7b7c (patch) | |
tree | 54c1f69111365a3e8b4e0c6a7ff91f82d20d1774 /sys/dev | |
parent | 51c8f7d1a98e8bd1b35c9312164d5e07b7db36df (diff) |
ugly ugly hack to allow a usb device to do a full reset of the port during
attach.
this is required by atu (atmel based usb wireless) devices. something better
will be done, but we need it for now to work on atu.
ok deraadt@
Diffstat (limited to 'sys/dev')
-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; |