usb.c revision 1.91 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 (at) 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