Home | History | Annotate | Line # | Download | only in usb
usb.c revision 1.53.2.10
      1  1.53.2.10   thorpej /*	$NetBSD: usb.c,v 1.53.2.10 2003/01/03 17:08:21 thorpej Exp $	*/
      2        1.1  augustss 
      3        1.1  augustss /*
      4   1.53.2.3   nathanw  * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
      5        1.1  augustss  * All rights reserved.
      6        1.1  augustss  *
      7        1.5  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8       1.44  augustss  * by Lennart Augustsson (lennart (at) augustsson.net) at
      9        1.5  augustss  * Carlstedt Research & Technology.
     10        1.1  augustss  *
     11        1.1  augustss  * Redistribution and use in source and binary forms, with or without
     12        1.1  augustss  * modification, are permitted provided that the following conditions
     13        1.1  augustss  * are met:
     14        1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     15        1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     16        1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     17        1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     18        1.1  augustss  *    documentation and/or other materials provided with the distribution.
     19        1.1  augustss  * 3. All advertising materials mentioning features or use of this software
     20        1.1  augustss  *    must display the following acknowledgement:
     21        1.1  augustss  *        This product includes software developed by the NetBSD
     22        1.1  augustss  *        Foundation, Inc. and its contributors.
     23        1.1  augustss  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24        1.1  augustss  *    contributors may be used to endorse or promote products derived
     25        1.1  augustss  *    from this software without specific prior written permission.
     26        1.1  augustss  *
     27        1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28        1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29        1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30        1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31        1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32        1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33        1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34        1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35        1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36        1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37        1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     38        1.1  augustss  */
     39        1.1  augustss 
     40        1.1  augustss /*
     41        1.8  augustss  * USB specifications and other documentation can be found at
     42        1.8  augustss  * http://www.usb.org/developers/data/ and
     43        1.8  augustss  * http://www.usb.org/developers/index.html .
     44        1.1  augustss  */
     45        1.1  augustss 
     46   1.53.2.1   nathanw #include <sys/cdefs.h>
     47  1.53.2.10   thorpej __KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.53.2.10 2003/01/03 17:08:21 thorpej Exp $");
     48  1.53.2.10   thorpej 
     49  1.53.2.10   thorpej #include "ohci.h"
     50  1.53.2.10   thorpej #include "uhci.h"
     51   1.53.2.1   nathanw 
     52        1.1  augustss #include <sys/param.h>
     53        1.1  augustss #include <sys/systm.h>
     54        1.1  augustss #include <sys/kernel.h>
     55        1.1  augustss #include <sys/malloc.h>
     56        1.1  augustss #include <sys/device.h>
     57       1.13  augustss #include <sys/kthread.h>
     58       1.30  augustss #include <sys/proc.h>
     59       1.22  augustss #include <sys/conf.h>
     60   1.53.2.5   nathanw #include <sys/fcntl.h>
     61        1.1  augustss #include <sys/poll.h>
     62        1.1  augustss #include <sys/select.h>
     63       1.26  augustss #include <sys/vnode.h>
     64       1.26  augustss #include <sys/signalvar.h>
     65        1.1  augustss 
     66        1.1  augustss #include <dev/usb/usb.h>
     67       1.13  augustss #include <dev/usb/usbdi.h>
     68       1.13  augustss #include <dev/usb/usbdi_util.h>
     69        1.1  augustss 
     70       1.26  augustss #define USB_DEV_MINOR 255
     71       1.26  augustss 
     72       1.20  augustss #include <machine/bus.h>
     73        1.7  augustss 
     74        1.1  augustss #include <dev/usb/usbdivar.h>
     75        1.1  augustss #include <dev/usb/usb_quirks.h>
     76        1.1  augustss 
     77        1.1  augustss #ifdef USB_DEBUG
     78       1.16  augustss #define DPRINTF(x)	if (usbdebug) logprintf x
     79       1.16  augustss #define DPRINTFN(n,x)	if (usbdebug>(n)) logprintf x
     80        1.1  augustss int	usbdebug = 0;
     81  1.53.2.10   thorpej #if defined(UHCI_DEBUG) && NUHCI > 0
     82  1.53.2.10   thorpej extern int	uhcidebug;
     83       1.30  augustss #endif
     84  1.53.2.10   thorpej #if defined(OHCI_DEBUG) && NOHCI > 0
     85  1.53.2.10   thorpej extern int	ohcidebug;
     86       1.30  augustss #endif
     87   1.53.2.4   nathanw /*
     88       1.34  augustss  * 0  - do usual exploration
     89       1.34  augustss  * 1  - do not use timeout exploration
     90       1.34  augustss  * >1 - do no exploration
     91       1.34  augustss  */
     92       1.21  augustss int	usb_noexplore = 0;
     93        1.1  augustss #else
     94        1.1  augustss #define DPRINTF(x)
     95        1.1  augustss #define DPRINTFN(n,x)
     96        1.1  augustss #endif
     97        1.1  augustss 
     98        1.1  augustss struct usb_softc {
     99       1.22  augustss 	USBBASEDEVICE	sc_dev;		/* base device */
    100        1.1  augustss 	usbd_bus_handle sc_bus;		/* USB controller */
    101        1.1  augustss 	struct usbd_port sc_port;	/* dummy port for root hub */
    102       1.25  augustss 
    103   1.53.2.3   nathanw 	struct proc	*sc_event_thread;
    104       1.25  augustss 
    105       1.25  augustss 	char		sc_dying;
    106        1.1  augustss };
    107        1.1  augustss 
    108   1.53.2.2   nathanw TAILQ_HEAD(, usb_task) usb_all_tasks;
    109   1.53.2.2   nathanw 
    110   1.53.2.6   nathanw dev_type_open(usbopen);
    111   1.53.2.6   nathanw dev_type_close(usbclose);
    112   1.53.2.6   nathanw dev_type_read(usbread);
    113   1.53.2.6   nathanw dev_type_ioctl(usbioctl);
    114   1.53.2.6   nathanw dev_type_poll(usbpoll);
    115   1.53.2.8   nathanw dev_type_kqfilter(usbkqfilter);
    116   1.53.2.6   nathanw 
    117   1.53.2.6   nathanw const struct cdevsw usb_cdevsw = {
    118   1.53.2.6   nathanw 	usbopen, usbclose, usbread, nowrite, usbioctl,
    119   1.53.2.8   nathanw 	nostop, notty, usbpoll, nommap, usbkqfilter,
    120   1.53.2.6   nathanw };
    121        1.7  augustss 
    122       1.51  augustss Static void	usb_discover(void *);
    123       1.45  augustss Static void	usb_create_event_thread(void *);
    124       1.45  augustss Static void	usb_event_thread(void *);
    125   1.53.2.2   nathanw Static void	usb_task_thread(void *);
    126   1.53.2.2   nathanw Static struct proc *usb_task_thread_proc = NULL;
    127        1.1  augustss 
    128       1.41  augustss #define USB_MAX_EVENTS 100
    129       1.26  augustss struct usb_event_q {
    130       1.26  augustss 	struct usb_event ue;
    131       1.26  augustss 	SIMPLEQ_ENTRY(usb_event_q) next;
    132       1.26  augustss };
    133   1.53.2.4   nathanw Static SIMPLEQ_HEAD(, usb_event_q) usb_events =
    134       1.29  augustss 	SIMPLEQ_HEAD_INITIALIZER(usb_events);
    135       1.42  augustss Static int usb_nevents = 0;
    136       1.42  augustss Static struct selinfo usb_selevent;
    137   1.53.2.2   nathanw Static usb_proc_ptr usb_async_proc;  /* process that wants USB SIGIO */
    138       1.42  augustss Static int usb_dev_open = 0;
    139       1.45  augustss Static void usb_add_event(int, struct usb_event *);
    140       1.26  augustss 
    141       1.45  augustss Static int usb_get_next_event(struct usb_event *);
    142       1.23  augustss 
    143       1.42  augustss Static const char *usbrev_str[] = USBREV_STR;
    144       1.31  augustss 
    145       1.28  augustss USB_DECLARE_DRIVER(usb);
    146        1.1  augustss 
    147        1.7  augustss USB_MATCH(usb)
    148        1.1  augustss {
    149        1.1  augustss 	DPRINTF(("usbd_match\n"));
    150        1.7  augustss 	return (UMATCH_GENERIC);
    151        1.1  augustss }
    152        1.1  augustss 
    153        1.7  augustss USB_ATTACH(usb)
    154        1.1  augustss {
    155        1.1  augustss 	struct usb_softc *sc = (struct usb_softc *)self;
    156        1.1  augustss 	usbd_device_handle dev;
    157       1.29  augustss 	usbd_status err;
    158       1.31  augustss 	int usbrev;
    159   1.53.2.2   nathanw 	int speed;
    160       1.38  augustss 	struct usb_event ue;
    161   1.53.2.4   nathanw 
    162        1.1  augustss 	DPRINTF(("usbd_attach\n"));
    163       1.31  augustss 
    164        1.4  augustss 	usbd_init();
    165        1.1  augustss 	sc->sc_bus = aux;
    166        1.1  augustss 	sc->sc_bus->usbctl = sc;
    167        1.1  augustss 	sc->sc_port.power = USB_MAX_POWER;
    168       1.31  augustss 
    169       1.31  augustss 	usbrev = sc->sc_bus->usbrev;
    170       1.32  augustss 	printf(": USB revision %s", usbrev_str[usbrev]);
    171   1.53.2.2   nathanw 	switch (usbrev) {
    172   1.53.2.2   nathanw 	case USBREV_1_0:
    173   1.53.2.2   nathanw 	case USBREV_1_1:
    174   1.53.2.2   nathanw 		speed = USB_SPEED_FULL;
    175   1.53.2.2   nathanw 		break;
    176   1.53.2.2   nathanw 	case USBREV_2_0:
    177   1.53.2.2   nathanw 		speed = USB_SPEED_HIGH;
    178   1.53.2.2   nathanw 		break;
    179   1.53.2.2   nathanw 	default:
    180       1.31  augustss 		printf(", not supported\n");
    181   1.53.2.2   nathanw 		sc->sc_dying = 1;
    182       1.31  augustss 		USB_ATTACH_ERROR_RETURN;
    183       1.32  augustss 	}
    184       1.32  augustss 	printf("\n");
    185       1.31  augustss 
    186       1.35  augustss 	/* Make sure not to use tsleep() if we are cold booting. */
    187       1.35  augustss 	if (cold)
    188       1.35  augustss 		sc->sc_bus->use_polling++;
    189       1.35  augustss 
    190       1.38  augustss 	ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
    191       1.38  augustss 	usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue);
    192       1.38  augustss 
    193       1.49  augustss #ifdef USB_USE_SOFTINTR
    194       1.49  augustss #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
    195       1.49  augustss 	/* XXX we should have our own level */
    196   1.53.2.4   nathanw 	sc->sc_bus->soft = softintr_establish(IPL_SOFTNET,
    197       1.49  augustss 	    sc->sc_bus->methods->soft_intr, sc->sc_bus);
    198       1.49  augustss 	if (sc->sc_bus->soft == NULL) {
    199       1.49  augustss 		printf("%s: can't register softintr\n", USBDEVNAME(sc->sc_dev));
    200       1.49  augustss 		sc->sc_dying = 1;
    201   1.53.2.2   nathanw 		USB_ATTACH_ERROR_RETURN;
    202       1.49  augustss 	}
    203       1.49  augustss #else
    204   1.53.2.5   nathanw 	usb_callout_init(sc->sc_bus->softi);
    205       1.49  augustss #endif
    206       1.49  augustss #endif
    207       1.49  augustss 
    208   1.53.2.2   nathanw 	err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, speed, 0,
    209       1.29  augustss 		  &sc->sc_port);
    210       1.29  augustss 	if (!err) {
    211        1.1  augustss 		dev = sc->sc_port.device;
    212       1.29  augustss 		if (dev->hub == NULL) {
    213       1.22  augustss 			sc->sc_dying = 1;
    214   1.53.2.4   nathanw 			printf("%s: root device is not a hub\n",
    215        1.7  augustss 			       USBDEVNAME(sc->sc_dev));
    216        1.7  augustss 			USB_ATTACH_ERROR_RETURN;
    217        1.1  augustss 		}
    218        1.1  augustss 		sc->sc_bus->root_hub = dev;
    219       1.24  augustss #if 1
    220   1.53.2.4   nathanw 		/*
    221       1.24  augustss 		 * Turning this code off will delay attachment of USB devices
    222       1.24  augustss 		 * until the USB event thread is running, which means that
    223       1.24  augustss 		 * the keyboard will not work until after cold boot.
    224       1.24  augustss 		 */
    225       1.36  augustss 		if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1))
    226       1.24  augustss 			dev->hub->explore(sc->sc_bus->root_hub);
    227       1.24  augustss #endif
    228        1.1  augustss 	} else {
    229   1.53.2.4   nathanw 		printf("%s: root hub problem, error=%d\n",
    230   1.53.2.4   nathanw 		       USBDEVNAME(sc->sc_dev), err);
    231       1.22  augustss 		sc->sc_dying = 1;
    232        1.1  augustss 	}
    233       1.35  augustss 	if (cold)
    234       1.35  augustss 		sc->sc_bus->use_polling--;
    235        1.7  augustss 
    236       1.37   thorpej 	config_pending_incr();
    237       1.43  augustss 	usb_kthread_create(usb_create_event_thread, sc);
    238       1.28  augustss 
    239        1.7  augustss 	USB_ATTACH_SUCCESS_RETURN;
    240        1.1  augustss }
    241        1.1  augustss 
    242       1.28  augustss #if defined(__NetBSD__) || defined(__OpenBSD__)
    243       1.13  augustss void
    244       1.45  augustss usb_create_event_thread(void *arg)
    245       1.13  augustss {
    246       1.13  augustss 	struct usb_softc *sc = arg;
    247   1.53.2.2   nathanw 	static int created = 0;
    248       1.13  augustss 
    249       1.43  augustss 	if (usb_kthread_create1(usb_event_thread, sc, &sc->sc_event_thread,
    250       1.13  augustss 			   "%s", sc->sc_dev.dv_xname)) {
    251       1.13  augustss 		printf("%s: unable to create event thread for\n",
    252       1.13  augustss 		       sc->sc_dev.dv_xname);
    253       1.13  augustss 		panic("usb_create_event_thread");
    254       1.13  augustss 	}
    255   1.53.2.2   nathanw 	if (!created) {
    256   1.53.2.2   nathanw 		created = 1;
    257   1.53.2.2   nathanw 		TAILQ_INIT(&usb_all_tasks);
    258   1.53.2.2   nathanw 		if (usb_kthread_create1(usb_task_thread, NULL,
    259   1.53.2.2   nathanw 					&usb_task_thread_proc, "usbtask")) {
    260   1.53.2.2   nathanw 			printf("unable to create task thread\n");
    261   1.53.2.2   nathanw 			panic("usb_create_event_thread task");
    262   1.53.2.2   nathanw 		}
    263   1.53.2.2   nathanw 	}
    264       1.13  augustss }
    265       1.13  augustss 
    266       1.52  augustss /*
    267   1.53.2.3   nathanw  * Add a task to be performed by the task thread.  This function can be
    268       1.52  augustss  * called from any context and the task will be executed in a process
    269       1.52  augustss  * context ASAP.
    270       1.52  augustss  */
    271       1.13  augustss void
    272       1.51  augustss usb_add_task(usbd_device_handle dev, struct usb_task *task)
    273       1.51  augustss {
    274       1.51  augustss 	int s;
    275       1.51  augustss 
    276       1.51  augustss 	s = splusb();
    277       1.51  augustss 	if (!task->onqueue) {
    278   1.53.2.2   nathanw 		DPRINTFN(2,("usb_add_task: task=%p\n", task));
    279   1.53.2.2   nathanw 		TAILQ_INSERT_TAIL(&usb_all_tasks, task, next);
    280       1.51  augustss 		task->onqueue = 1;
    281   1.53.2.3   nathanw 	} else {
    282   1.53.2.2   nathanw 		DPRINTFN(3,("usb_add_task: task=%p on q\n", task));
    283   1.53.2.3   nathanw 	}
    284   1.53.2.2   nathanw 	wakeup(&usb_all_tasks);
    285       1.51  augustss 	splx(s);
    286       1.51  augustss }
    287       1.51  augustss 
    288       1.51  augustss void
    289       1.53  augustss usb_rem_task(usbd_device_handle dev, struct usb_task *task)
    290       1.53  augustss {
    291       1.53  augustss 	int s;
    292       1.53  augustss 
    293       1.53  augustss 	s = splusb();
    294       1.53  augustss 	if (task->onqueue) {
    295   1.53.2.2   nathanw 		TAILQ_REMOVE(&usb_all_tasks, task, next);
    296       1.53  augustss 		task->onqueue = 0;
    297       1.53  augustss 	}
    298       1.53  augustss 	splx(s);
    299       1.53  augustss }
    300       1.53  augustss 
    301       1.53  augustss void
    302       1.45  augustss usb_event_thread(void *arg)
    303       1.13  augustss {
    304       1.13  augustss 	struct usb_softc *sc = arg;
    305       1.13  augustss 
    306       1.27  augustss 	DPRINTF(("usb_event_thread: start\n"));
    307       1.40  augustss 
    308   1.53.2.2   nathanw 	/*
    309   1.53.2.2   nathanw 	 * In case this controller is a companion controller to an
    310   1.53.2.2   nathanw 	 * EHCI controller we need to wait until the EHCI controller
    311   1.53.2.2   nathanw 	 * has grabbed the port.
    312   1.53.2.3   nathanw 	 * XXX It would be nicer to do this with a tsleep(), but I don't
    313   1.53.2.3   nathanw 	 * know how to synchronize the creation of the threads so it
    314   1.53.2.3   nathanw 	 * will work.
    315   1.53.2.2   nathanw 	 */
    316   1.53.2.2   nathanw 	usb_delay_ms(sc->sc_bus, 500);
    317   1.53.2.2   nathanw 
    318       1.40  augustss 	/* Make sure first discover does something. */
    319       1.40  augustss 	sc->sc_bus->needs_explore = 1;
    320       1.51  augustss 	usb_discover(sc);
    321       1.51  augustss 	config_pending_decr();
    322       1.27  augustss 
    323       1.22  augustss 	while (!sc->sc_dying) {
    324   1.53.2.2   nathanw #ifdef USB_DEBUG
    325   1.53.2.2   nathanw 		if (usb_noexplore < 2)
    326   1.53.2.2   nathanw #endif
    327   1.53.2.2   nathanw 		usb_discover(sc);
    328   1.53.2.2   nathanw #ifdef USB_DEBUG
    329   1.53.2.2   nathanw 		(void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
    330   1.53.2.2   nathanw 		    usb_noexplore ? 0 : hz * 60);
    331   1.53.2.2   nathanw #else
    332   1.53.2.2   nathanw 		(void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
    333   1.53.2.2   nathanw 		    hz * 60);
    334   1.53.2.2   nathanw #endif
    335   1.53.2.2   nathanw 		DPRINTFN(2,("usb_event_thread: woke up\n"));
    336       1.13  augustss 	}
    337       1.50  augustss 	sc->sc_event_thread = NULL;
    338       1.13  augustss 
    339       1.13  augustss 	/* In case parent is waiting for us to exit. */
    340       1.13  augustss 	wakeup(sc);
    341       1.13  augustss 
    342       1.27  augustss 	DPRINTF(("usb_event_thread: exit\n"));
    343       1.13  augustss 	kthread_exit(0);
    344       1.13  augustss }
    345       1.13  augustss 
    346   1.53.2.2   nathanw void
    347   1.53.2.2   nathanw usb_task_thread(void *arg)
    348   1.53.2.2   nathanw {
    349   1.53.2.2   nathanw 	struct usb_task *task;
    350   1.53.2.2   nathanw 	int s;
    351   1.53.2.2   nathanw 
    352   1.53.2.2   nathanw 	DPRINTF(("usb_task_thread: start\n"));
    353   1.53.2.2   nathanw 
    354   1.53.2.2   nathanw 	s = splusb();
    355   1.53.2.2   nathanw 	for (;;) {
    356   1.53.2.2   nathanw 		task = TAILQ_FIRST(&usb_all_tasks);
    357   1.53.2.2   nathanw 		if (task == NULL) {
    358   1.53.2.2   nathanw 			tsleep(&usb_all_tasks, PWAIT, "usbtsk", 0);
    359   1.53.2.2   nathanw 			task = TAILQ_FIRST(&usb_all_tasks);
    360   1.53.2.2   nathanw 		}
    361   1.53.2.2   nathanw 		DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task));
    362   1.53.2.2   nathanw 		if (task != NULL) {
    363   1.53.2.2   nathanw 			TAILQ_REMOVE(&usb_all_tasks, task, next);
    364   1.53.2.2   nathanw 			task->onqueue = 0;
    365   1.53.2.2   nathanw 			splx(s);
    366   1.53.2.2   nathanw 			task->fun(task->arg);
    367   1.53.2.2   nathanw 			s = splusb();
    368   1.53.2.2   nathanw 		}
    369   1.53.2.2   nathanw 	}
    370   1.53.2.2   nathanw }
    371   1.53.2.2   nathanw 
    372        1.1  augustss int
    373       1.45  augustss usbctlprint(void *aux, const char *pnp)
    374        1.1  augustss {
    375        1.1  augustss 	/* only "usb"es can attach to host controllers */
    376        1.1  augustss 	if (pnp)
    377  1.53.2.10   thorpej 		aprint_normal("usb at %s", pnp);
    378        1.1  augustss 
    379        1.1  augustss 	return (UNCONF);
    380        1.1  augustss }
    381       1.28  augustss #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
    382        1.7  augustss 
    383        1.1  augustss int
    384   1.53.2.2   nathanw usbopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
    385        1.1  augustss {
    386       1.26  augustss 	int unit = minor(dev);
    387       1.26  augustss 	struct usb_softc *sc;
    388       1.26  augustss 
    389       1.26  augustss 	if (unit == USB_DEV_MINOR) {
    390       1.26  augustss 		if (usb_dev_open)
    391       1.26  augustss 			return (EBUSY);
    392       1.26  augustss 		usb_dev_open = 1;
    393       1.26  augustss 		usb_async_proc = 0;
    394       1.26  augustss 		return (0);
    395       1.26  augustss 	}
    396       1.26  augustss 
    397       1.26  augustss 	USB_GET_SC_OPEN(usb, unit, sc);
    398        1.1  augustss 
    399       1.22  augustss 	if (sc->sc_dying)
    400       1.22  augustss 		return (EIO);
    401        1.1  augustss 
    402        1.1  augustss 	return (0);
    403        1.1  augustss }
    404        1.1  augustss 
    405        1.1  augustss int
    406       1.45  augustss usbread(dev_t dev, struct uio *uio, int flag)
    407       1.26  augustss {
    408       1.26  augustss 	struct usb_event ue;
    409       1.26  augustss 	int s, error, n;
    410       1.26  augustss 
    411       1.26  augustss 	if (minor(dev) != USB_DEV_MINOR)
    412       1.26  augustss 		return (ENXIO);
    413       1.26  augustss 
    414       1.26  augustss 	if (uio->uio_resid != sizeof(struct usb_event))
    415       1.26  augustss 		return (EINVAL);
    416       1.26  augustss 
    417       1.26  augustss 	error = 0;
    418       1.26  augustss 	s = splusb();
    419       1.26  augustss 	for (;;) {
    420       1.26  augustss 		n = usb_get_next_event(&ue);
    421       1.26  augustss 		if (n != 0)
    422       1.26  augustss 			break;
    423       1.26  augustss 		if (flag & IO_NDELAY) {
    424       1.26  augustss 			error = EWOULDBLOCK;
    425       1.26  augustss 			break;
    426       1.26  augustss 		}
    427       1.26  augustss 		error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0);
    428       1.26  augustss 		if (error)
    429       1.26  augustss 			break;
    430       1.26  augustss 	}
    431       1.26  augustss 	splx(s);
    432       1.26  augustss 	if (!error)
    433       1.30  augustss 		error = uiomove((void *)&ue, uio->uio_resid, uio);
    434       1.26  augustss 
    435       1.26  augustss 	return (error);
    436       1.26  augustss }
    437       1.26  augustss 
    438       1.26  augustss int
    439   1.53.2.2   nathanw usbclose(dev_t dev, int flag, int mode, usb_proc_ptr p)
    440        1.1  augustss {
    441       1.26  augustss 	int unit = minor(dev);
    442       1.26  augustss 
    443       1.26  augustss 	if (unit == USB_DEV_MINOR) {
    444       1.26  augustss 		usb_async_proc = 0;
    445       1.26  augustss 		usb_dev_open = 0;
    446       1.26  augustss 	}
    447       1.26  augustss 
    448        1.1  augustss 	return (0);
    449        1.1  augustss }
    450        1.1  augustss 
    451        1.1  augustss int
    452   1.53.2.2   nathanw usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
    453        1.1  augustss {
    454       1.26  augustss 	struct usb_softc *sc;
    455       1.28  augustss 	int unit = minor(devt);
    456       1.26  augustss 
    457       1.26  augustss 	if (unit == USB_DEV_MINOR) {
    458       1.26  augustss 		switch (cmd) {
    459       1.26  augustss 		case FIONBIO:
    460       1.26  augustss 			/* All handled in the upper FS layer. */
    461       1.26  augustss 			return (0);
    462   1.53.2.4   nathanw 
    463       1.26  augustss 		case FIOASYNC:
    464       1.26  augustss 			if (*(int *)data)
    465       1.26  augustss 				usb_async_proc = p;
    466       1.26  augustss 			else
    467       1.26  augustss 				usb_async_proc = 0;
    468       1.26  augustss 			return (0);
    469       1.26  augustss 
    470       1.26  augustss 		default:
    471       1.26  augustss 			return (EINVAL);
    472       1.26  augustss 		}
    473       1.26  augustss 	}
    474       1.26  augustss 
    475       1.26  augustss 	USB_GET_SC(usb, unit, sc);
    476        1.1  augustss 
    477       1.22  augustss 	if (sc->sc_dying)
    478       1.22  augustss 		return (EIO);
    479       1.22  augustss 
    480        1.1  augustss 	switch (cmd) {
    481        1.1  augustss #ifdef USB_DEBUG
    482        1.1  augustss 	case USB_SETDEBUG:
    483   1.53.2.5   nathanw 		if (!(flag & FWRITE))
    484   1.53.2.5   nathanw 			return (EBADF);
    485       1.30  augustss 		usbdebug  = ((*(int *)data) & 0x000000ff);
    486  1.53.2.10   thorpej #if defined(UHCI_DEBUG) && NUHCI > 0
    487       1.30  augustss 		uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8;
    488       1.30  augustss #endif
    489  1.53.2.10   thorpej #if defined(OHCI_DEBUG) && NOHCI > 0
    490       1.30  augustss 		ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16;
    491       1.30  augustss #endif
    492        1.1  augustss 		break;
    493   1.53.2.1   nathanw #endif /* USB_DEBUG */
    494        1.1  augustss 	case USB_REQUEST:
    495        1.1  augustss 	{
    496        1.1  augustss 		struct usb_ctl_request *ur = (void *)data;
    497   1.53.2.4   nathanw 		int len = UGETW(ur->ucr_request.wLength);
    498        1.1  augustss 		struct iovec iov;
    499        1.1  augustss 		struct uio uio;
    500        1.1  augustss 		void *ptr = 0;
    501   1.53.2.4   nathanw 		int addr = ur->ucr_addr;
    502       1.29  augustss 		usbd_status err;
    503        1.1  augustss 		int error = 0;
    504        1.1  augustss 
    505   1.53.2.5   nathanw 		if (!(flag & FWRITE))
    506   1.53.2.5   nathanw 			return (EBADF);
    507   1.53.2.5   nathanw 
    508        1.9  augustss 		DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
    509        1.1  augustss 		if (len < 0 || len > 32768)
    510        1.9  augustss 			return (EINVAL);
    511   1.53.2.4   nathanw 		if (addr < 0 || addr >= USB_MAX_DEVICES ||
    512        1.1  augustss 		    sc->sc_bus->devices[addr] == 0)
    513        1.9  augustss 			return (EINVAL);
    514        1.1  augustss 		if (len != 0) {
    515   1.53.2.4   nathanw 			iov.iov_base = (caddr_t)ur->ucr_data;
    516        1.1  augustss 			iov.iov_len = len;
    517        1.1  augustss 			uio.uio_iov = &iov;
    518        1.1  augustss 			uio.uio_iovcnt = 1;
    519        1.1  augustss 			uio.uio_resid = len;
    520        1.1  augustss 			uio.uio_offset = 0;
    521        1.1  augustss 			uio.uio_segflg = UIO_USERSPACE;
    522        1.1  augustss 			uio.uio_rw =
    523   1.53.2.4   nathanw 				ur->ucr_request.bmRequestType & UT_READ ?
    524        1.1  augustss 				UIO_READ : UIO_WRITE;
    525        1.1  augustss 			uio.uio_procp = p;
    526        1.1  augustss 			ptr = malloc(len, M_TEMP, M_WAITOK);
    527        1.1  augustss 			if (uio.uio_rw == UIO_WRITE) {
    528        1.1  augustss 				error = uiomove(ptr, len, &uio);
    529        1.1  augustss 				if (error)
    530        1.1  augustss 					goto ret;
    531        1.1  augustss 			}
    532        1.1  augustss 		}
    533       1.29  augustss 		err = usbd_do_request_flags(sc->sc_bus->devices[addr],
    534   1.53.2.4   nathanw 			  &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen,
    535   1.53.2.4   nathanw 			  USBD_DEFAULT_TIMEOUT);
    536       1.29  augustss 		if (err) {
    537        1.1  augustss 			error = EIO;
    538        1.1  augustss 			goto ret;
    539        1.1  augustss 		}
    540        1.1  augustss 		if (len != 0) {
    541        1.1  augustss 			if (uio.uio_rw == UIO_READ) {
    542        1.1  augustss 				error = uiomove(ptr, len, &uio);
    543        1.1  augustss 				if (error)
    544        1.1  augustss 					goto ret;
    545        1.1  augustss 			}
    546        1.1  augustss 		}
    547        1.1  augustss 	ret:
    548        1.1  augustss 		if (ptr)
    549        1.1  augustss 			free(ptr, M_TEMP);
    550        1.1  augustss 		return (error);
    551        1.1  augustss 	}
    552        1.1  augustss 
    553        1.1  augustss 	case USB_DEVICEINFO:
    554        1.1  augustss 	{
    555        1.1  augustss 		struct usb_device_info *di = (void *)data;
    556   1.53.2.4   nathanw 		int addr = di->udi_addr;
    557       1.30  augustss 		usbd_device_handle dev;
    558        1.1  augustss 
    559        1.1  augustss 		if (addr < 1 || addr >= USB_MAX_DEVICES)
    560        1.1  augustss 			return (EINVAL);
    561       1.30  augustss 		dev = sc->sc_bus->devices[addr];
    562       1.30  augustss 		if (dev == NULL)
    563        1.1  augustss 			return (ENXIO);
    564       1.48  augustss 		usbd_fill_deviceinfo(dev, di, 1);
    565        1.1  augustss 		break;
    566        1.1  augustss 	}
    567        1.2  augustss 
    568        1.2  augustss 	case USB_DEVICESTATS:
    569        1.2  augustss 		*(struct usb_device_stats *)data = sc->sc_bus->stats;
    570        1.2  augustss 		break;
    571        1.1  augustss 
    572        1.1  augustss 	default:
    573       1.26  augustss 		return (EINVAL);
    574        1.1  augustss 	}
    575        1.1  augustss 	return (0);
    576        1.1  augustss }
    577        1.1  augustss 
    578        1.1  augustss int
    579   1.53.2.2   nathanw usbpoll(dev_t dev, int events, usb_proc_ptr p)
    580        1.1  augustss {
    581       1.26  augustss 	int revents, mask, s;
    582        1.1  augustss 
    583       1.30  augustss 	if (minor(dev) == USB_DEV_MINOR) {
    584       1.30  augustss 		revents = 0;
    585       1.30  augustss 		mask = POLLIN | POLLRDNORM;
    586   1.53.2.4   nathanw 
    587       1.30  augustss 		s = splusb();
    588       1.30  augustss 		if (events & mask && usb_nevents > 0)
    589       1.30  augustss 			revents |= events & mask;
    590       1.30  augustss 		if (revents == 0 && events & mask)
    591       1.30  augustss 			selrecord(p, &usb_selevent);
    592       1.30  augustss 		splx(s);
    593   1.53.2.4   nathanw 
    594       1.30  augustss 		return (revents);
    595       1.30  augustss 	} else {
    596       1.30  augustss 		return (ENXIO);
    597        1.1  augustss 	}
    598        1.1  augustss }
    599        1.1  augustss 
    600   1.53.2.8   nathanw static void
    601   1.53.2.8   nathanw filt_usbrdetach(struct knote *kn)
    602   1.53.2.8   nathanw {
    603   1.53.2.8   nathanw 	int s;
    604   1.53.2.8   nathanw 
    605   1.53.2.8   nathanw 	s = splusb();
    606   1.53.2.9   thorpej 	SLIST_REMOVE(&usb_selevent.sel_klist, kn, knote, kn_selnext);
    607   1.53.2.8   nathanw 	splx(s);
    608   1.53.2.8   nathanw }
    609   1.53.2.8   nathanw 
    610   1.53.2.8   nathanw static int
    611   1.53.2.8   nathanw filt_usbread(struct knote *kn, long hint)
    612   1.53.2.8   nathanw {
    613   1.53.2.8   nathanw 
    614   1.53.2.8   nathanw 	if (usb_nevents == 0)
    615   1.53.2.8   nathanw 		return (0);
    616   1.53.2.8   nathanw 
    617   1.53.2.8   nathanw 	kn->kn_data = sizeof(struct usb_event);
    618   1.53.2.8   nathanw 	return (1);
    619   1.53.2.8   nathanw }
    620   1.53.2.8   nathanw 
    621   1.53.2.8   nathanw static const struct filterops usbread_filtops =
    622   1.53.2.8   nathanw 	{ 1, NULL, filt_usbrdetach, filt_usbread };
    623   1.53.2.8   nathanw 
    624   1.53.2.8   nathanw int
    625   1.53.2.8   nathanw usbkqfilter(dev_t dev, struct knote *kn)
    626   1.53.2.8   nathanw {
    627   1.53.2.8   nathanw 	struct klist *klist;
    628   1.53.2.8   nathanw 	int s;
    629   1.53.2.8   nathanw 
    630   1.53.2.8   nathanw 	switch (kn->kn_filter) {
    631   1.53.2.8   nathanw 	case EVFILT_READ:
    632   1.53.2.8   nathanw 		if (minor(dev) != USB_DEV_MINOR)
    633   1.53.2.8   nathanw 			return (1);
    634   1.53.2.9   thorpej 		klist = &usb_selevent.sel_klist;
    635   1.53.2.8   nathanw 		kn->kn_fop = &usbread_filtops;
    636   1.53.2.8   nathanw 		break;
    637   1.53.2.8   nathanw 
    638   1.53.2.8   nathanw 	default:
    639   1.53.2.8   nathanw 		return (1);
    640   1.53.2.8   nathanw 	}
    641   1.53.2.8   nathanw 
    642   1.53.2.8   nathanw 	kn->kn_hook = NULL;
    643   1.53.2.8   nathanw 
    644   1.53.2.8   nathanw 	s = splusb();
    645   1.53.2.8   nathanw 	SLIST_INSERT_HEAD(klist, kn, kn_selnext);
    646   1.53.2.8   nathanw 	splx(s);
    647   1.53.2.8   nathanw 
    648   1.53.2.8   nathanw 	return (0);
    649   1.53.2.8   nathanw }
    650   1.53.2.8   nathanw 
    651       1.25  augustss /* Explore device tree from the root. */
    652       1.51  augustss Static void
    653       1.51  augustss usb_discover(void *v)
    654        1.1  augustss {
    655       1.51  augustss 	struct usb_softc *sc = v;
    656       1.51  augustss 
    657       1.51  augustss 	DPRINTFN(2,("usb_discover\n"));
    658       1.51  augustss #ifdef USB_DEBUG
    659       1.51  augustss 	if (usb_noexplore > 1)
    660       1.51  augustss 		return;
    661       1.51  augustss #endif
    662   1.53.2.4   nathanw 	/*
    663       1.25  augustss 	 * We need mutual exclusion while traversing the device tree,
    664       1.25  augustss 	 * but this is guaranteed since this function is only called
    665       1.25  augustss 	 * from the event thread for the controller.
    666       1.25  augustss 	 */
    667       1.30  augustss 	while (sc->sc_bus->needs_explore && !sc->sc_dying) {
    668       1.13  augustss 		sc->sc_bus->needs_explore = 0;
    669       1.13  augustss 		sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
    670       1.30  augustss 	}
    671        1.1  augustss }
    672        1.1  augustss 
    673        1.1  augustss void
    674       1.51  augustss usb_needs_explore(usbd_device_handle dev)
    675        1.1  augustss {
    676       1.51  augustss 	DPRINTFN(2,("usb_needs_explore\n"));
    677       1.51  augustss 	dev->bus->needs_explore = 1;
    678   1.53.2.2   nathanw 	wakeup(&dev->bus->needs_explore);
    679        1.1  augustss }
    680        1.7  augustss 
    681       1.26  augustss /* Called at splusb() */
    682       1.26  augustss int
    683       1.45  augustss usb_get_next_event(struct usb_event *ue)
    684       1.26  augustss {
    685       1.26  augustss 	struct usb_event_q *ueq;
    686       1.26  augustss 
    687       1.26  augustss 	if (usb_nevents <= 0)
    688       1.26  augustss 		return (0);
    689       1.26  augustss 	ueq = SIMPLEQ_FIRST(&usb_events);
    690   1.53.2.3   nathanw #ifdef DIAGNOSTIC
    691   1.53.2.3   nathanw 	if (ueq == NULL) {
    692   1.53.2.3   nathanw 		printf("usb: usb_nevents got out of sync! %d\n", usb_nevents);
    693   1.53.2.3   nathanw 		usb_nevents = 0;
    694   1.53.2.3   nathanw 		return (0);
    695   1.53.2.3   nathanw 	}
    696   1.53.2.3   nathanw #endif
    697       1.26  augustss 	*ue = ueq->ue;
    698   1.53.2.5   nathanw 	SIMPLEQ_REMOVE_HEAD(&usb_events, next);
    699       1.26  augustss 	free(ueq, M_USBDEV);
    700       1.26  augustss 	usb_nevents--;
    701       1.26  augustss 	return (1);
    702       1.26  augustss }
    703       1.26  augustss 
    704       1.26  augustss void
    705       1.45  augustss usbd_add_dev_event(int type, usbd_device_handle udev)
    706       1.38  augustss {
    707       1.38  augustss 	struct usb_event ue;
    708       1.38  augustss 
    709       1.48  augustss 	usbd_fill_deviceinfo(udev, &ue.u.ue_device, USB_EVENT_IS_ATTACH(type));
    710       1.38  augustss 	usb_add_event(type, &ue);
    711       1.38  augustss }
    712       1.38  augustss 
    713       1.38  augustss void
    714       1.45  augustss usbd_add_drv_event(int type, usbd_device_handle udev, device_ptr_t dev)
    715       1.38  augustss {
    716       1.38  augustss 	struct usb_event ue;
    717       1.38  augustss 
    718       1.38  augustss 	ue.u.ue_driver.ue_cookie = udev->cookie;
    719   1.53.2.4   nathanw 	strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev),
    720       1.38  augustss 	    sizeof ue.u.ue_driver.ue_devname);
    721       1.38  augustss 	usb_add_event(type, &ue);
    722       1.38  augustss }
    723       1.38  augustss 
    724       1.42  augustss Static void
    725       1.45  augustss usb_add_event(int type, struct usb_event *uep)
    726       1.26  augustss {
    727       1.26  augustss 	struct usb_event_q *ueq;
    728       1.26  augustss 	struct usb_event ue;
    729       1.26  augustss 	struct timeval thetime;
    730       1.26  augustss 	int s;
    731       1.26  augustss 
    732       1.38  augustss 	microtime(&thetime);
    733       1.38  augustss 	/* Don't want to wait here inside splusb() */
    734       1.38  augustss 	ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK);
    735       1.38  augustss 	ueq->ue = *uep;
    736       1.38  augustss 	ueq->ue.ue_type = type;
    737       1.38  augustss 	TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
    738       1.38  augustss 
    739       1.26  augustss 	s = splusb();
    740       1.26  augustss 	if (++usb_nevents >= USB_MAX_EVENTS) {
    741       1.26  augustss 		/* Too many queued events, drop an old one. */
    742       1.26  augustss 		DPRINTFN(-1,("usb: event dropped\n"));
    743       1.26  augustss 		(void)usb_get_next_event(&ue);
    744       1.26  augustss 	}
    745       1.26  augustss 	SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next);
    746       1.26  augustss 	wakeup(&usb_events);
    747   1.53.2.8   nathanw 	selnotify(&usb_selevent, 0);
    748       1.29  augustss 	if (usb_async_proc != NULL)
    749       1.26  augustss 		psignal(usb_async_proc, SIGIO);
    750       1.26  augustss 	splx(s);
    751       1.39  augustss }
    752   1.53.2.2   nathanw 
    753       1.39  augustss void
    754       1.49  augustss usb_schedsoftintr(usbd_bus_handle bus)
    755       1.39  augustss {
    756   1.53.2.1   nathanw 	DPRINTFN(10,("usb_schedsoftintr: polling=%d\n", bus->use_polling));
    757       1.49  augustss #ifdef USB_USE_SOFTINTR
    758       1.49  augustss 	if (bus->use_polling) {
    759       1.49  augustss 		bus->methods->soft_intr(bus);
    760       1.49  augustss 	} else {
    761       1.49  augustss #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
    762       1.49  augustss 		softintr_schedule(bus->soft);
    763       1.49  augustss #else
    764       1.49  augustss 		if (!callout_pending(&bus->softi))
    765       1.49  augustss 			callout_reset(&bus->softi, 0, bus->methods->soft_intr,
    766       1.49  augustss 			    bus);
    767       1.49  augustss #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
    768       1.49  augustss 	}
    769       1.49  augustss #else
    770       1.39  augustss 	bus->methods->soft_intr(bus);
    771   1.53.2.1   nathanw #endif /* USB_USE_SOFTINTR */
    772       1.26  augustss }
    773       1.26  augustss 
    774        1.7  augustss int
    775       1.45  augustss usb_activate(device_ptr_t self, enum devact act)
    776        1.7  augustss {
    777       1.22  augustss 	struct usb_softc *sc = (struct usb_softc *)self;
    778       1.25  augustss 	usbd_device_handle dev = sc->sc_port.device;
    779       1.25  augustss 	int i, rv = 0;
    780       1.22  augustss 
    781       1.22  augustss 	switch (act) {
    782       1.22  augustss 	case DVACT_ACTIVATE:
    783       1.22  augustss 		return (EOPNOTSUPP);
    784       1.22  augustss 
    785       1.22  augustss 	case DVACT_DEACTIVATE:
    786       1.22  augustss 		sc->sc_dying = 1;
    787   1.53.2.3   nathanw 		if (dev != NULL && dev->cdesc != NULL && dev->subdevs != NULL) {
    788       1.25  augustss 			for (i = 0; dev->subdevs[i]; i++)
    789       1.25  augustss 				rv |= config_deactivate(dev->subdevs[i]);
    790       1.25  augustss 		}
    791       1.22  augustss 		break;
    792       1.22  augustss 	}
    793       1.22  augustss 	return (rv);
    794       1.13  augustss }
    795        1.7  augustss 
    796       1.13  augustss int
    797       1.45  augustss usb_detach(device_ptr_t self, int flags)
    798       1.13  augustss {
    799       1.22  augustss 	struct usb_softc *sc = (struct usb_softc *)self;
    800       1.38  augustss 	struct usb_event ue;
    801       1.22  augustss 
    802       1.27  augustss 	DPRINTF(("usb_detach: start\n"));
    803       1.27  augustss 
    804       1.22  augustss 	sc->sc_dying = 1;
    805       1.22  augustss 
    806       1.22  augustss 	/* Make all devices disconnect. */
    807   1.53.2.3   nathanw 	if (sc->sc_port.device != NULL)
    808       1.27  augustss 		usb_disconnect_port(&sc->sc_port, self);
    809       1.22  augustss 
    810       1.22  augustss 	/* Kill off event thread. */
    811   1.53.2.3   nathanw 	if (sc->sc_event_thread != NULL) {
    812   1.53.2.2   nathanw 		wakeup(&sc->sc_bus->needs_explore);
    813       1.22  augustss 		if (tsleep(sc, PWAIT, "usbdet", hz * 60))
    814       1.22  augustss 			printf("%s: event thread didn't die\n",
    815       1.22  augustss 			       USBDEVNAME(sc->sc_dev));
    816       1.27  augustss 		DPRINTF(("usb_detach: event thread dead\n"));
    817       1.22  augustss 	}
    818       1.22  augustss 
    819       1.26  augustss 	usbd_finish();
    820       1.49  augustss 
    821       1.49  augustss #ifdef USB_USE_SOFTINTR
    822       1.49  augustss #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
    823       1.49  augustss 	if (sc->sc_bus->soft != NULL) {
    824       1.49  augustss 		softintr_disestablish(sc->sc_bus->soft);
    825       1.49  augustss 		sc->sc_bus->soft = NULL;
    826       1.49  augustss 	}
    827       1.49  augustss #else
    828       1.49  augustss 	callout_stop(&sc->sc_bus->softi);
    829       1.49  augustss #endif
    830       1.49  augustss #endif
    831       1.38  augustss 
    832       1.38  augustss 	ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
    833       1.38  augustss 	usb_add_event(USB_EVENT_CTRLR_DETACH, &ue);
    834       1.38  augustss 
    835        1.7  augustss 	return (0);
    836        1.7  augustss }
    837