summaryrefslogtreecommitdiff
path: root/sys/dev/usb/uhub.c
diff options
context:
space:
mode:
authorIan Dowse <iedowse@FreeBSD.org>2004-11-03 01:52:50 +0000
committerIan Dowse <iedowse@FreeBSD.org>2004-11-03 01:52:50 +0000
commitf79bef60979a43b9f4ac0f03ca4e53eefc65c8e3 (patch)
treed9d339fddbadd971663de538f170ee9d422eda06 /sys/dev/usb/uhub.c
parent9a2050f9b4ecf113569064ad06f8e49e58a2dff5 (diff)
Notes
Diffstat (limited to 'sys/dev/usb/uhub.c')
-rw-r--r--sys/dev/usb/uhub.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index 54affde4750c..53784584a04a 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -85,6 +85,9 @@ struct uhub_softc {
u_int8_t sc_status[1]; /* XXX more ports */
u_char sc_running;
};
+#define UHUB_PROTO(sc) ((sc)->sc_hub->ddesc.bDeviceProtocol)
+#define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB)
+#define UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT)
Static usbd_status uhub_explore(usbd_device_handle hub);
Static void uhub_intr(usbd_xfer_handle, usbd_private_handle,usbd_status);
@@ -162,12 +165,13 @@ USB_ATTACH(uhub)
usbd_device_handle dev = uaa->device;
char *devinfo;
usbd_status err;
- struct usbd_hub *hub;
+ struct usbd_hub *hub = NULL;
usb_device_request_t req;
usb_hub_descriptor_t hubdesc;
int p, port, nports, nremov, pwrdly;
usbd_interface_handle iface;
usb_endpoint_descriptor_t *ed;
+ struct usbd_tt *tts = NULL;
devinfo = malloc(1024, M_TEMP, M_NOWAIT);
if (devinfo == NULL) {
@@ -178,6 +182,12 @@ USB_ATTACH(uhub)
usbd_devinfo(dev, 1, devinfo);
USB_ATTACH_SETUP;
+ if (UHUB_IS_HIGH_SPEED(sc)) {
+ printf("%s: %s transaction translator%s\n",
+ USBDEVNAME(sc->sc_dev),
+ UHUB_IS_SINGLE_TT(sc) ? "single" : "multiple",
+ UHUB_IS_SINGLE_TT(sc) ? "" : "s");
+ }
err = usbd_set_config_index(dev, 0, 1);
if (err) {
DPRINTF(("%s: configuration failed, error=%s\n",
@@ -220,6 +230,11 @@ USB_ATTACH(uhub)
USBDEVNAME(sc->sc_dev), nports, nports != 1 ? "s" : "",
nremov, dev->self_powered ? "self" : "bus");
+ if (nports == 0) {
+ printf("%s: no ports, hub ignored\n", USBDEVNAME(sc->sc_dev));
+ goto bad;
+ }
+
hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
M_USBDEV, M_NOWAIT);
if (hub == NULL) {
@@ -299,10 +314,17 @@ USB_ATTACH(uhub)
* proceed with device attachment
*/
+ if (UHUB_IS_HIGH_SPEED(sc)) {
+ tts = malloc((UHUB_IS_SINGLE_TT(sc) ? 1 : nports) *
+ sizeof (struct usbd_tt), M_USBDEV, M_NOWAIT);
+ if (!tts)
+ goto bad;
+ }
+
/* Set up data structures */
for (p = 0; p < nports; p++) {
struct usbd_port *up = &hub->ports[p];
- up->device = 0;
+ up->device = NULL;
up->parent = dev;
up->portno = p+1;
if (dev->self_powered)
@@ -311,6 +333,12 @@ USB_ATTACH(uhub)
else
up->power = USB_MIN_POWER;
up->restartcnt = 0;
+ if (UHUB_IS_HIGH_SPEED(sc)) {
+ up->tt = &tts[UHUB_IS_SINGLE_TT(sc) ? 0 : p];
+ up->tt->hub = hub;
+ } else {
+ up->tt = NULL;
+ }
}
/* XXX should check for none, individual, or ganged power? */
@@ -336,9 +364,10 @@ USB_ATTACH(uhub)
USB_ATTACH_SUCCESS_RETURN;
bad:
- free(hub, M_USBDEV);
+ if (hub)
+ free(hub, M_USBDEV);
free(devinfo, M_TEMP);
- dev->hub = 0;
+ dev->hub = NULL;
USB_ATTACH_ERROR_RETURN;
}
@@ -475,6 +504,15 @@ uhub_explore(usbd_device_handle dev)
continue;
}
+#if 0
+ if (UHUB_IS_HIGH_SPEED(sc) && !(status & UPS_HIGH_SPEED)) {
+ printf("%s: port %d, transaction translation not "
+ "implemented, low/full speed device ignored\n",
+ USBDEVNAME(sc->sc_dev), port);
+ continue;
+ }
+#endif
+
/* Figure out device speed */
if (status & UPS_HIGH_SPEED)
speed = USB_SPEED_HIGH;
@@ -574,6 +612,8 @@ USB_DETACH(uhub)
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub,
USBDEV(sc->sc_dev));
+ if (hub->ports[0].tt)
+ free(hub->ports[0].tt, M_USBDEV);
free(hub, M_USBDEV);
sc->sc_hub->hub = NULL;