diff options
| author | Ian Dowse <iedowse@FreeBSD.org> | 2004-11-03 01:52:50 +0000 |
|---|---|---|
| committer | Ian Dowse <iedowse@FreeBSD.org> | 2004-11-03 01:52:50 +0000 |
| commit | f79bef60979a43b9f4ac0f03ca4e53eefc65c8e3 (patch) | |
| tree | d9d339fddbadd971663de538f170ee9d422eda06 /sys/dev/usb/uhub.c | |
| parent | 9a2050f9b4ecf113569064ad06f8e49e58a2dff5 (diff) | |
Notes
Diffstat (limited to 'sys/dev/usb/uhub.c')
| -rw-r--r-- | sys/dev/usb/uhub.c | 48 |
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; |
