diff options
author | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2005-03-13 02:54:05 +0000 |
---|---|---|
committer | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2005-03-13 02:54:05 +0000 |
commit | 8c99b398138993b55eb5ecb7fd935e8315be1a12 (patch) | |
tree | b89bccbb6b5267d4fed6dc98657bda69c14377a2 /sys/dev/usb/usb_subr.c | |
parent | 7d158c4e4058c60a5af4a4a03f0054b0381d62b4 (diff) |
Merge support for USB1 devices located beyond USB2 hubs, mostly from netbsd.
Supports bulk, control and interrupt pipes, letting USB1 keyboards and most
network interfaces work when connected to a USB2 hub.
ok dlg@
Diffstat (limited to 'sys/dev/usb/usb_subr.c')
-rw-r--r-- | sys/dev/usb/usb_subr.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index dd66a79118e..9023bf131c5 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.32 2004/12/12 06:13:15 dlg Exp $ */ +/* $OpenBSD: usb_subr.c,v 1.33 2005/03/13 02:54:04 pascoe 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 $ */ @@ -991,12 +991,13 @@ usbd_status usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, int speed, int port, struct usbd_port *up) { - usbd_device_handle dev; + usbd_device_handle dev, adev; struct usbd_device *hub; usb_device_descriptor_t *dd; usbd_status err; int addr; int i; + int p; DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n", bus, port, depth, speed)); @@ -1031,11 +1032,27 @@ usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, dev->depth = depth; dev->powersrc = up; dev->myhub = up->parent; - for (hub = up->parent; + + up->device = dev; + + /* Locate port on upstream high speed hub */ + for (adev = dev, hub = up->parent; hub != NULL && hub->speed != USB_SPEED_HIGH; - hub = hub->myhub) + adev = hub, hub = hub->myhub) ; - dev->myhighhub = hub; + if (hub) { + for (p = 0; p < hub->hub->hubdesc.bNbrPorts; p++) { + if (hub->hub->ports[p].device == adev) { + dev->myhsport = &hub->hub->ports[p]; + goto found; + } + } + panic("usbd_new_device: cannot find HS port\n"); + found: + DPRINTFN(1,("usbd_new_device: high speed port %d\n", p)); + } else { + dev->myhsport = NULL; + } dev->speed = speed; dev->langid = USBD_NOLANG; dev->cookie.cookie = ++usb_cookie_no; @@ -1048,7 +1065,6 @@ usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, return (err); } - up->device = dev; dd = &dev->ddesc; /* Try a few times in case the device is slow (i.e. outside specs.) */ for (i = 0; i < 5; i++) { @@ -1163,8 +1179,8 @@ usbd_remove_device(usbd_device_handle dev, struct usbd_port *up) if (dev->default_pipe != NULL) usbd_kill_pipe(dev->default_pipe); - up->device = 0; - dev->bus->devices[dev->address] = 0; + up->device = NULL; + dev->bus->devices[dev->address] = NULL; free(dev, M_USB); } @@ -1389,6 +1405,7 @@ usb_disconnect_port(struct usbd_port *up, device_ptr_t parent) printf(" port %d", up->portno); printf(" (addr %d) disconnected\n", dev->address); config_detach(dev->subdevs[i], DETACH_FORCE); + dev->subdevs[i] = 0; } } |