1 /* $NetBSD: uhub.c,v 1.107 2009/09/04 18:14:41 dyoung Exp $ */
2 /* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $ */
5 * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (lennart@augustsson.net) at
10 * Carlstedt Research & Technology.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
35 * USB spec: http://www.usb.org/developers/docs/usbspec.zip
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.107 2009/09/04 18:14:41 dyoung Exp $");
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #include <sys/device.h>
50 #include <dev/usb/usb.h>
51 #include <dev/usb/usbdi.h>
52 #include <dev/usb/usbdi_util.h>
53 #include <dev/usb/usbdivar.h>
56 #define DPRINTF(x) if (uhubdebug) logprintf x
57 #define DPRINTFN(n,x) if (uhubdebug>(n)) logprintf x
65 USBBASEDEVICE sc_dev
; /* base device */
66 usbd_device_handle sc_hub
; /* USB device */
67 int sc_proto
; /* device protocol */
68 usbd_pipe_handle sc_ipipe
; /* interrupt pipe */
70 /* XXX second buffer needed because we can't suspend pipes yet */
71 u_int8_t
*sc_statusbuf
;
74 int sc_explorepending
;
75 int sc_isehciroothub
; /* see comment in uhub_intr() */
80 #define UHUB_IS_HIGH_SPEED(sc) ((sc)->sc_proto != UDPROTO_FSHUB)
81 #define UHUB_IS_SINGLE_TT(sc) ((sc)->sc_proto == UDPROTO_HSHUBSTT)
83 #define PORTSTAT_ISSET(sc, port) \
84 ((sc)->sc_status[(port) / 8] & (1 << ((port) % 8)))
86 Static usbd_status
uhub_explore(usbd_device_handle hub
);
87 Static
void uhub_intr(usbd_xfer_handle
, usbd_private_handle
,usbd_status
);
91 * We need two attachment points:
92 * hub to usb and hub to hub
93 * Every other driver only connects to hubs
96 int uhub_match(device_t
, cfdata_t
, void *);
97 void uhub_attach(device_t
, device_t
, void *);
98 int uhub_rescan(device_t
, const char *, const int *);
99 void uhub_childdet(device_t
, device_t
);
100 int uhub_detach(device_t
, int);
101 extern struct cfdriver uhub_cd
;
102 CFATTACH_DECL3_NEW(uhub
, sizeof(struct uhub_softc
), uhub_match
,
103 uhub_attach
, uhub_detach
, NULL
, uhub_rescan
, uhub_childdet
,
104 DVF_DETACH_SHUTDOWN
);
105 CFATTACH_DECL2_NEW(uroothub
, sizeof(struct uhub_softc
), uhub_match
,
106 uhub_attach
, uhub_detach
, NULL
, uhub_rescan
, uhub_childdet
);
109 uhub_match(device_t parent
, cfdata_t match
, void *aux
)
111 struct usb_attach_arg
*uaa
= aux
;
113 DPRINTFN(5,("uhub_match, uaa=%p\n", uaa
));
115 * The subclass for hubs seems to be 0 for some and 1 for others,
116 * so we just ignore the subclass.
118 if (uaa
->class == UDCLASS_HUB
)
119 return (UMATCH_DEVCLASS_DEVSUBCLASS
);
120 return (UMATCH_NONE
);
124 uhub_attach(device_t parent
, device_t self
, void *aux
)
126 struct uhub_softc
*sc
= device_private(self
);
127 struct usb_attach_arg
*uaa
= aux
;
128 usbd_device_handle dev
= uaa
->device
;
131 struct usbd_hub
*hub
= NULL
;
132 usb_device_request_t req
;
133 usb_hub_descriptor_t hubdesc
;
134 int p
, port
, nports
, nremov
, pwrdly
;
135 usbd_interface_handle iface
;
136 usb_endpoint_descriptor_t
*ed
;
138 struct usbd_tt
*tts
= NULL
;
141 DPRINTFN(1,("uhub_attach\n"));
144 sc
->sc_proto
= uaa
->proto
;
146 devinfop
= usbd_devinfo_alloc(dev
, 1);
148 aprint_normal(": %s\n", devinfop
);
149 usbd_devinfo_free(devinfop
);
151 if (dev
->depth
> 0 && UHUB_IS_HIGH_SPEED(sc
)) {
152 aprint_normal_dev(self
, "%s transaction translator%s\n",
153 UHUB_IS_SINGLE_TT(sc
) ? "single" : "multiple",
154 UHUB_IS_SINGLE_TT(sc
) ? "" : "s");
157 err
= usbd_set_config_index(dev
, 0, 1);
159 DPRINTF(("%s: configuration failed, error=%s\n",
160 device_xname(sc
->sc_dev
), usbd_errstr(err
)));
164 if (dev
->depth
> USB_HUB_MAX_DEPTH
) {
165 aprint_error_dev(self
,
166 "hub depth (%d) exceeded, hub ignored\n",
171 /* Get hub descriptor. */
172 req
.bmRequestType
= UT_READ_CLASS_DEVICE
;
173 req
.bRequest
= UR_GET_DESCRIPTOR
;
174 USETW2(req
.wValue
, UDESC_HUB
, 0);
175 USETW(req
.wIndex
, 0);
176 USETW(req
.wLength
, USB_HUB_DESCRIPTOR_SIZE
);
177 DPRINTFN(1,("usb_init_hub: getting hub descriptor\n"));
178 err
= usbd_do_request(dev
, &req
, &hubdesc
);
179 nports
= hubdesc
.bNbrPorts
;
180 if (!err
&& nports
> 7) {
181 USETW(req
.wLength
, USB_HUB_DESCRIPTOR_SIZE
+ (nports
+1) / 8);
182 err
= usbd_do_request(dev
, &req
, &hubdesc
);
185 DPRINTF(("%s: getting hub descriptor failed, error=%s\n",
186 device_xname(sc
->sc_dev
), usbd_errstr(err
)));
190 for (nremov
= 0, port
= 1; port
<= nports
; port
++)
191 if (!UHD_NOT_REMOV(&hubdesc
, port
))
193 aprint_verbose_dev(self
, "%d port%s with %d removable, %s powered\n",
194 nports
, nports
!= 1 ? "s" : "", nremov
,
195 dev
->self_powered
? "self" : "bus");
198 aprint_debug_dev(self
, "no ports, hub ignored\n");
202 hub
= malloc(sizeof(*hub
) + (nports
-1) * sizeof(struct usbd_port
),
207 dev
->hub
->hubsoftc
= sc
;
208 hub
->explore
= uhub_explore
;
209 hub
->hubdesc
= hubdesc
;
211 /* Set up interrupt pipe. */
212 err
= usbd_device2interface_handle(dev
, 0, &iface
);
214 aprint_error_dev(self
, "no interface handle\n");
218 if (UHUB_IS_HIGH_SPEED(sc
) && !UHUB_IS_SINGLE_TT(sc
)) {
219 err
= usbd_set_interface(iface
, 1);
221 aprint_error_dev(self
, "can't enable multiple TTs\n");
224 ed
= usbd_interface2endpoint_descriptor(iface
, 0);
226 aprint_error_dev(self
, "no endpoint descriptor\n");
229 if ((ed
->bmAttributes
& UE_XFERTYPE
) != UE_INTERRUPT
) {
230 aprint_error_dev(self
, "bad interrupt endpoint\n");
234 sc
->sc_statuslen
= (nports
+ 1 + 7) / 8;
235 sc
->sc_statusbuf
= malloc(sc
->sc_statuslen
, M_USBDEV
, M_NOWAIT
);
236 if (!sc
->sc_statusbuf
)
238 sc
->sc_status
= malloc(sc
->sc_statuslen
, M_USBDEV
, M_NOWAIT
);
241 if (device_is_a(device_parent(device_parent(sc
->sc_dev
)), "ehci"))
242 sc
->sc_isehciroothub
= 1;
244 /* force initial scan */
245 memset(sc
->sc_status
, 0xff, sc
->sc_statuslen
);
246 sc
->sc_explorepending
= 1;
248 err
= usbd_open_pipe_intr(iface
, ed
->bEndpointAddress
,
249 USBD_SHORT_XFER_OK
, &sc
->sc_ipipe
, sc
, sc
->sc_statusbuf
,
250 sc
->sc_statuslen
, uhub_intr
, USBD_DEFAULT_INTERVAL
);
252 aprint_error_dev(self
, "cannot open interrupt pipe\n");
256 /* Wait with power off for a while. */
257 usbd_delay_ms(dev
, USB_POWER_DOWN_TIME
);
259 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, dev
, sc
->sc_dev
);
262 * To have the best chance of success we do things in the exact same
263 * order as Windoze98. This should not be necessary, but some
264 * devices do not follow the USB specs to the letter.
266 * These are the events on the bus when a hub is attached:
267 * Get device and config descriptors (see attach code)
268 * Get hub descriptor (see above)
271 * wait for power to become stable
272 * (all below happens in explore code)
274 * clear C_PORT_CONNECTION
277 * if device connected
283 * proceed with device attachment
287 if (UHUB_IS_HIGH_SPEED(sc
) && nports
> 0) {
288 tts
= malloc((UHUB_IS_SINGLE_TT(sc
) ? 1 : nports
) *
289 sizeof (struct usbd_tt
), M_USBDEV
, M_NOWAIT
);
294 /* Set up data structures */
295 for (p
= 0; p
< nports
; p
++) {
296 struct usbd_port
*up
= &hub
->ports
[p
];
300 if (dev
->self_powered
)
301 /* Self powered hub, give ports maximum current. */
302 up
->power
= USB_MAX_POWER
;
304 up
->power
= USB_MIN_POWER
;
308 if (UHUB_IS_HIGH_SPEED(sc
)) {
309 up
->tt
= &tts
[UHUB_IS_SINGLE_TT(sc
) ? 0 : p
];
317 /* XXX should check for none, individual, or ganged power? */
319 pwrdly
= dev
->hub
->hubdesc
.bPwrOn2PwrGood
* UHD_PWRON_FACTOR
320 + USB_EXTRA_POWER_UP_TIME
;
321 for (port
= 1; port
<= nports
; port
++) {
322 /* Turn the power on. */
323 err
= usbd_set_port_feature(dev
, port
, UHF_PORT_POWER
);
325 aprint_error_dev(self
, "port %d power on failed, %s\n",
326 port
, usbd_errstr(err
));
327 DPRINTF(("usb_init_port: turn on port %d power\n", port
));
330 /* Wait for stable power if we are not a root hub */
331 if (dev
->powersrc
->parent
!= NULL
)
332 usbd_delay_ms(dev
, pwrdly
);
334 /* The usual exploration will finish the setup. */
338 if (!pmf_device_register(self
, NULL
, NULL
))
339 aprint_error_dev(self
, "couldn't establish power handler\n");
345 free(sc
->sc_status
, M_USBDEV
);
346 if (sc
->sc_statusbuf
)
347 free(sc
->sc_statusbuf
, M_USBDEV
);
355 uhub_explore(usbd_device_handle dev
)
357 usb_hub_descriptor_t
*hd
= &dev
->hub
->hubdesc
;
358 struct uhub_softc
*sc
= dev
->hub
->hubsoftc
;
359 struct usbd_port
*up
;
363 int change
, status
, reconnect
;
365 DPRINTFN(10, ("uhub_explore dev=%p addr=%d\n", dev
, dev
->address
));
368 return (USBD_NOT_STARTED
);
370 /* Ignore hubs that are too deep. */
371 if (dev
->depth
> USB_HUB_MAX_DEPTH
)
372 return (USBD_TOO_DEEP
);
374 if (PORTSTAT_ISSET(sc
, 0)) { /* hub status change */
377 err
= usbd_get_hub_status(dev
, &hs
);
379 DPRINTF(("%s: get hub status failed, err=%d\n",
380 device_xname(sc
->sc_dev
), err
));
382 /* just acknowledge */
383 status
= UGETW(hs
.wHubStatus
);
384 change
= UGETW(hs
.wHubChange
);
385 if (change
& UHS_LOCAL_POWER
)
386 usbd_clear_hub_feature(dev
,
387 UHF_C_HUB_LOCAL_POWER
);
388 if (change
& UHS_OVER_CURRENT
)
389 usbd_clear_hub_feature(dev
,
390 UHF_C_HUB_OVER_CURRENT
);
394 for (port
= 1; port
<= hd
->bNbrPorts
; port
++) {
395 up
= &dev
->hub
->ports
[port
-1];
397 /* reattach is needed after firmware upload */
398 reconnect
= up
->reattach
;
403 /* don't check if no change summary notification */
404 if (PORTSTAT_ISSET(sc
, port
) || reconnect
) {
405 err
= usbd_get_port_status(dev
, port
, &up
->status
);
407 DPRINTF(("uhub_explore: get port stat failed, "
408 "error=%s\n", usbd_errstr(err
)));
411 status
= UGETW(up
->status
.wPortStatus
);
412 change
= UGETW(up
->status
.wPortChange
);
414 printf("%s port %d: s/c=%x/%x\n",
415 device_xname(sc
->sc_dev
), port
, status
, change
);
418 if (!change
&& !reconnect
) {
419 /* No status change, just do recursive explore. */
420 if (up
->device
!= NULL
&& up
->device
->hub
!= NULL
)
421 up
->device
->hub
->explore(up
->device
);
425 if (change
& UPS_C_PORT_ENABLED
) {
426 DPRINTF(("uhub_explore: C_PORT_ENABLED\n"));
427 usbd_clear_port_feature(dev
, port
, UHF_C_PORT_ENABLE
);
428 if (change
& UPS_C_CONNECT_STATUS
) {
429 /* Ignore the port error if the device
431 } else if (status
& UPS_PORT_ENABLED
) {
432 aprint_error_dev(sc
->sc_dev
,
433 "illegal enable change, port %d\n", port
);
435 /* Port error condition. */
436 if (up
->restartcnt
) /* no message first time */
437 aprint_error_dev(sc
->sc_dev
,
438 "port error, restarting port %d\n",
441 if (up
->restartcnt
++ < USBD_RESTART_MAX
)
444 aprint_error_dev(sc
->sc_dev
,
445 "port error, giving up port %d\n",
450 /* XXX handle overcurrent and resume events! */
452 if (!(change
& UPS_C_CONNECT_STATUS
))
455 /* We have a connect status change, handle it. */
457 DPRINTF(("uhub_explore: status change hub=%d port=%d\n",
458 dev
->address
, port
));
459 usbd_clear_port_feature(dev
, port
, UHF_C_PORT_CONNECTION
);
461 * If there is already a device on the port the change status
462 * must mean that is has disconnected. Looking at the
463 * current connect status is not enough to figure this out
464 * since a new unit may have been connected before we handle
468 if (up
->device
!= NULL
) {
470 DPRINTF(("uhub_explore: device addr=%d disappeared "
471 "on port %d\n", up
->device
->address
, port
));
472 usb_disconnect_port(up
, sc
->sc_dev
, DETACH_FORCE
);
473 usbd_clear_port_feature(dev
, port
,
474 UHF_C_PORT_CONNECTION
);
476 if (!(status
& UPS_CURRENT_CONNECT_STATUS
)) {
477 /* Nothing connected, just ignore it. */
478 DPRINTFN(3,("uhub_explore: port=%d !CURRENT_CONNECT"
485 if (!(status
& UPS_PORT_POWER
))
486 aprint_normal_dev(sc
->sc_dev
,
487 "strange, connected port %d has no power\n", port
);
489 /* Wait for maximum device power up time. */
490 usbd_delay_ms(dev
, USB_PORT_POWERUP_DELAY
);
492 /* Reset port, which implies enabling it. */
493 if (usbd_reset_port(dev
, port
, &up
->status
)) {
494 aprint_error_dev(sc
->sc_dev
,
495 "port %d reset failed\n", port
);
498 /* Get port status again, it might have changed during reset */
499 err
= usbd_get_port_status(dev
, port
, &up
->status
);
501 DPRINTF(("uhub_explore: get port status failed, "
502 "error=%s\n", usbd_errstr(err
)));
505 status
= UGETW(up
->status
.wPortStatus
);
506 change
= UGETW(up
->status
.wPortChange
);
507 if (!(status
& UPS_CURRENT_CONNECT_STATUS
)) {
508 /* Nothing connected, just ignore it. */
510 aprint_debug_dev(sc
->sc_dev
,
511 "port %d, device disappeared after reset\n", port
);
516 /* Figure out device speed */
517 if (status
& UPS_HIGH_SPEED
)
518 speed
= USB_SPEED_HIGH
;
519 else if (status
& UPS_LOW_SPEED
)
520 speed
= USB_SPEED_LOW
;
522 speed
= USB_SPEED_FULL
;
523 /* Get device info and set its address. */
524 err
= usbd_new_device(sc
->sc_dev
, dev
->bus
,
525 dev
->depth
+ 1, speed
, port
, up
);
526 /* XXX retry a few times? */
528 DPRINTFN(-1,("uhub_explore: usb_new_device failed, "
529 "error=%s\n", usbd_errstr(err
)));
530 /* Avoid addressing problems by disabling. */
531 /* usbd_reset_port(dev, port, &up->status); */
534 * The unit refused to accept a new address, or had
535 * some other serious problem. Since we cannot leave
536 * at 0 we have to disable the port instead.
538 aprint_error_dev(sc
->sc_dev
,
539 "device problem, disabling port %d\n", port
);
540 usbd_clear_port_feature(dev
, port
, UHF_PORT_ENABLE
);
542 /* The port set up succeeded, reset error count. */
546 up
->device
->hub
->explore(up
->device
);
549 /* enable status change notifications again */
550 if (!sc
->sc_isehciroothub
)
551 memset(sc
->sc_status
, 0, sc
->sc_statuslen
);
552 sc
->sc_explorepending
= 0;
553 return (USBD_NORMAL_COMPLETION
);
557 * Called from process context when the hub is gone.
558 * Detach all devices on active ports.
561 uhub_detach(device_t self
, int flags
)
563 struct uhub_softc
*sc
= device_private(self
);
564 struct usbd_hub
*hub
= sc
->sc_hub
->hub
;
565 struct usbd_port
*rup
;
566 int nports
, port
, rc
;
568 DPRINTF(("uhub_detach: sc=%p flags=%d\n", sc
, flags
));
570 if (hub
== NULL
) /* Must be partially working */
573 nports
= hub
->hubdesc
.bNbrPorts
;
574 for(port
= 0; port
< nports
; port
++) {
575 rup
= &hub
->ports
[port
];
576 if (rup
->device
== NULL
)
578 if ((rc
= usb_disconnect_port(rup
, self
, flags
)) != 0)
582 pmf_device_deregister(self
);
583 usbd_abort_pipe(sc
->sc_ipipe
);
584 usbd_close_pipe(sc
->sc_ipipe
);
586 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH
, sc
->sc_hub
, sc
->sc_dev
);
589 if (hub
->ports
[0].tt
)
590 free(hub
->ports
[0].tt
, M_USBDEV
);
593 sc
->sc_hub
->hub
= NULL
;
595 free(sc
->sc_status
, M_USBDEV
);
596 if (sc
->sc_statusbuf
)
597 free(sc
->sc_statusbuf
, M_USBDEV
);
603 uhub_rescan(device_t self
, const char *ifattr
, const int *locators
)
605 struct uhub_softc
*sc
= device_private(self
);
606 struct usbd_hub
*hub
= sc
->sc_hub
->hub
;
607 usbd_device_handle dev
;
610 for (port
= 0; port
< hub
->hubdesc
.bNbrPorts
; port
++) {
611 dev
= hub
->ports
[port
].device
;
614 err
= usbd_reattach_device(sc
->sc_dev
, dev
, port
, locators
);
619 /* Called when a device has been detached from it */
621 uhub_childdet(device_t self
, device_t child
)
623 struct uhub_softc
*sc
= device_private(self
);
624 usbd_device_handle devhub
= sc
->sc_hub
;
625 usbd_device_handle dev
;
631 /* should never happen; children are only created after init */
632 panic("hub not fully initialised, but child deleted?");
634 nports
= devhub
->hub
->hubdesc
.bNbrPorts
;
635 for (port
= 0; port
< nports
; port
++) {
636 dev
= devhub
->hub
->ports
[port
].device
;
639 for (i
= 0; i
< dev
->subdevlen
; i
++) {
640 if (dev
->subdevs
[i
] == child
) {
641 dev
->subdevs
[i
] = NULL
;
642 dev
->nifaces_claimed
--;
651 * This an indication that some port has changed status.
652 * Notify the bus event handler thread that we need
653 * to be explored again.
656 uhub_intr(usbd_xfer_handle xfer
, usbd_private_handle addr
, usbd_status status
)
658 struct uhub_softc
*sc
= addr
;
660 DPRINTFN(5,("uhub_intr: sc=%p\n", sc
));
662 if (status
== USBD_STALLED
)
663 usbd_clear_endpoint_stall_async(sc
->sc_ipipe
);
664 else if (status
== USBD_NORMAL_COMPLETION
&&
665 !sc
->sc_explorepending
) {
667 * Make sure the status is not overwritten in between.
668 * XXX we should suspend the pipe instead
670 memcpy(sc
->sc_status
, sc
->sc_statusbuf
, sc
->sc_statuslen
);
671 sc
->sc_explorepending
= 1;
672 usb_needs_explore(sc
->sc_hub
);
675 * XXX workaround for broken implementation of the interrupt
676 * pipe in EHCI root hub emulation which doesn't resend
677 * status change notifications until handled: force a rescan
678 * of the ports we touched in the last run
680 if (status
== USBD_NORMAL_COMPLETION
&& sc
->sc_explorepending
&&
681 sc
->sc_isehciroothub
)
682 usb_needs_explore(sc
->sc_hub
);