From: mpi Date: Sat, 9 Aug 2014 09:58:11 +0000 (+0000) Subject: Correctly recognize Super Speed devices, this is part of the work to X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=1cb1f490f27aeffb466a6ac2f29e0754bac6c159;p=openbsd Correctly recognize Super Speed devices, this is part of the work to be able to use USB 3.0 devices behind an external hub. This is a bit tricky because the SS status use a different power bit that maps to the Low speed one. So no longer accept devices without power bit and fallback to the parent hub's speed in case the status does not report any particular speed. Note that xhci(4) root hubs still set the traditionnal UPS_PORT_POWER bit with the correct device speed. --- diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index 29cdbb1c2b4..6a2d90b61df 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uhub.c,v 1.71 2014/08/09 09:48:32 mpi Exp $ */ +/* $OpenBSD: uhub.c,v 1.72 2014/08/09 09:58:11 mpi Exp $ */ /* $NetBSD: uhub.c,v 1.64 2003/02/08 03:32:51 ichiro Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $ */ @@ -414,9 +414,11 @@ uhub_explore(struct usbd_device *dev) } /* Connected */ - if (!(status & UPS_PORT_POWER)) - printf("%s: strange, connected port %d has no power\n", + if (!(status & (UPS_PORT_POWER|UPS_PORT_POWER_SS))) { + printf("%s: connected port %d has no power\n", sc->sc_dev.dv_xname, port); + continue; + } /* Wait for maximum device power up time. */ usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY); @@ -443,15 +445,31 @@ uhub_explore(struct usbd_device *dev) continue; } - /* Figure out device speed */ + /* + * Figure out device speed. This is a bit tricky because + * UPS_PORT_POWER_SS and UPS_LOW_SPEED share the same bit. + */ + if ((status & UPS_PORT_POWER) == 0) + status &= ~UPS_PORT_POWER_SS; + if (status & UPS_SUPER_SPEED) speed = USB_SPEED_SUPER; else if (status & UPS_HIGH_SPEED) speed = USB_SPEED_HIGH; else if (status & UPS_LOW_SPEED) speed = USB_SPEED_LOW; - else - speed = USB_SPEED_FULL; + else { + /* + * If there is no power bit set, it is certainly + * a Super Speed device, so use the speed of its + * parent hub. + */ + if (status & UPS_PORT_POWER) + speed = USB_SPEED_FULL; + else + speed = sc->sc_hub->speed; + } + /* Get device info and set its address. */ err = usbd_new_device(&sc->sc_dev, dev->bus, dev->depth + 1, speed, port, up);