usb_hub.c revision 213432
1/* $FreeBSD: head/sys/dev/usb/usb_hub.c 213432 2010-10-04 22:21:30Z hselasky $ */
2/*-
3 * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
4 * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
5 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29/*
30 * USB spec: http://www.usb.org/developers/docs/usbspec.zip
31 */
32
33#include <sys/stdint.h>
34#include <sys/stddef.h>
35#include <sys/param.h>
36#include <sys/queue.h>
37#include <sys/types.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/bus.h>
41#include <sys/linker_set.h>
42#include <sys/module.h>
43#include <sys/lock.h>
44#include <sys/mutex.h>
45#include <sys/condvar.h>
46#include <sys/sysctl.h>
47#include <sys/sx.h>
48#include <sys/unistd.h>
49#include <sys/callout.h>
50#include <sys/malloc.h>
51#include <sys/priv.h>
52
53#include <dev/usb/usb.h>
54#include <dev/usb/usb_ioctl.h>
55#include <dev/usb/usbdi.h>
56#include <dev/usb/usbdi_util.h>
57
58#define	USB_DEBUG_VAR uhub_debug
59
60#include <dev/usb/usb_core.h>
61#include <dev/usb/usb_process.h>
62#include <dev/usb/usb_device.h>
63#include <dev/usb/usb_request.h>
64#include <dev/usb/usb_debug.h>
65#include <dev/usb/usb_hub.h>
66#include <dev/usb/usb_util.h>
67#include <dev/usb/usb_busdma.h>
68#include <dev/usb/usb_transfer.h>
69#include <dev/usb/usb_dynamic.h>
70
71#include <dev/usb/usb_controller.h>
72#include <dev/usb/usb_bus.h>
73
74#define	UHUB_INTR_INTERVAL 250		/* ms */
75#define	UHUB_N_TRANSFER 1
76
77#ifdef USB_DEBUG
78static int uhub_debug = 0;
79
80SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB");
81SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW, &uhub_debug, 0,
82    "Debug level");
83
84TUNABLE_INT("hw.usb.uhub.debug", &uhub_debug);
85#endif
86
87#if USB_HAVE_POWERD
88static int usb_power_timeout = 30;	/* seconds */
89
90SYSCTL_INT(_hw_usb, OID_AUTO, power_timeout, CTLFLAG_RW,
91    &usb_power_timeout, 0, "USB power timeout");
92#endif
93
94struct uhub_current_state {
95	uint16_t port_change;
96	uint16_t port_status;
97};
98
99struct uhub_softc {
100	struct uhub_current_state sc_st;/* current state */
101	device_t sc_dev;		/* base device */
102	struct mtx sc_mtx;		/* our mutex */
103	struct usb_device *sc_udev;	/* USB device */
104	struct usb_xfer *sc_xfer[UHUB_N_TRANSFER];	/* interrupt xfer */
105	uint8_t	sc_flags;
106#define	UHUB_FLAG_DID_EXPLORE 0x01
107	char	sc_name[32];
108};
109
110#define	UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol)
111#define	UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB)
112#define	UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT)
113
114/* prototypes for type checking: */
115
116static device_probe_t uhub_probe;
117static device_attach_t uhub_attach;
118static device_detach_t uhub_detach;
119static device_suspend_t uhub_suspend;
120static device_resume_t uhub_resume;
121
122static bus_driver_added_t uhub_driver_added;
123static bus_child_location_str_t uhub_child_location_string;
124static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
125
126static usb_callback_t uhub_intr_callback;
127
128static void usb_dev_resume_peer(struct usb_device *udev);
129static void usb_dev_suspend_peer(struct usb_device *udev);
130static uint8_t usb_peer_should_wakeup(struct usb_device *udev);
131
132static const struct usb_config uhub_config[UHUB_N_TRANSFER] = {
133
134	[0] = {
135		.type = UE_INTERRUPT,
136		.endpoint = UE_ADDR_ANY,
137		.direction = UE_DIR_ANY,
138		.timeout = 0,
139		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
140		.bufsize = 0,	/* use wMaxPacketSize */
141		.callback = &uhub_intr_callback,
142		.interval = UHUB_INTR_INTERVAL,
143	},
144};
145
146/*
147 * driver instance for "hub" connected to "usb"
148 * and "hub" connected to "hub"
149 */
150static devclass_t uhub_devclass;
151
152static device_method_t uhub_methods[] = {
153	DEVMETHOD(device_probe, uhub_probe),
154	DEVMETHOD(device_attach, uhub_attach),
155	DEVMETHOD(device_detach, uhub_detach),
156
157	DEVMETHOD(device_suspend, uhub_suspend),
158	DEVMETHOD(device_resume, uhub_resume),
159
160	DEVMETHOD(bus_child_location_str, uhub_child_location_string),
161	DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_string),
162	DEVMETHOD(bus_driver_added, uhub_driver_added),
163	{0, 0}
164};
165
166static driver_t uhub_driver = {
167	.name = "uhub",
168	.methods = uhub_methods,
169	.size = sizeof(struct uhub_softc)
170};
171
172DRIVER_MODULE(uhub, usbus, uhub_driver, uhub_devclass, 0, 0);
173DRIVER_MODULE(uhub, uhub, uhub_driver, uhub_devclass, NULL, 0);
174MODULE_VERSION(uhub, 1);
175
176static void
177uhub_intr_callback(struct usb_xfer *xfer, usb_error_t error)
178{
179	struct uhub_softc *sc = usbd_xfer_softc(xfer);
180
181	switch (USB_GET_STATE(xfer)) {
182	case USB_ST_TRANSFERRED:
183		DPRINTFN(2, "\n");
184		/*
185		 * This is an indication that some port
186		 * has changed status. Notify the bus
187		 * event handler thread that we need
188		 * to be explored again:
189		 */
190		usb_needs_explore(sc->sc_udev->bus, 0);
191
192	case USB_ST_SETUP:
193		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
194		usbd_transfer_submit(xfer);
195		break;
196
197	default:			/* Error */
198		if (xfer->error != USB_ERR_CANCELLED) {
199			/*
200			 * Do a clear-stall. The "stall_pipe" flag
201			 * will get cleared before next callback by
202			 * the USB stack.
203			 */
204			usbd_xfer_set_stall(xfer);
205			usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
206			usbd_transfer_submit(xfer);
207		}
208		break;
209	}
210}
211
212/*------------------------------------------------------------------------*
213 *	uhub_explore_sub - subroutine
214 *
215 * Return values:
216 *    0: Success
217 * Else: A control transaction failed
218 *------------------------------------------------------------------------*/
219static usb_error_t
220uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up)
221{
222	struct usb_bus *bus;
223	struct usb_device *child;
224	uint8_t refcount;
225	usb_error_t err;
226
227	bus = sc->sc_udev->bus;
228	err = 0;
229
230	/* get driver added refcount from USB bus */
231	refcount = bus->driver_added_refcount;
232
233	/* get device assosiated with the given port */
234	child = usb_bus_port_get_device(bus, up);
235	if (child == NULL) {
236		/* nothing to do */
237		goto done;
238	}
239	/* check if device should be re-enumerated */
240
241	if (child->flags.usb_mode == USB_MODE_HOST) {
242		usbd_enum_lock(child);
243		if (child->re_enumerate_wait) {
244			err = usbd_set_config_index(child, USB_UNCONFIG_INDEX);
245			if (err == 0)
246				err = usbd_req_re_enumerate(child, NULL);
247			if (err == 0)
248				err = usbd_set_config_index(child, 0);
249			if (err == 0) {
250				err = usb_probe_and_attach(child,
251				    USB_IFACE_INDEX_ANY);
252			}
253			child->re_enumerate_wait = 0;
254			err = 0;
255		}
256		usbd_enum_unlock(child);
257	}
258
259	/* check if probe and attach should be done */
260
261	if (child->driver_added_refcount != refcount) {
262		child->driver_added_refcount = refcount;
263		err = usb_probe_and_attach(child,
264		    USB_IFACE_INDEX_ANY);
265		if (err) {
266			goto done;
267		}
268	}
269	/* start control transfer, if device mode */
270
271	if (child->flags.usb_mode == USB_MODE_DEVICE) {
272		usbd_ctrl_transfer_setup(child);
273	}
274	/* if a HUB becomes present, do a recursive HUB explore */
275
276	if (child->hub) {
277		err = (child->hub->explore) (child);
278	}
279done:
280	return (err);
281}
282
283/*------------------------------------------------------------------------*
284 *	uhub_read_port_status - factored out code
285 *------------------------------------------------------------------------*/
286static usb_error_t
287uhub_read_port_status(struct uhub_softc *sc, uint8_t portno)
288{
289	struct usb_port_status ps;
290	usb_error_t err;
291
292	err = usbd_req_get_port_status(
293	    sc->sc_udev, NULL, &ps, portno);
294
295	/* update status regardless of error */
296
297	sc->sc_st.port_status = UGETW(ps.wPortStatus);
298	sc->sc_st.port_change = UGETW(ps.wPortChange);
299
300	/* debugging print */
301
302	DPRINTFN(4, "port %d, wPortStatus=0x%04x, "
303	    "wPortChange=0x%04x, err=%s\n",
304	    portno, sc->sc_st.port_status,
305	    sc->sc_st.port_change, usbd_errstr(err));
306	return (err);
307}
308
309/*------------------------------------------------------------------------*
310 *	uhub_reattach_port
311 *
312 * Returns:
313 *    0: Success
314 * Else: A control transaction failed
315 *------------------------------------------------------------------------*/
316static usb_error_t
317uhub_reattach_port(struct uhub_softc *sc, uint8_t portno)
318{
319	struct usb_device *child;
320	struct usb_device *udev;
321	enum usb_dev_speed speed;
322	enum usb_hc_mode mode;
323	usb_error_t err;
324	uint8_t timeout;
325
326	DPRINTF("reattaching port %d\n", portno);
327
328	err = 0;
329	timeout = 0;
330	udev = sc->sc_udev;
331	child = usb_bus_port_get_device(udev->bus,
332	    udev->hub->ports + portno - 1);
333
334repeat:
335
336	/* first clear the port connection change bit */
337
338	err = usbd_req_clear_port_feature(udev, NULL,
339	    portno, UHF_C_PORT_CONNECTION);
340
341	if (err) {
342		goto error;
343	}
344	/* check if there is a child */
345
346	if (child != NULL) {
347		/*
348		 * Free USB device and all subdevices, if any.
349		 */
350		usb_free_device(child, 0);
351		child = NULL;
352	}
353	/* get fresh status */
354
355	err = uhub_read_port_status(sc, portno);
356	if (err) {
357		goto error;
358	}
359	/* check if nothing is connected to the port */
360
361	if (!(sc->sc_st.port_status & UPS_CURRENT_CONNECT_STATUS)) {
362		goto error;
363	}
364	/* check if there is no power on the port and print a warning */
365
366	if (!(sc->sc_st.port_status & UPS_PORT_POWER)) {
367		DPRINTF("WARNING: strange, connected port %d "
368		    "has no power\n", portno);
369	}
370	/* check if the device is in Host Mode */
371
372	if (!(sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)) {
373
374		DPRINTF("Port %d is in Host Mode\n", portno);
375
376		if (sc->sc_st.port_status & UPS_SUSPEND) {
377			DPRINTF("Port %d was still "
378			    "suspended, clearing.\n", portno);
379			err = usbd_req_clear_port_feature(sc->sc_udev,
380			    NULL, portno, UHF_PORT_SUSPEND);
381		}
382		/* USB Host Mode */
383
384		/* wait for maximum device power up time */
385
386		usb_pause_mtx(NULL,
387		    USB_MS_TO_TICKS(USB_PORT_POWERUP_DELAY));
388
389		/* reset port, which implies enabling it */
390
391		err = usbd_req_reset_port(udev, NULL, portno);
392
393		if (err) {
394			DPRINTFN(0, "port %d reset "
395			    "failed, error=%s\n",
396			    portno, usbd_errstr(err));
397			goto error;
398		}
399		/* get port status again, it might have changed during reset */
400
401		err = uhub_read_port_status(sc, portno);
402		if (err) {
403			goto error;
404		}
405		/* check if something changed during port reset */
406
407		if ((sc->sc_st.port_change & UPS_C_CONNECT_STATUS) ||
408		    (!(sc->sc_st.port_status & UPS_CURRENT_CONNECT_STATUS))) {
409			if (timeout) {
410				DPRINTFN(0, "giving up port reset "
411				    "- device vanished\n");
412				goto error;
413			}
414			timeout = 1;
415			goto repeat;
416		}
417	} else {
418		DPRINTF("Port %d is in Device Mode\n", portno);
419	}
420
421	/*
422	 * Figure out the device speed
423	 */
424	switch (udev->speed) {
425	case USB_SPEED_HIGH:
426		if (sc->sc_st.port_status & UPS_HIGH_SPEED)
427			speed = USB_SPEED_HIGH;
428		else if (sc->sc_st.port_status & UPS_LOW_SPEED)
429			speed = USB_SPEED_LOW;
430		else
431			speed = USB_SPEED_FULL;
432		break;
433	case USB_SPEED_FULL:
434		if (sc->sc_st.port_status & UPS_LOW_SPEED)
435			speed = USB_SPEED_LOW;
436		else
437			speed = USB_SPEED_FULL;
438		break;
439	case USB_SPEED_LOW:
440		speed = USB_SPEED_LOW;
441		break;
442	default:
443		/* same speed like parent */
444		speed = udev->speed;
445		break;
446	}
447	/*
448	 * Figure out the device mode
449	 *
450	 * NOTE: This part is currently FreeBSD specific.
451	 */
452	if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
453		mode = USB_MODE_DEVICE;
454	else
455		mode = USB_MODE_HOST;
456
457	/* need to create a new child */
458	child = usb_alloc_device(sc->sc_dev, udev->bus, udev,
459	    udev->depth + 1, portno - 1, portno, speed, mode);
460	if (child == NULL) {
461		DPRINTFN(0, "could not allocate new device\n");
462		goto error;
463	}
464	return (0);			/* success */
465
466error:
467	if (child != NULL) {
468		/*
469		 * Free USB device and all subdevices, if any.
470		 */
471		usb_free_device(child, 0);
472		child = NULL;
473	}
474	if (err == 0) {
475		if (sc->sc_st.port_status & UPS_PORT_ENABLED) {
476			err = usbd_req_clear_port_feature(
477			    sc->sc_udev, NULL,
478			    portno, UHF_PORT_ENABLE);
479		}
480	}
481	if (err) {
482		DPRINTFN(0, "device problem (%s), "
483		    "disabling port %d\n", usbd_errstr(err), portno);
484	}
485	return (err);
486}
487
488/*------------------------------------------------------------------------*
489 *	uhub_suspend_resume_port
490 *
491 * Returns:
492 *    0: Success
493 * Else: A control transaction failed
494 *------------------------------------------------------------------------*/
495static usb_error_t
496uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno)
497{
498	struct usb_device *child;
499	struct usb_device *udev;
500	uint8_t is_suspend;
501	usb_error_t err;
502
503	DPRINTF("port %d\n", portno);
504
505	udev = sc->sc_udev;
506	child = usb_bus_port_get_device(udev->bus,
507	    udev->hub->ports + portno - 1);
508
509	/* first clear the port suspend change bit */
510
511	err = usbd_req_clear_port_feature(udev, NULL,
512	    portno, UHF_C_PORT_SUSPEND);
513	if (err) {
514		DPRINTF("clearing suspend failed.\n");
515		goto done;
516	}
517	/* get fresh status */
518
519	err = uhub_read_port_status(sc, portno);
520	if (err) {
521		DPRINTF("reading port status failed.\n");
522		goto done;
523	}
524	/* get current state */
525
526	if (sc->sc_st.port_status & UPS_SUSPEND) {
527		is_suspend = 1;
528	} else {
529		is_suspend = 0;
530	}
531
532	DPRINTF("suspended=%u\n", is_suspend);
533
534	/* do the suspend or resume */
535
536	if (child) {
537		/*
538		 * This code handle two cases: 1) Host Mode - we can only
539		 * receive resume here 2) Device Mode - we can receive
540		 * suspend and resume here
541		 */
542		if (is_suspend == 0)
543			usb_dev_resume_peer(child);
544		else if (child->flags.usb_mode == USB_MODE_DEVICE)
545			usb_dev_suspend_peer(child);
546	}
547done:
548	return (err);
549}
550
551/*------------------------------------------------------------------------*
552 *	uhub_root_interrupt
553 *
554 * This function is called when a Root HUB interrupt has
555 * happened. "ptr" and "len" makes up the Root HUB interrupt
556 * packet. This function is called having the "bus_mtx" locked.
557 *------------------------------------------------------------------------*/
558void
559uhub_root_intr(struct usb_bus *bus, const uint8_t *ptr, uint8_t len)
560{
561	USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
562
563	usb_needs_explore(bus, 0);
564}
565
566/*------------------------------------------------------------------------*
567 *	uhub_explore
568 *
569 * Returns:
570 *     0: Success
571 *  Else: Failure
572 *------------------------------------------------------------------------*/
573static usb_error_t
574uhub_explore(struct usb_device *udev)
575{
576	struct usb_hub *hub;
577	struct uhub_softc *sc;
578	struct usb_port *up;
579	usb_error_t err;
580	uint8_t portno;
581	uint8_t x;
582
583	hub = udev->hub;
584	sc = hub->hubsoftc;
585
586	DPRINTFN(11, "udev=%p addr=%d\n", udev, udev->address);
587
588	/* ignore hubs that are too deep */
589	if (udev->depth > USB_HUB_MAX_DEPTH) {
590		return (USB_ERR_TOO_DEEP);
591	}
592
593	if (udev->flags.self_suspended) {
594		/* need to wait until the child signals resume */
595		DPRINTF("Device is suspended!\n");
596		return (0);
597	}
598	for (x = 0; x != hub->nports; x++) {
599		up = hub->ports + x;
600		portno = x + 1;
601
602		err = uhub_read_port_status(sc, portno);
603		if (err) {
604			/* most likely the HUB is gone */
605			break;
606		}
607		if (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) {
608			DPRINTF("Overcurrent on port %u.\n", portno);
609			err = usbd_req_clear_port_feature(
610			    udev, NULL, portno, UHF_C_PORT_OVER_CURRENT);
611			if (err) {
612				/* most likely the HUB is gone */
613				break;
614			}
615		}
616		if (!(sc->sc_flags & UHUB_FLAG_DID_EXPLORE)) {
617			/*
618			 * Fake a connect status change so that the
619			 * status gets checked initially!
620			 */
621			sc->sc_st.port_change |=
622			    UPS_C_CONNECT_STATUS;
623		}
624		if (sc->sc_st.port_change & UPS_C_PORT_ENABLED) {
625			err = usbd_req_clear_port_feature(
626			    udev, NULL, portno, UHF_C_PORT_ENABLE);
627			if (err) {
628				/* most likely the HUB is gone */
629				break;
630			}
631			if (sc->sc_st.port_change & UPS_C_CONNECT_STATUS) {
632				/*
633				 * Ignore the port error if the device
634				 * has vanished !
635				 */
636			} else if (sc->sc_st.port_status & UPS_PORT_ENABLED) {
637				DPRINTFN(0, "illegal enable change, "
638				    "port %d\n", portno);
639			} else {
640
641				if (up->restartcnt == USB_RESTART_MAX) {
642					/* XXX could try another speed ? */
643					DPRINTFN(0, "port error, giving up "
644					    "port %d\n", portno);
645				} else {
646					sc->sc_st.port_change |=
647					    UPS_C_CONNECT_STATUS;
648					up->restartcnt++;
649				}
650			}
651		}
652		if (sc->sc_st.port_change & UPS_C_CONNECT_STATUS) {
653			err = uhub_reattach_port(sc, portno);
654			if (err) {
655				/* most likely the HUB is gone */
656				break;
657			}
658		}
659		if (sc->sc_st.port_change & UPS_C_SUSPEND) {
660			err = uhub_suspend_resume_port(sc, portno);
661			if (err) {
662				/* most likely the HUB is gone */
663				break;
664			}
665		}
666		err = uhub_explore_sub(sc, up);
667		if (err) {
668			/* no device(s) present */
669			continue;
670		}
671		/* explore succeeded - reset restart counter */
672		up->restartcnt = 0;
673	}
674
675	/* initial status checked */
676	sc->sc_flags |= UHUB_FLAG_DID_EXPLORE;
677
678	/* return success */
679	return (USB_ERR_NORMAL_COMPLETION);
680}
681
682static int
683uhub_probe(device_t dev)
684{
685	struct usb_attach_arg *uaa = device_get_ivars(dev);
686
687	if (uaa->usb_mode != USB_MODE_HOST) {
688		return (ENXIO);
689	}
690	/*
691	 * The subclass for USB HUBs is ignored because it is 0 for
692	 * some and 1 for others.
693	 */
694	if ((uaa->info.bConfigIndex == 0) &&
695	    (uaa->info.bDeviceClass == UDCLASS_HUB)) {
696		return (0);
697	}
698	return (ENXIO);
699}
700
701static int
702uhub_attach(device_t dev)
703{
704	struct uhub_softc *sc = device_get_softc(dev);
705	struct usb_attach_arg *uaa = device_get_ivars(dev);
706	struct usb_device *udev = uaa->device;
707	struct usb_device *parent_hub = udev->parent_hub;
708	struct usb_hub *hub;
709	struct usb_hub_descriptor hubdesc;
710	uint16_t pwrdly;
711	uint8_t x;
712	uint8_t nports;
713	uint8_t portno;
714	uint8_t removable;
715	uint8_t iface_index;
716	usb_error_t err;
717
718	sc->sc_udev = udev;
719	sc->sc_dev = dev;
720
721	mtx_init(&sc->sc_mtx, "USB HUB mutex", NULL, MTX_DEF);
722
723	snprintf(sc->sc_name, sizeof(sc->sc_name), "%s",
724	    device_get_nameunit(dev));
725
726	device_set_usb_desc(dev);
727
728	DPRINTFN(2, "depth=%d selfpowered=%d, parent=%p, "
729	    "parent->selfpowered=%d\n",
730	    udev->depth,
731	    udev->flags.self_powered,
732	    parent_hub,
733	    parent_hub ?
734	    parent_hub->flags.self_powered : 0);
735
736	if (udev->depth > USB_HUB_MAX_DEPTH) {
737		DPRINTFN(0, "hub depth, %d, exceeded. HUB ignored\n",
738		    USB_HUB_MAX_DEPTH);
739		goto error;
740	}
741	if (!udev->flags.self_powered && parent_hub &&
742	    (!parent_hub->flags.self_powered)) {
743		DPRINTFN(0, "bus powered HUB connected to "
744		    "bus powered HUB. HUB ignored\n");
745		goto error;
746	}
747	/* get HUB descriptor */
748
749	DPRINTFN(2, "getting HUB descriptor\n");
750
751	/* assuming that there is one port */
752	err = usbd_req_get_hub_descriptor(udev, NULL, &hubdesc, 1);
753
754	nports = hubdesc.bNbrPorts;
755
756	if (!err && (nports >= 8)) {
757		/* get complete HUB descriptor */
758		err = usbd_req_get_hub_descriptor(udev, NULL, &hubdesc, nports);
759	}
760	if (err) {
761		DPRINTFN(0, "getting hub descriptor failed,"
762		    "error=%s\n", usbd_errstr(err));
763		goto error;
764	}
765	if (hubdesc.bNbrPorts != nports) {
766		DPRINTFN(0, "number of ports changed\n");
767		goto error;
768	}
769	if (nports == 0) {
770		DPRINTFN(0, "portless HUB\n");
771		goto error;
772	}
773	hub = malloc(sizeof(hub[0]) + (sizeof(hub->ports[0]) * nports),
774	    M_USBDEV, M_WAITOK | M_ZERO);
775
776	if (hub == NULL) {
777		goto error;
778	}
779	udev->hub = hub;
780
781#if USB_HAVE_TT_SUPPORT
782	/* init FULL-speed ISOCHRONOUS schedule */
783	usbd_fs_isoc_schedule_init_all(hub->fs_isoc_schedule);
784#endif
785	/* initialize HUB structure */
786	hub->hubsoftc = sc;
787	hub->explore = &uhub_explore;
788	hub->nports = hubdesc.bNbrPorts;
789	hub->hubudev = udev;
790
791	/* if self powered hub, give ports maximum current */
792	if (udev->flags.self_powered) {
793		hub->portpower = USB_MAX_POWER;
794	} else {
795		hub->portpower = USB_MIN_POWER;
796	}
797
798	/* set up interrupt pipe */
799	iface_index = 0;
800	if (udev->parent_hub == NULL) {
801		/* root HUB is special */
802		err = 0;
803	} else {
804		/* normal HUB */
805		err = usbd_transfer_setup(udev, &iface_index, sc->sc_xfer,
806		    uhub_config, UHUB_N_TRANSFER, sc, &sc->sc_mtx);
807	}
808	if (err) {
809		DPRINTFN(0, "cannot setup interrupt transfer, "
810		    "errstr=%s\n", usbd_errstr(err));
811		goto error;
812	}
813	/* wait with power off for a while */
814	usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_POWER_DOWN_TIME));
815
816	/*
817	 * To have the best chance of success we do things in the exact same
818	 * order as Windoze98.  This should not be necessary, but some
819	 * devices do not follow the USB specs to the letter.
820	 *
821	 * These are the events on the bus when a hub is attached:
822	 *  Get device and config descriptors (see attach code)
823	 *  Get hub descriptor (see above)
824	 *  For all ports
825	 *     turn on power
826	 *     wait for power to become stable
827	 * (all below happens in explore code)
828	 *  For all ports
829	 *     clear C_PORT_CONNECTION
830	 *  For all ports
831	 *     get port status
832	 *     if device connected
833	 *        wait 100 ms
834	 *        turn on reset
835	 *        wait
836	 *        clear C_PORT_RESET
837	 *        get port status
838	 *        proceed with device attachment
839	 */
840
841	/* XXX should check for none, individual, or ganged power? */
842
843	removable = 0;
844	pwrdly = ((hubdesc.bPwrOn2PwrGood * UHD_PWRON_FACTOR) +
845	    USB_EXTRA_POWER_UP_TIME);
846
847	for (x = 0; x != nports; x++) {
848		/* set up data structures */
849		struct usb_port *up = hub->ports + x;
850
851		up->device_index = 0;
852		up->restartcnt = 0;
853		portno = x + 1;
854
855		/* check if port is removable */
856		if (!UHD_NOT_REMOV(&hubdesc, portno)) {
857			removable++;
858		}
859		if (!err) {
860			/* turn the power on */
861			err = usbd_req_set_port_feature(udev, NULL,
862			    portno, UHF_PORT_POWER);
863		}
864		if (err) {
865			DPRINTFN(0, "port %d power on failed, %s\n",
866			    portno, usbd_errstr(err));
867		}
868		DPRINTF("turn on port %d power\n",
869		    portno);
870
871		/* wait for stable power */
872		usb_pause_mtx(NULL, USB_MS_TO_TICKS(pwrdly));
873	}
874
875	device_printf(dev, "%d port%s with %d "
876	    "removable, %s powered\n", nports, (nports != 1) ? "s" : "",
877	    removable, udev->flags.self_powered ? "self" : "bus");
878
879	/* Start the interrupt endpoint, if any */
880
881	if (sc->sc_xfer[0] != NULL) {
882		mtx_lock(&sc->sc_mtx);
883		usbd_transfer_start(sc->sc_xfer[0]);
884		mtx_unlock(&sc->sc_mtx);
885	}
886
887	/* Enable automatic power save on all USB HUBs */
888
889	usbd_set_power_mode(udev, USB_POWER_MODE_SAVE);
890
891	return (0);
892
893error:
894	usbd_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
895
896	if (udev->hub) {
897		free(udev->hub, M_USBDEV);
898		udev->hub = NULL;
899	}
900
901	mtx_destroy(&sc->sc_mtx);
902
903	return (ENXIO);
904}
905
906/*
907 * Called from process context when the hub is gone.
908 * Detach all devices on active ports.
909 */
910static int
911uhub_detach(device_t dev)
912{
913	struct uhub_softc *sc = device_get_softc(dev);
914	struct usb_hub *hub = sc->sc_udev->hub;
915	struct usb_device *child;
916	uint8_t x;
917
918	if (hub == NULL) {		/* must be partially working */
919		return (0);
920	}
921
922	/* Make sure interrupt transfer is gone. */
923	usbd_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
924
925	/* Detach all ports */
926	for (x = 0; x != hub->nports; x++) {
927
928		child = usb_bus_port_get_device(sc->sc_udev->bus, hub->ports + x);
929
930		if (child == NULL) {
931			continue;
932		}
933
934		/*
935		 * Free USB device and all subdevices, if any.
936		 */
937		usb_free_device(child, 0);
938	}
939
940	free(hub, M_USBDEV);
941	sc->sc_udev->hub = NULL;
942
943	mtx_destroy(&sc->sc_mtx);
944
945	return (0);
946}
947
948static int
949uhub_suspend(device_t dev)
950{
951	DPRINTF("\n");
952	/* Sub-devices are not suspended here! */
953	return (0);
954}
955
956static int
957uhub_resume(device_t dev)
958{
959	DPRINTF("\n");
960	/* Sub-devices are not resumed here! */
961	return (0);
962}
963
964static void
965uhub_driver_added(device_t dev, driver_t *driver)
966{
967	usb_needs_explore_all();
968}
969
970struct hub_result {
971	struct usb_device *udev;
972	uint8_t	portno;
973	uint8_t	iface_index;
974};
975
976static void
977uhub_find_iface_index(struct usb_hub *hub, device_t child,
978    struct hub_result *res)
979{
980	struct usb_interface *iface;
981	struct usb_device *udev;
982	uint8_t nports;
983	uint8_t x;
984	uint8_t i;
985
986	nports = hub->nports;
987	for (x = 0; x != nports; x++) {
988		udev = usb_bus_port_get_device(hub->hubudev->bus,
989		    hub->ports + x);
990		if (!udev) {
991			continue;
992		}
993		for (i = 0; i != USB_IFACE_MAX; i++) {
994			iface = usbd_get_iface(udev, i);
995			if (iface &&
996			    (iface->subdev == child)) {
997				res->iface_index = i;
998				res->udev = udev;
999				res->portno = x + 1;
1000				return;
1001			}
1002		}
1003	}
1004	res->iface_index = 0;
1005	res->udev = NULL;
1006	res->portno = 0;
1007}
1008
1009static int
1010uhub_child_location_string(device_t parent, device_t child,
1011    char *buf, size_t buflen)
1012{
1013	struct uhub_softc *sc;
1014	struct usb_hub *hub;
1015	struct hub_result res;
1016
1017	if (!device_is_attached(parent)) {
1018		if (buflen)
1019			buf[0] = 0;
1020		return (0);
1021	}
1022
1023	sc = device_get_softc(parent);
1024	hub = sc->sc_udev->hub;
1025
1026	mtx_lock(&Giant);
1027	uhub_find_iface_index(hub, child, &res);
1028	if (!res.udev) {
1029		DPRINTF("device not on hub\n");
1030		if (buflen) {
1031			buf[0] = '\0';
1032		}
1033		goto done;
1034	}
1035	snprintf(buf, buflen, "bus=%u hubaddr=%u port=%u devaddr=%u interface=%u",
1036	    (res.udev->parent_hub != NULL) ? res.udev->parent_hub->device_index : 0,
1037	    res.portno, device_get_unit(res.udev->bus->bdev),
1038	    res.udev->device_index, res.iface_index);
1039done:
1040	mtx_unlock(&Giant);
1041
1042	return (0);
1043}
1044
1045static int
1046uhub_child_pnpinfo_string(device_t parent, device_t child,
1047    char *buf, size_t buflen)
1048{
1049	struct uhub_softc *sc;
1050	struct usb_hub *hub;
1051	struct usb_interface *iface;
1052	struct hub_result res;
1053
1054	if (!device_is_attached(parent)) {
1055		if (buflen)
1056			buf[0] = 0;
1057		return (0);
1058	}
1059
1060	sc = device_get_softc(parent);
1061	hub = sc->sc_udev->hub;
1062
1063	mtx_lock(&Giant);
1064	uhub_find_iface_index(hub, child, &res);
1065	if (!res.udev) {
1066		DPRINTF("device not on hub\n");
1067		if (buflen) {
1068			buf[0] = '\0';
1069		}
1070		goto done;
1071	}
1072	iface = usbd_get_iface(res.udev, res.iface_index);
1073	if (iface && iface->idesc) {
1074		snprintf(buf, buflen, "vendor=0x%04x product=0x%04x "
1075		    "devclass=0x%02x devsubclass=0x%02x "
1076		    "sernum=\"%s\" "
1077		    "release=0x%04x "
1078		    "intclass=0x%02x intsubclass=0x%02x",
1079		    UGETW(res.udev->ddesc.idVendor),
1080		    UGETW(res.udev->ddesc.idProduct),
1081		    res.udev->ddesc.bDeviceClass,
1082		    res.udev->ddesc.bDeviceSubClass,
1083		    usb_get_serial(res.udev),
1084		    UGETW(res.udev->ddesc.bcdDevice),
1085		    iface->idesc->bInterfaceClass,
1086		    iface->idesc->bInterfaceSubClass);
1087	} else {
1088		if (buflen) {
1089			buf[0] = '\0';
1090		}
1091		goto done;
1092	}
1093done:
1094	mtx_unlock(&Giant);
1095
1096	return (0);
1097}
1098
1099/*
1100 * The USB Transaction Translator:
1101 * ===============================
1102 *
1103 * When doing LOW- and FULL-speed USB transfers accross a HIGH-speed
1104 * USB HUB, bandwidth must be allocated for ISOCHRONOUS and INTERRUPT
1105 * USB transfers. To utilize bandwidth dynamically the "scatter and
1106 * gather" principle must be applied. This means that bandwidth must
1107 * be divided into equal parts of bandwidth. With regard to USB all
1108 * data is transferred in smaller packets with length
1109 * "wMaxPacketSize". The problem however is that "wMaxPacketSize" is
1110 * not a constant!
1111 *
1112 * The bandwidth scheduler which I have implemented will simply pack
1113 * the USB transfers back to back until there is no more space in the
1114 * schedule. Out of the 8 microframes which the USB 2.0 standard
1115 * provides, only 6 are available for non-HIGH-speed devices. I have
1116 * reserved the first 4 microframes for ISOCHRONOUS transfers. The
1117 * last 2 microframes I have reserved for INTERRUPT transfers. Without
1118 * this division, it is very difficult to allocate and free bandwidth
1119 * dynamically.
1120 *
1121 * NOTE about the Transaction Translator in USB HUBs:
1122 *
1123 * USB HUBs have a very simple Transaction Translator, that will
1124 * simply pipeline all the SPLIT transactions. That means that the
1125 * transactions will be executed in the order they are queued!
1126 *
1127 */
1128
1129/*------------------------------------------------------------------------*
1130 *	usb_intr_find_best_slot
1131 *
1132 * Return value:
1133 *   The best Transaction Translation slot for an interrupt endpoint.
1134 *------------------------------------------------------------------------*/
1135static uint8_t
1136usb_intr_find_best_slot(usb_size_t *ptr, uint8_t start,
1137    uint8_t end, uint8_t mask)
1138{
1139	usb_size_t min = 0 - 1;
1140	usb_size_t sum;
1141	uint8_t x;
1142	uint8_t y;
1143	uint8_t z;
1144
1145	y = 0;
1146
1147	/* find the last slot with lesser used bandwidth */
1148
1149	for (x = start; x < end; x++) {
1150
1151		sum = 0;
1152
1153		/* compute sum of bandwidth */
1154		for (z = x; z < end; z++) {
1155			if (mask & (1U << (z - x)))
1156				sum += ptr[z];
1157		}
1158
1159		/* check if the current multi-slot is more optimal */
1160		if (min >= sum) {
1161			min = sum;
1162			y = x;
1163		}
1164
1165		/* check if the mask is about to be shifted out */
1166		if (mask & (1U << (end - 1 - x)))
1167			break;
1168	}
1169	return (y);
1170}
1171
1172/*------------------------------------------------------------------------*
1173 *	usb_hs_bandwidth_adjust
1174 *
1175 * This function will update the bandwith usage for the microframe
1176 * having index "slot" by "len" bytes. "len" can be negative.  If the
1177 * "slot" argument is greater or equal to "USB_HS_MICRO_FRAMES_MAX"
1178 * the "slot" argument will be replaced by the slot having least used
1179 * bandwidth. The "mask" argument is used for multi-slot allocations.
1180 *
1181 * Returns:
1182 *    The slot in which the bandwidth update was done: 0..7
1183 *------------------------------------------------------------------------*/
1184static uint8_t
1185usb_hs_bandwidth_adjust(struct usb_device *udev, int16_t len,
1186    uint8_t slot, uint8_t mask)
1187{
1188	struct usb_bus *bus = udev->bus;
1189	struct usb_hub *hub;
1190	enum usb_dev_speed speed;
1191	uint8_t x;
1192
1193	USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
1194
1195	speed = usbd_get_speed(udev);
1196
1197	switch (speed) {
1198	case USB_SPEED_LOW:
1199	case USB_SPEED_FULL:
1200		if (speed == USB_SPEED_LOW) {
1201			len *= 8;
1202		}
1203		/*
1204	         * The Host Controller Driver should have
1205	         * performed checks so that the lookup
1206	         * below does not result in a NULL pointer
1207	         * access.
1208	         */
1209
1210		hub = udev->parent_hs_hub->hub;
1211		if (slot >= USB_HS_MICRO_FRAMES_MAX) {
1212			slot = usb_intr_find_best_slot(hub->uframe_usage,
1213			    USB_FS_ISOC_UFRAME_MAX, 6, mask);
1214		}
1215		for (x = slot; x < 8; x++) {
1216			if (mask & (1U << (x - slot))) {
1217				hub->uframe_usage[x] += len;
1218				bus->uframe_usage[x] += len;
1219			}
1220		}
1221		break;
1222	default:
1223		if (slot >= USB_HS_MICRO_FRAMES_MAX) {
1224			slot = usb_intr_find_best_slot(bus->uframe_usage, 0,
1225			    USB_HS_MICRO_FRAMES_MAX, mask);
1226		}
1227		for (x = slot; x < 8; x++) {
1228			if (mask & (1U << (x - slot))) {
1229				bus->uframe_usage[x] += len;
1230			}
1231		}
1232		break;
1233	}
1234	return (slot);
1235}
1236
1237/*------------------------------------------------------------------------*
1238 *	usb_hs_bandwidth_alloc
1239 *
1240 * This function is a wrapper function for "usb_hs_bandwidth_adjust()".
1241 *------------------------------------------------------------------------*/
1242void
1243usb_hs_bandwidth_alloc(struct usb_xfer *xfer)
1244{
1245	struct usb_device *udev;
1246	uint8_t slot;
1247	uint8_t mask;
1248	uint8_t speed;
1249
1250	udev = xfer->xroot->udev;
1251
1252	if (udev->flags.usb_mode != USB_MODE_HOST)
1253		return;		/* not supported */
1254
1255	xfer->endpoint->refcount_bw++;
1256	if (xfer->endpoint->refcount_bw != 1)
1257		return;		/* already allocated */
1258
1259	speed = usbd_get_speed(udev);
1260
1261	switch (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
1262	case UE_INTERRUPT:
1263		/* allocate a microframe slot */
1264
1265		mask = 0x01;
1266		slot = usb_hs_bandwidth_adjust(udev,
1267		    xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX, mask);
1268
1269		xfer->endpoint->usb_uframe = slot;
1270		xfer->endpoint->usb_smask = mask << slot;
1271
1272		if ((speed != USB_SPEED_FULL) &&
1273		    (speed != USB_SPEED_LOW)) {
1274			xfer->endpoint->usb_cmask = 0x00 ;
1275		} else {
1276			xfer->endpoint->usb_cmask = (-(0x04 << slot)) & 0xFE;
1277		}
1278		break;
1279
1280	case UE_ISOCHRONOUS:
1281		switch (usbd_xfer_get_fps_shift(xfer)) {
1282		case 0:
1283			mask = 0xFF;
1284			break;
1285		case 1:
1286			mask = 0x55;
1287			break;
1288		case 2:
1289			mask = 0x11;
1290			break;
1291		default:
1292			mask = 0x01;
1293			break;
1294		}
1295
1296		/* allocate a microframe multi-slot */
1297
1298		slot = usb_hs_bandwidth_adjust(udev,
1299		    xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX, mask);
1300
1301		xfer->endpoint->usb_uframe = slot;
1302		xfer->endpoint->usb_cmask = 0;
1303		xfer->endpoint->usb_smask = mask << slot;
1304		break;
1305
1306	default:
1307		xfer->endpoint->usb_uframe = 0;
1308		xfer->endpoint->usb_cmask = 0;
1309		xfer->endpoint->usb_smask = 0;
1310		break;
1311	}
1312
1313	DPRINTFN(11, "slot=%d, mask=0x%02x\n",
1314	    xfer->endpoint->usb_uframe,
1315	    xfer->endpoint->usb_smask >> xfer->endpoint->usb_uframe);
1316}
1317
1318/*------------------------------------------------------------------------*
1319 *	usb_hs_bandwidth_free
1320 *
1321 * This function is a wrapper function for "usb_hs_bandwidth_adjust()".
1322 *------------------------------------------------------------------------*/
1323void
1324usb_hs_bandwidth_free(struct usb_xfer *xfer)
1325{
1326	struct usb_device *udev;
1327	uint8_t slot;
1328	uint8_t mask;
1329
1330	udev = xfer->xroot->udev;
1331
1332	if (udev->flags.usb_mode != USB_MODE_HOST)
1333		return;		/* not supported */
1334
1335	xfer->endpoint->refcount_bw--;
1336	if (xfer->endpoint->refcount_bw != 0)
1337		return;		/* still allocated */
1338
1339	switch (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
1340	case UE_INTERRUPT:
1341	case UE_ISOCHRONOUS:
1342
1343		slot = xfer->endpoint->usb_uframe;
1344		mask = xfer->endpoint->usb_smask;
1345
1346		/* free microframe slot(s): */
1347		usb_hs_bandwidth_adjust(udev,
1348		    -xfer->max_frame_size, slot, mask >> slot);
1349
1350		DPRINTFN(11, "slot=%d, mask=0x%02x\n",
1351		    slot, mask >> slot);
1352
1353		xfer->endpoint->usb_uframe = 0;
1354		xfer->endpoint->usb_cmask = 0;
1355		xfer->endpoint->usb_smask = 0;
1356		break;
1357
1358	default:
1359		break;
1360	}
1361}
1362
1363/*------------------------------------------------------------------------*
1364 *	usbd_fs_isoc_schedule_init_sub
1365 *
1366 * This function initialises an USB FULL speed isochronous schedule
1367 * entry.
1368 *------------------------------------------------------------------------*/
1369#if USB_HAVE_TT_SUPPORT
1370static void
1371usbd_fs_isoc_schedule_init_sub(struct usb_fs_isoc_schedule *fss)
1372{
1373	fss->total_bytes = (USB_FS_ISOC_UFRAME_MAX *
1374	    USB_FS_BYTES_PER_HS_UFRAME);
1375	fss->frame_bytes = (USB_FS_BYTES_PER_HS_UFRAME);
1376	fss->frame_slot = 0;
1377}
1378#endif
1379
1380/*------------------------------------------------------------------------*
1381 *	usbd_fs_isoc_schedule_init_all
1382 *
1383 * This function will reset the complete USB FULL speed isochronous
1384 * bandwidth schedule.
1385 *------------------------------------------------------------------------*/
1386#if USB_HAVE_TT_SUPPORT
1387void
1388usbd_fs_isoc_schedule_init_all(struct usb_fs_isoc_schedule *fss)
1389{
1390	struct usb_fs_isoc_schedule *fss_end = fss + USB_ISOC_TIME_MAX;
1391
1392	while (fss != fss_end) {
1393		usbd_fs_isoc_schedule_init_sub(fss);
1394		fss++;
1395	}
1396}
1397#endif
1398
1399/*------------------------------------------------------------------------*
1400 *	usb_isoc_time_expand
1401 *
1402 * This function will expand the time counter from 7-bit to 16-bit.
1403 *
1404 * Returns:
1405 *   16-bit isochronous time counter.
1406 *------------------------------------------------------------------------*/
1407uint16_t
1408usb_isoc_time_expand(struct usb_bus *bus, uint16_t isoc_time_curr)
1409{
1410	uint16_t rem;
1411
1412	USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
1413
1414	rem = bus->isoc_time_last & (USB_ISOC_TIME_MAX - 1);
1415
1416	isoc_time_curr &= (USB_ISOC_TIME_MAX - 1);
1417
1418	if (isoc_time_curr < rem) {
1419		/* the time counter wrapped around */
1420		bus->isoc_time_last += USB_ISOC_TIME_MAX;
1421	}
1422	/* update the remainder */
1423
1424	bus->isoc_time_last &= ~(USB_ISOC_TIME_MAX - 1);
1425	bus->isoc_time_last |= isoc_time_curr;
1426
1427	return (bus->isoc_time_last);
1428}
1429
1430/*------------------------------------------------------------------------*
1431 *	usbd_fs_isoc_schedule_isoc_time_expand
1432 *
1433 * This function does multiple things. First of all it will expand the
1434 * passed isochronous time, which is the return value. Then it will
1435 * store where the current FULL speed isochronous schedule is
1436 * positioned in time and where the end is. See "pp_start" and
1437 * "pp_end" arguments.
1438 *
1439 * Returns:
1440 *   Expanded version of "isoc_time".
1441 *
1442 * NOTE: This function depends on being called regularly with
1443 * intervals less than "USB_ISOC_TIME_MAX".
1444 *------------------------------------------------------------------------*/
1445#if USB_HAVE_TT_SUPPORT
1446uint16_t
1447usbd_fs_isoc_schedule_isoc_time_expand(struct usb_device *udev,
1448    struct usb_fs_isoc_schedule **pp_start,
1449    struct usb_fs_isoc_schedule **pp_end,
1450    uint16_t isoc_time)
1451{
1452	struct usb_fs_isoc_schedule *fss_end;
1453	struct usb_fs_isoc_schedule *fss_a;
1454	struct usb_fs_isoc_schedule *fss_b;
1455	struct usb_hub *hs_hub;
1456
1457	isoc_time = usb_isoc_time_expand(udev->bus, isoc_time);
1458
1459	hs_hub = udev->parent_hs_hub->hub;
1460
1461	if (hs_hub != NULL) {
1462
1463		fss_a = hs_hub->fs_isoc_schedule +
1464		    (hs_hub->isoc_last_time % USB_ISOC_TIME_MAX);
1465
1466		hs_hub->isoc_last_time = isoc_time;
1467
1468		fss_b = hs_hub->fs_isoc_schedule +
1469		    (isoc_time % USB_ISOC_TIME_MAX);
1470
1471		fss_end = hs_hub->fs_isoc_schedule + USB_ISOC_TIME_MAX;
1472
1473		*pp_start = hs_hub->fs_isoc_schedule;
1474		*pp_end = fss_end;
1475
1476		while (fss_a != fss_b) {
1477			if (fss_a == fss_end) {
1478				fss_a = hs_hub->fs_isoc_schedule;
1479				continue;
1480			}
1481			usbd_fs_isoc_schedule_init_sub(fss_a);
1482			fss_a++;
1483		}
1484
1485	} else {
1486
1487		*pp_start = NULL;
1488		*pp_end = NULL;
1489	}
1490	return (isoc_time);
1491}
1492#endif
1493
1494/*------------------------------------------------------------------------*
1495 *	usbd_fs_isoc_schedule_alloc
1496 *
1497 * This function will allocate bandwidth for an isochronous FULL speed
1498 * transaction in the FULL speed schedule. The microframe slot where
1499 * the transaction should be started is stored in the byte pointed to
1500 * by "pstart". The "len" argument specifies the length of the
1501 * transaction in bytes.
1502 *
1503 * Returns:
1504 *    0: Success
1505 * Else: Error
1506 *------------------------------------------------------------------------*/
1507#if USB_HAVE_TT_SUPPORT
1508uint8_t
1509usbd_fs_isoc_schedule_alloc(struct usb_fs_isoc_schedule *fss,
1510    uint8_t *pstart, uint16_t len)
1511{
1512	uint8_t slot = fss->frame_slot;
1513
1514	/* Compute overhead and bit-stuffing */
1515
1516	len += 8;
1517
1518	len *= 7;
1519	len /= 6;
1520
1521	if (len > fss->total_bytes) {
1522		*pstart = 0;		/* set some dummy value */
1523		return (1);		/* error */
1524	}
1525	if (len > 0) {
1526
1527		fss->total_bytes -= len;
1528
1529		while (len >= fss->frame_bytes) {
1530			len -= fss->frame_bytes;
1531			fss->frame_bytes = USB_FS_BYTES_PER_HS_UFRAME;
1532			fss->frame_slot++;
1533		}
1534
1535		fss->frame_bytes -= len;
1536	}
1537	*pstart = slot;
1538	return (0);			/* success */
1539}
1540#endif
1541
1542/*------------------------------------------------------------------------*
1543 *	usb_bus_port_get_device
1544 *
1545 * This function is NULL safe.
1546 *------------------------------------------------------------------------*/
1547struct usb_device *
1548usb_bus_port_get_device(struct usb_bus *bus, struct usb_port *up)
1549{
1550	if ((bus == NULL) || (up == NULL)) {
1551		/* be NULL safe */
1552		return (NULL);
1553	}
1554	if (up->device_index == 0) {
1555		/* nothing to do */
1556		return (NULL);
1557	}
1558	return (bus->devices[up->device_index]);
1559}
1560
1561/*------------------------------------------------------------------------*
1562 *	usb_bus_port_set_device
1563 *
1564 * This function is NULL safe.
1565 *------------------------------------------------------------------------*/
1566void
1567usb_bus_port_set_device(struct usb_bus *bus, struct usb_port *up,
1568    struct usb_device *udev, uint8_t device_index)
1569{
1570	if (bus == NULL) {
1571		/* be NULL safe */
1572		return;
1573	}
1574	/*
1575	 * There is only one case where we don't
1576	 * have an USB port, and that is the Root Hub!
1577         */
1578	if (up) {
1579		if (udev) {
1580			up->device_index = device_index;
1581		} else {
1582			device_index = up->device_index;
1583			up->device_index = 0;
1584		}
1585	}
1586	/*
1587	 * Make relationships to our new device
1588	 */
1589	if (device_index != 0) {
1590#if USB_HAVE_UGEN
1591		mtx_lock(&usb_ref_lock);
1592#endif
1593		bus->devices[device_index] = udev;
1594#if USB_HAVE_UGEN
1595		mtx_unlock(&usb_ref_lock);
1596#endif
1597	}
1598	/*
1599	 * Debug print
1600	 */
1601	DPRINTFN(2, "bus %p devices[%u] = %p\n", bus, device_index, udev);
1602}
1603
1604/*------------------------------------------------------------------------*
1605 *	usb_needs_explore
1606 *
1607 * This functions is called when the USB event thread needs to run.
1608 *------------------------------------------------------------------------*/
1609void
1610usb_needs_explore(struct usb_bus *bus, uint8_t do_probe)
1611{
1612	uint8_t do_unlock;
1613
1614	DPRINTF("\n");
1615
1616	if (bus == NULL) {
1617		DPRINTF("No bus pointer!\n");
1618		return;
1619	}
1620	if ((bus->devices == NULL) ||
1621	    (bus->devices[USB_ROOT_HUB_ADDR] == NULL)) {
1622		DPRINTF("No root HUB\n");
1623		return;
1624	}
1625	if (mtx_owned(&bus->bus_mtx)) {
1626		do_unlock = 0;
1627	} else {
1628		USB_BUS_LOCK(bus);
1629		do_unlock = 1;
1630	}
1631	if (do_probe) {
1632		bus->do_probe = 1;
1633	}
1634	if (usb_proc_msignal(&bus->explore_proc,
1635	    &bus->explore_msg[0], &bus->explore_msg[1])) {
1636		/* ignore */
1637	}
1638	if (do_unlock) {
1639		USB_BUS_UNLOCK(bus);
1640	}
1641}
1642
1643/*------------------------------------------------------------------------*
1644 *	usb_needs_explore_all
1645 *
1646 * This function is called whenever a new driver is loaded and will
1647 * cause that all USB busses are re-explored.
1648 *------------------------------------------------------------------------*/
1649void
1650usb_needs_explore_all(void)
1651{
1652	struct usb_bus *bus;
1653	devclass_t dc;
1654	device_t dev;
1655	int max;
1656
1657	DPRINTFN(3, "\n");
1658
1659	dc = usb_devclass_ptr;
1660	if (dc == NULL) {
1661		DPRINTFN(0, "no devclass\n");
1662		return;
1663	}
1664	/*
1665	 * Explore all USB busses in parallell.
1666	 */
1667	max = devclass_get_maxunit(dc);
1668	while (max >= 0) {
1669		dev = devclass_get_device(dc, max);
1670		if (dev) {
1671			bus = device_get_softc(dev);
1672			if (bus) {
1673				usb_needs_explore(bus, 1);
1674			}
1675		}
1676		max--;
1677	}
1678}
1679
1680/*------------------------------------------------------------------------*
1681 *	usb_bus_power_update
1682 *
1683 * This function will ensure that all USB devices on the given bus are
1684 * properly suspended or resumed according to the device transfer
1685 * state.
1686 *------------------------------------------------------------------------*/
1687#if USB_HAVE_POWERD
1688void
1689usb_bus_power_update(struct usb_bus *bus)
1690{
1691	usb_needs_explore(bus, 0 /* no probe */ );
1692}
1693#endif
1694
1695/*------------------------------------------------------------------------*
1696 *	usbd_transfer_power_ref
1697 *
1698 * This function will modify the power save reference counts and
1699 * wakeup the USB device associated with the given USB transfer, if
1700 * needed.
1701 *------------------------------------------------------------------------*/
1702#if USB_HAVE_POWERD
1703void
1704usbd_transfer_power_ref(struct usb_xfer *xfer, int val)
1705{
1706	static const usb_power_mask_t power_mask[4] = {
1707		[UE_CONTROL] = USB_HW_POWER_CONTROL,
1708		[UE_BULK] = USB_HW_POWER_BULK,
1709		[UE_INTERRUPT] = USB_HW_POWER_INTERRUPT,
1710		[UE_ISOCHRONOUS] = USB_HW_POWER_ISOC,
1711	};
1712	struct usb_device *udev;
1713	uint8_t needs_explore;
1714	uint8_t needs_hw_power;
1715	uint8_t xfer_type;
1716
1717	udev = xfer->xroot->udev;
1718
1719	if (udev->device_index == USB_ROOT_HUB_ADDR) {
1720		/* no power save for root HUB */
1721		return;
1722	}
1723	USB_BUS_LOCK(udev->bus);
1724
1725	xfer_type = xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE;
1726
1727	udev->pwr_save.last_xfer_time = ticks;
1728	udev->pwr_save.type_refs[xfer_type] += val;
1729
1730	if (xfer->flags_int.control_xfr) {
1731		udev->pwr_save.read_refs += val;
1732		if (xfer->flags_int.usb_mode == USB_MODE_HOST) {
1733			/*
1734			 * It is not allowed to suspend during a
1735			 * control transfer:
1736			 */
1737			udev->pwr_save.write_refs += val;
1738		}
1739	} else if (USB_GET_DATA_ISREAD(xfer)) {
1740		udev->pwr_save.read_refs += val;
1741	} else {
1742		udev->pwr_save.write_refs += val;
1743	}
1744
1745	if (val > 0) {
1746		if (udev->flags.self_suspended)
1747			needs_explore = usb_peer_should_wakeup(udev);
1748		else
1749			needs_explore = 0;
1750
1751		if (!(udev->bus->hw_power_state & power_mask[xfer_type])) {
1752			DPRINTF("Adding type %u to power state\n", xfer_type);
1753			udev->bus->hw_power_state |= power_mask[xfer_type];
1754			needs_hw_power = 1;
1755		} else {
1756			needs_hw_power = 0;
1757		}
1758	} else {
1759		needs_explore = 0;
1760		needs_hw_power = 0;
1761	}
1762
1763	USB_BUS_UNLOCK(udev->bus);
1764
1765	if (needs_explore) {
1766		DPRINTF("update\n");
1767		usb_bus_power_update(udev->bus);
1768	} else if (needs_hw_power) {
1769		DPRINTF("needs power\n");
1770		if (udev->bus->methods->set_hw_power != NULL) {
1771			(udev->bus->methods->set_hw_power) (udev->bus);
1772		}
1773	}
1774}
1775#endif
1776
1777/*------------------------------------------------------------------------*
1778 *	usb_peer_should_wakeup
1779 *
1780 * This function returns non-zero if the current device should wake up.
1781 *------------------------------------------------------------------------*/
1782static uint8_t
1783usb_peer_should_wakeup(struct usb_device *udev)
1784{
1785	return ((udev->power_mode == USB_POWER_MODE_ON) ||
1786	    (udev->driver_added_refcount != udev->bus->driver_added_refcount) ||
1787	    (udev->re_enumerate_wait != 0) ||
1788	    (udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0) ||
1789	    (udev->pwr_save.write_refs != 0) ||
1790	    ((udev->pwr_save.read_refs != 0) &&
1791	    (udev->flags.usb_mode == USB_MODE_HOST) &&
1792	    (usb_peer_can_wakeup(udev) == 0)));
1793}
1794
1795/*------------------------------------------------------------------------*
1796 *	usb_bus_powerd
1797 *
1798 * This function implements the USB power daemon and is called
1799 * regularly from the USB explore thread.
1800 *------------------------------------------------------------------------*/
1801#if USB_HAVE_POWERD
1802void
1803usb_bus_powerd(struct usb_bus *bus)
1804{
1805	struct usb_device *udev;
1806	usb_ticks_t temp;
1807	usb_ticks_t limit;
1808	usb_ticks_t mintime;
1809	usb_size_t type_refs[5];
1810	uint8_t x;
1811
1812	limit = usb_power_timeout;
1813	if (limit == 0)
1814		limit = hz;
1815	else if (limit > 255)
1816		limit = 255 * hz;
1817	else
1818		limit = limit * hz;
1819
1820	DPRINTF("bus=%p\n", bus);
1821
1822	USB_BUS_LOCK(bus);
1823
1824	/*
1825	 * The root HUB device is never suspended
1826	 * and we simply skip it.
1827	 */
1828	for (x = USB_ROOT_HUB_ADDR + 1;
1829	    x != bus->devices_max; x++) {
1830
1831		udev = bus->devices[x];
1832		if (udev == NULL)
1833			continue;
1834
1835		temp = ticks - udev->pwr_save.last_xfer_time;
1836
1837		if (usb_peer_should_wakeup(udev)) {
1838			/* check if we are suspended */
1839			if (udev->flags.self_suspended != 0) {
1840				USB_BUS_UNLOCK(bus);
1841				usb_dev_resume_peer(udev);
1842				USB_BUS_LOCK(bus);
1843			}
1844		} else if ((temp >= limit) &&
1845		    (udev->flags.usb_mode == USB_MODE_HOST) &&
1846		    (udev->flags.self_suspended == 0)) {
1847			/* try to do suspend */
1848
1849			USB_BUS_UNLOCK(bus);
1850			usb_dev_suspend_peer(udev);
1851			USB_BUS_LOCK(bus);
1852		}
1853	}
1854
1855	/* reset counters */
1856
1857	mintime = 0 - 1;
1858	type_refs[0] = 0;
1859	type_refs[1] = 0;
1860	type_refs[2] = 0;
1861	type_refs[3] = 0;
1862	type_refs[4] = 0;
1863
1864	/* Re-loop all the devices to get the actual state */
1865
1866	for (x = USB_ROOT_HUB_ADDR + 1;
1867	    x != bus->devices_max; x++) {
1868
1869		udev = bus->devices[x];
1870		if (udev == NULL)
1871			continue;
1872
1873		/* we found a non-Root-Hub USB device */
1874		type_refs[4] += 1;
1875
1876		/* "last_xfer_time" can be updated by a resume */
1877		temp = ticks - udev->pwr_save.last_xfer_time;
1878
1879		/*
1880		 * Compute minimum time since last transfer for the complete
1881		 * bus:
1882		 */
1883		if (temp < mintime)
1884			mintime = temp;
1885
1886		if (udev->flags.self_suspended == 0) {
1887			type_refs[0] += udev->pwr_save.type_refs[0];
1888			type_refs[1] += udev->pwr_save.type_refs[1];
1889			type_refs[2] += udev->pwr_save.type_refs[2];
1890			type_refs[3] += udev->pwr_save.type_refs[3];
1891		}
1892	}
1893
1894	if (mintime >= (1 * hz)) {
1895		/* recompute power masks */
1896		DPRINTF("Recomputing power masks\n");
1897		bus->hw_power_state = 0;
1898		if (type_refs[UE_CONTROL] != 0)
1899			bus->hw_power_state |= USB_HW_POWER_CONTROL;
1900		if (type_refs[UE_BULK] != 0)
1901			bus->hw_power_state |= USB_HW_POWER_BULK;
1902		if (type_refs[UE_INTERRUPT] != 0)
1903			bus->hw_power_state |= USB_HW_POWER_INTERRUPT;
1904		if (type_refs[UE_ISOCHRONOUS] != 0)
1905			bus->hw_power_state |= USB_HW_POWER_ISOC;
1906		if (type_refs[4] != 0)
1907			bus->hw_power_state |= USB_HW_POWER_NON_ROOT_HUB;
1908	}
1909	USB_BUS_UNLOCK(bus);
1910
1911	if (bus->methods->set_hw_power != NULL) {
1912		/* always update hardware power! */
1913		(bus->methods->set_hw_power) (bus);
1914	}
1915	return;
1916}
1917#endif
1918
1919/*------------------------------------------------------------------------*
1920 *	usb_dev_resume_peer
1921 *
1922 * This function will resume an USB peer and do the required USB
1923 * signalling to get an USB device out of the suspended state.
1924 *------------------------------------------------------------------------*/
1925static void
1926usb_dev_resume_peer(struct usb_device *udev)
1927{
1928	struct usb_bus *bus;
1929	int err;
1930
1931	/* be NULL safe */
1932	if (udev == NULL)
1933		return;
1934
1935	/* check if already resumed */
1936	if (udev->flags.self_suspended == 0)
1937		return;
1938
1939	/* we need a parent HUB to do resume */
1940	if (udev->parent_hub == NULL)
1941		return;
1942
1943	DPRINTF("udev=%p\n", udev);
1944
1945	if ((udev->flags.usb_mode == USB_MODE_DEVICE) &&
1946	    (udev->flags.remote_wakeup == 0)) {
1947		/*
1948		 * If the host did not set the remote wakeup feature, we can
1949		 * not wake it up either!
1950		 */
1951		DPRINTF("remote wakeup is not set!\n");
1952		return;
1953	}
1954	/* get bus pointer */
1955	bus = udev->bus;
1956
1957	/* resume parent hub first */
1958	usb_dev_resume_peer(udev->parent_hub);
1959
1960	/* reduce chance of instant resume failure by waiting a little bit */
1961	usb_pause_mtx(NULL, USB_MS_TO_TICKS(20));
1962
1963	/* resume current port (Valid in Host and Device Mode) */
1964	err = usbd_req_clear_port_feature(udev->parent_hub,
1965	    NULL, udev->port_no, UHF_PORT_SUSPEND);
1966	if (err) {
1967		DPRINTFN(0, "Resuming port failed\n");
1968		return;
1969	}
1970	/* resume settle time */
1971	usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY));
1972
1973	if (bus->methods->device_resume != NULL) {
1974		/* resume USB device on the USB controller */
1975		(bus->methods->device_resume) (udev);
1976	}
1977	USB_BUS_LOCK(bus);
1978	/* set that this device is now resumed */
1979	udev->flags.self_suspended = 0;
1980#if USB_HAVE_POWERD
1981	/* make sure that we don't go into suspend right away */
1982	udev->pwr_save.last_xfer_time = ticks;
1983
1984	/* make sure the needed power masks are on */
1985	if (udev->pwr_save.type_refs[UE_CONTROL] != 0)
1986		bus->hw_power_state |= USB_HW_POWER_CONTROL;
1987	if (udev->pwr_save.type_refs[UE_BULK] != 0)
1988		bus->hw_power_state |= USB_HW_POWER_BULK;
1989	if (udev->pwr_save.type_refs[UE_INTERRUPT] != 0)
1990		bus->hw_power_state |= USB_HW_POWER_INTERRUPT;
1991	if (udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0)
1992		bus->hw_power_state |= USB_HW_POWER_ISOC;
1993#endif
1994	USB_BUS_UNLOCK(bus);
1995
1996	if (bus->methods->set_hw_power != NULL) {
1997		/* always update hardware power! */
1998		(bus->methods->set_hw_power) (bus);
1999	}
2000
2001	usbd_sr_lock(udev);
2002
2003	/* notify all sub-devices about resume */
2004	err = usb_suspend_resume(udev, 0);
2005
2006	usbd_sr_unlock(udev);
2007
2008	/* check if peer has wakeup capability */
2009	if (usb_peer_can_wakeup(udev)) {
2010		/* clear remote wakeup */
2011		err = usbd_req_clear_device_feature(udev,
2012		    NULL, UF_DEVICE_REMOTE_WAKEUP);
2013		if (err) {
2014			DPRINTFN(0, "Clearing device "
2015			    "remote wakeup failed: %s\n",
2016			    usbd_errstr(err));
2017		}
2018	}
2019	return;
2020}
2021
2022/*------------------------------------------------------------------------*
2023 *	usb_dev_suspend_peer
2024 *
2025 * This function will suspend an USB peer and do the required USB
2026 * signalling to get an USB device into the suspended state.
2027 *------------------------------------------------------------------------*/
2028static void
2029usb_dev_suspend_peer(struct usb_device *udev)
2030{
2031	struct usb_device *child;
2032	int err;
2033	uint8_t x;
2034	uint8_t nports;
2035
2036repeat:
2037	/* be NULL safe */
2038	if (udev == NULL)
2039		return;
2040
2041	/* check if already suspended */
2042	if (udev->flags.self_suspended)
2043		return;
2044
2045	/* we need a parent HUB to do suspend */
2046	if (udev->parent_hub == NULL)
2047		return;
2048
2049	DPRINTF("udev=%p\n", udev);
2050
2051	/* check if the current device is a HUB */
2052	if (udev->hub != NULL) {
2053		nports = udev->hub->nports;
2054
2055		/* check if all devices on the HUB are suspended */
2056		for (x = 0; x != nports; x++) {
2057
2058			child = usb_bus_port_get_device(udev->bus,
2059			    udev->hub->ports + x);
2060
2061			if (child == NULL)
2062				continue;
2063
2064			if (child->flags.self_suspended)
2065				continue;
2066
2067			DPRINTFN(1, "Port %u is busy on the HUB!\n", x + 1);
2068			return;
2069		}
2070	}
2071
2072	USB_BUS_LOCK(udev->bus);
2073	/*
2074	 * Checking for suspend condition and setting suspended bit
2075	 * must be atomic!
2076	 */
2077	err = usb_peer_should_wakeup(udev);
2078	if (err == 0) {
2079		/*
2080		 * Set that this device is suspended. This variable
2081		 * must be set before calling USB controller suspend
2082		 * callbacks.
2083		 */
2084		udev->flags.self_suspended = 1;
2085	}
2086	USB_BUS_UNLOCK(udev->bus);
2087
2088	if (err != 0) {
2089		if (udev->flags.usb_mode == USB_MODE_DEVICE) {
2090			/* resume parent HUB first */
2091			usb_dev_resume_peer(udev->parent_hub);
2092
2093			/* reduce chance of instant resume failure by waiting a little bit */
2094			usb_pause_mtx(NULL, USB_MS_TO_TICKS(20));
2095
2096			/* resume current port (Valid in Host and Device Mode) */
2097			err = usbd_req_clear_port_feature(udev->parent_hub,
2098			    NULL, udev->port_no, UHF_PORT_SUSPEND);
2099
2100			/* resume settle time */
2101			usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY));
2102		}
2103		DPRINTF("Suspend was cancelled!\n");
2104		return;
2105	}
2106
2107	usbd_sr_lock(udev);
2108
2109	/* notify all sub-devices about suspend */
2110	err = usb_suspend_resume(udev, 1);
2111
2112	usbd_sr_unlock(udev);
2113
2114	if (usb_peer_can_wakeup(udev)) {
2115		/* allow device to do remote wakeup */
2116		err = usbd_req_set_device_feature(udev,
2117		    NULL, UF_DEVICE_REMOTE_WAKEUP);
2118		if (err) {
2119			DPRINTFN(0, "Setting device "
2120			    "remote wakeup failed\n");
2121		}
2122	}
2123
2124	if (udev->bus->methods->device_suspend != NULL) {
2125		usb_timeout_t temp;
2126
2127		/* suspend device on the USB controller */
2128		(udev->bus->methods->device_suspend) (udev);
2129
2130		/* do DMA delay */
2131		temp = usbd_get_dma_delay(udev);
2132		if (temp != 0)
2133			usb_pause_mtx(NULL, USB_MS_TO_TICKS(temp));
2134
2135	}
2136	/* suspend current port */
2137	err = usbd_req_set_port_feature(udev->parent_hub,
2138	    NULL, udev->port_no, UHF_PORT_SUSPEND);
2139	if (err) {
2140		DPRINTFN(0, "Suspending port failed\n");
2141		return;
2142	}
2143
2144	udev = udev->parent_hub;
2145	goto repeat;
2146}
2147
2148/*------------------------------------------------------------------------*
2149 *	usbd_set_power_mode
2150 *
2151 * This function will set the power mode, see USB_POWER_MODE_XXX for a
2152 * USB device.
2153 *------------------------------------------------------------------------*/
2154void
2155usbd_set_power_mode(struct usb_device *udev, uint8_t power_mode)
2156{
2157	/* filter input argument */
2158	if ((power_mode != USB_POWER_MODE_ON) &&
2159	    (power_mode != USB_POWER_MODE_OFF))
2160		power_mode = USB_POWER_MODE_SAVE;
2161
2162	power_mode = usbd_filter_power_mode(udev, power_mode);
2163
2164	udev->power_mode = power_mode;	/* update copy of power mode */
2165
2166#if USB_HAVE_POWERD
2167	usb_bus_power_update(udev->bus);
2168#endif
2169}
2170
2171/*------------------------------------------------------------------------*
2172 *	usbd_filter_power_mode
2173 *
2174 * This function filters the power mode based on hardware requirements.
2175 *------------------------------------------------------------------------*/
2176uint8_t
2177usbd_filter_power_mode(struct usb_device *udev, uint8_t power_mode)
2178{
2179	struct usb_bus_methods *mtod;
2180	int8_t temp;
2181
2182	mtod = udev->bus->methods;
2183	temp = -1;
2184
2185	if (mtod->get_power_mode != NULL)
2186		(mtod->get_power_mode) (udev, &temp);
2187
2188	/* check if we should not filter */
2189	if (temp < 0)
2190		return (power_mode);
2191
2192	/* use fixed power mode given by hardware driver */
2193	return (temp);
2194}
2195