summaryrefslogtreecommitdiff
path: root/sys/dev/usb/usb_subr.c
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2005-03-13 02:54:05 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2005-03-13 02:54:05 +0000
commit8c99b398138993b55eb5ecb7fd935e8315be1a12 (patch)
treeb89bccbb6b5267d4fed6dc98657bda69c14377a2 /sys/dev/usb/usb_subr.c
parent7d158c4e4058c60a5af4a4a03f0054b0381d62b4 (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.c33
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;
}
}