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