summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/usb_port.h5
-rw-r--r--sys/dev/usb/usb_subr.c40
-rw-r--r--sys/dev/usb/usbdi.h3
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;