usb.c revision 1.100 1 /* $NetBSD: usb.c,v 1.100 2007/10/08 16:18:04 ad 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.100 2007/10/08 16:18:04 ad Exp $");
48
49 #include "opt_compat_netbsd.h"
50
51 #include "ohci.h"
52 #include "uhci.h"
53
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/kernel.h>
57 #include <sys/malloc.h>
58 #include <sys/device.h>
59 #include <sys/kthread.h>
60 #include <sys/proc.h>
61 #include <sys/conf.h>
62 #include <sys/fcntl.h>
63 #include <sys/poll.h>
64 #include <sys/select.h>
65 #include <sys/vnode.h>
66 #include <sys/signalvar.h>
67 #include <sys/intr.h>
68
69 #include <dev/usb/usb.h>
70 #include <dev/usb/usbdi.h>
71 #include <dev/usb/usbdi_util.h>
72
73 #define USB_DEV_MINOR 255
74
75 #include <machine/bus.h>
76
77 #include <dev/usb/usbdivar.h>
78 #include <dev/usb/usb_quirks.h>
79
80 #ifdef USB_DEBUG
81 #define DPRINTF(x) if (usbdebug) logprintf x
82 #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
83 int usbdebug = 0;
84 #if defined(UHCI_DEBUG) && NUHCI > 0
85 extern int uhcidebug;
86 #endif
87 #if defined(OHCI_DEBUG) && NOHCI > 0
88 extern int ohcidebug;
89 #endif
90 /*
91 * 0 - do usual exploration
92 * 1 - do not use timeout exploration
93 * >1 - do no exploration
94 */
95 int usb_noexplore = 0;
96 #else
97 #define DPRINTF(x)
98 #define DPRINTFN(n,x)
99 #endif
100
101 struct usb_softc {
102 USBBASEDEVICE sc_dev; /* base device */
103 usbd_bus_handle sc_bus; /* USB controller */
104 struct usbd_port sc_port; /* dummy port for root hub */
105
106 struct lwp *sc_event_thread;
107
108 char sc_dying;
109 };
110
111 struct usb_taskq {
112 TAILQ_HEAD(, usb_task) tasks;
113 struct lwp *task_thread_lwp;
114 const char *name;
115 int taskcreated; /* task thread exists. */
116 };
117
118 static struct usb_taskq usb_taskq[USB_NUM_TASKQS];
119
120 dev_type_open(usbopen);
121 dev_type_close(usbclose);
122 dev_type_read(usbread);
123 dev_type_ioctl(usbioctl);
124 dev_type_poll(usbpoll);
125 dev_type_kqfilter(usbkqfilter);
126
127 const struct cdevsw usb_cdevsw = {
128 usbopen, usbclose, usbread, nowrite, usbioctl,
129 nostop, notty, usbpoll, nommap, usbkqfilter, D_OTHER,
130 };
131
132 Static void usb_discover(void *);
133 Static void usb_create_event_thread(void *);
134 Static void usb_event_thread(void *);
135 Static void usb_task_thread(void *);
136
137 #define USB_MAX_EVENTS 100
138 struct usb_event_q {
139 struct usb_event ue;
140 SIMPLEQ_ENTRY(usb_event_q) next;
141 };
142 Static SIMPLEQ_HEAD(, usb_event_q) usb_events =
143 SIMPLEQ_HEAD_INITIALIZER(usb_events);
144 Static int usb_nevents = 0;
145 Static struct selinfo usb_selevent;
146 Static usb_proc_ptr usb_async_proc; /* process that wants USB SIGIO */
147 Static int usb_dev_open = 0;
148 Static struct usb_event *usb_alloc_event(void);
149 Static void usb_free_event(struct usb_event *);
150 Static void usb_add_event(int, struct usb_event *);
151
152 Static int usb_get_next_event(struct usb_event *);
153
154 #ifdef COMPAT_30
155 Static void usb_copy_old_devinfo(struct usb_device_info_old *, const struct usb_device_info *);
156 #endif
157
158 Static const char *usbrev_str[] = USBREV_STR;
159
160 USB_DECLARE_DRIVER(usb);
161
162 USB_MATCH(usb)
163 {
164 DPRINTF(("usbd_match\n"));
165 return (UMATCH_GENERIC);
166 }
167
168 USB_ATTACH(usb)
169 {
170 struct usb_softc *sc = (struct usb_softc *)self;
171 usbd_device_handle dev;
172 usbd_status err;
173 int usbrev;
174 int speed;
175 struct usb_event *ue;
176
177 DPRINTF(("usbd_attach\n"));
178
179 sc->sc_bus = aux;
180 sc->sc_bus->usbctl = sc;
181 sc->sc_port.power = USB_MAX_POWER;
182
183 usbrev = sc->sc_bus->usbrev;
184 printf(": USB revision %s", usbrev_str[usbrev]);
185 switch (usbrev) {
186 case USBREV_1_0:
187 case USBREV_1_1:
188 speed = USB_SPEED_FULL;
189 break;
190 case USBREV_2_0:
191 speed = USB_SPEED_HIGH;
192 break;
193 default:
194 printf(", not supported\n");
195 sc->sc_dying = 1;
196 USB_ATTACH_ERROR_RETURN;
197 }
198 printf("\n");
199
200 /* Make sure not to use tsleep() if we are cold booting. */
201 if (cold)
202 sc->sc_bus->use_polling++;
203
204 ue = usb_alloc_event();
205 ue->u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
206 usb_add_event(USB_EVENT_CTRLR_ATTACH, ue);
207
208 #ifdef USB_USE_SOFTINTR
209 /* XXX we should have our own level */
210 sc->sc_bus->soft = softint_establish(SOFTINT_NET,
211 sc->sc_bus->methods->soft_intr, sc->sc_bus);
212 if (sc->sc_bus->soft == NULL) {
213 printf("%s: can't register softintr\n", USBDEVNAME(sc->sc_dev));
214 sc->sc_dying = 1;
215 USB_ATTACH_ERROR_RETURN;
216 }
217 #endif
218
219 err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, speed, 0,
220 &sc->sc_port);
221 if (!err) {
222 dev = sc->sc_port.device;
223 if (dev->hub == NULL) {
224 sc->sc_dying = 1;
225 printf("%s: root device is not a hub\n",
226 USBDEVNAME(sc->sc_dev));
227 USB_ATTACH_ERROR_RETURN;
228 }
229 sc->sc_bus->root_hub = dev;
230 #if 1
231 /*
232 * Turning this code off will delay attachment of USB devices
233 * until the USB event thread is running, which means that
234 * the keyboard will not work until after cold boot.
235 */
236 if (cold && (device_cfdata(&sc->sc_dev)->cf_flags & 1))
237 dev->hub->explore(sc->sc_bus->root_hub);
238 #endif
239 } else {
240 printf("%s: root hub problem, error=%d\n",
241 USBDEVNAME(sc->sc_dev), err);
242 sc->sc_dying = 1;
243 }
244 if (cold)
245 sc->sc_bus->use_polling--;
246
247 config_pending_incr();
248 usb_kthread_create(usb_create_event_thread, sc);
249
250 USB_ATTACH_SUCCESS_RETURN;
251 }
252
253 static const char *taskq_names[] = USB_TASKQ_NAMES;
254
255 #if defined(__NetBSD__) || defined(__OpenBSD__)
256 void
257 usb_create_event_thread(void *arg)
258 {
259 struct usb_softc *sc = arg;
260 struct usb_taskq *taskq;
261 int i;
262
263 if (usb_kthread_create1(PRI_NONE, 0, NULL, usb_event_thread, sc,
264 &sc->sc_event_thread, "%s", sc->sc_dev.dv_xname)) {
265 printf("%s: unable to create event thread for\n",
266 sc->sc_dev.dv_xname);
267 panic("usb_create_event_thread");
268 }
269 for (i = 0; i < USB_NUM_TASKQS; i++) {
270 taskq = &usb_taskq[i];
271
272 if (taskq->taskcreated)
273 continue;
274
275 TAILQ_INIT(&taskq->tasks);
276 taskq->taskcreated = 1;
277 taskq->name = taskq_names[i];
278 if (usb_kthread_create1(PRI_NONE, 0, NULL, usb_task_thread,
279 taskq, &taskq->task_thread_lwp, taskq->name)) {
280 printf("unable to create task thread: %s\n", taskq->name);
281 panic("usb_create_event_thread task");
282 }
283 }
284 }
285
286 /*
287 * Add a task to be performed by the task thread. This function can be
288 * called from any context and the task will be executed in a process
289 * context ASAP.
290 */
291 void
292 usb_add_task(usbd_device_handle dev, struct usb_task *task, int queue)
293 {
294 struct usb_taskq *taskq;
295 int s;
296
297 taskq = &usb_taskq[queue];
298 s = splusb();
299 if (task->queue == -1) {
300 DPRINTFN(2,("usb_add_task: task=%p\n", task));
301 TAILQ_INSERT_TAIL(&taskq->tasks, task, next);
302 task->queue = queue;
303 } else {
304 DPRINTFN(3,("usb_add_task: task=%p on q\n", task));
305 }
306 wakeup(&taskq->tasks);
307 splx(s);
308 }
309
310 void
311 usb_rem_task(usbd_device_handle dev, struct usb_task *task)
312 {
313 struct usb_taskq *taskq;
314 int s;
315
316 taskq = &usb_taskq[task->queue];
317 s = splusb();
318 if (task->queue != -1) {
319 TAILQ_REMOVE(&taskq->tasks, task, next);
320 task->queue = -1;
321 }
322 splx(s);
323 }
324
325 void
326 usb_event_thread(void *arg)
327 {
328 struct usb_softc *sc = arg;
329
330 DPRINTF(("usb_event_thread: start\n"));
331
332 /*
333 * In case this controller is a companion controller to an
334 * EHCI controller we need to wait until the EHCI controller
335 * has grabbed the port.
336 * XXX It would be nicer to do this with a tsleep(), but I don't
337 * know how to synchronize the creation of the threads so it
338 * will work.
339 */
340 usb_delay_ms(sc->sc_bus, 500);
341
342 /* Make sure first discover does something. */
343 sc->sc_bus->needs_explore = 1;
344 usb_discover(sc);
345 config_pending_decr();
346
347 while (!sc->sc_dying) {
348 #ifdef USB_DEBUG
349 if (usb_noexplore < 2)
350 #endif
351 usb_discover(sc);
352 #ifdef USB_DEBUG
353 (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
354 usb_noexplore ? 0 : hz * 60);
355 #else
356 (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
357 hz * 60);
358 #endif
359 DPRINTFN(2,("usb_event_thread: woke up\n"));
360 }
361 sc->sc_event_thread = NULL;
362
363 /* In case parent is waiting for us to exit. */
364 wakeup(sc);
365
366 DPRINTF(("usb_event_thread: exit\n"));
367 kthread_exit(0);
368 }
369
370 void
371 usb_task_thread(void *arg)
372 {
373 struct usb_task *task;
374 struct usb_taskq *taskq;
375 int s;
376
377 taskq = arg;
378 DPRINTF(("usb_task_thread: start taskq %s\n", taskq->name));
379
380 s = splusb();
381 for (;;) {
382 task = TAILQ_FIRST(&taskq->tasks);
383 if (task == NULL) {
384 tsleep(&taskq->tasks, PWAIT, "usbtsk", 0);
385 task = TAILQ_FIRST(&taskq->tasks);
386 }
387 DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task));
388 if (task != NULL) {
389 TAILQ_REMOVE(&taskq->tasks, task, next);
390 task->queue = -1;
391 splx(s);
392 task->fun(task->arg);
393 s = splusb();
394 }
395 }
396 }
397
398 int
399 usbctlprint(void *aux, const char *pnp)
400 {
401 /* only "usb"es can attach to host controllers */
402 if (pnp)
403 aprint_normal("usb at %s", pnp);
404
405 return (UNCONF);
406 }
407 #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
408
409 int
410 usbopen(dev_t dev, int flag, int mode, struct lwp *l)
411 {
412 int unit = minor(dev);
413 struct usb_softc *sc;
414
415 if (unit == USB_DEV_MINOR) {
416 if (usb_dev_open)
417 return (EBUSY);
418 usb_dev_open = 1;
419 usb_async_proc = 0;
420 return (0);
421 }
422
423 USB_GET_SC_OPEN(usb, unit, sc);
424
425 if (sc->sc_dying)
426 return (EIO);
427
428 return (0);
429 }
430
431 int
432 usbread(dev_t dev, struct uio *uio, int flag)
433 {
434 struct usb_event *ue;
435 #ifdef COMPAT_30
436 struct usb_event_old *ueo = NULL; /* XXXGCC */
437 #endif
438 int s, error, n, useold;
439
440 if (minor(dev) != USB_DEV_MINOR)
441 return (ENXIO);
442
443 useold = 0;
444 switch (uio->uio_resid) {
445 #ifdef COMPAT_30
446 case sizeof(struct usb_event_old):
447 ueo = malloc(sizeof(struct usb_event_old), M_USBDEV,
448 M_WAITOK|M_ZERO);
449 useold = 1;
450 /* FALLTHRU */
451 #endif
452 case sizeof(struct usb_event):
453 ue = usb_alloc_event();
454 break;
455 default:
456 return (EINVAL);
457 }
458
459 error = 0;
460 s = splusb();
461 for (;;) {
462 n = usb_get_next_event(ue);
463 if (n != 0)
464 break;
465 if (flag & IO_NDELAY) {
466 error = EWOULDBLOCK;
467 break;
468 }
469 error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0);
470 if (error)
471 break;
472 }
473 splx(s);
474 if (!error) {
475 #ifdef COMPAT_30
476 if (useold) { /* copy fields to old struct */
477 ueo->ue_type = ue->ue_type;
478 memcpy(&ueo->ue_time, &ue->ue_time,
479 sizeof(struct timespec));
480 switch (ue->ue_type) {
481 case USB_EVENT_DEVICE_ATTACH:
482 case USB_EVENT_DEVICE_DETACH:
483 usb_copy_old_devinfo(&ueo->u.ue_device, &ue->u.ue_device);
484 break;
485
486 case USB_EVENT_CTRLR_ATTACH:
487 case USB_EVENT_CTRLR_DETACH:
488 ueo->u.ue_ctrlr.ue_bus=ue->u.ue_ctrlr.ue_bus;
489 break;
490
491 case USB_EVENT_DRIVER_ATTACH:
492 case USB_EVENT_DRIVER_DETACH:
493 ueo->u.ue_driver.ue_cookie=ue->u.ue_driver.ue_cookie;
494 memcpy(ueo->u.ue_driver.ue_devname,
495 ue->u.ue_driver.ue_devname,
496 sizeof(ue->u.ue_driver.ue_devname));
497 break;
498 default:
499 ;
500 }
501
502 error = uiomove((void *)ueo, uio->uio_resid, uio);
503 } else
504 #endif
505 error = uiomove((void *)ue, uio->uio_resid, uio);
506 }
507 usb_free_event(ue);
508 #ifdef COMPAT_30
509 if (useold)
510 free(ueo, M_USBDEV);
511 #endif
512
513 return (error);
514 }
515
516 int
517 usbclose(dev_t dev, int flag, int mode,
518 struct lwp *l)
519 {
520 int unit = minor(dev);
521
522 if (unit == USB_DEV_MINOR) {
523 usb_async_proc = 0;
524 usb_dev_open = 0;
525 }
526
527 return (0);
528 }
529
530 int
531 usbioctl(dev_t devt, u_long cmd, void *data, int flag, struct lwp *l)
532 {
533 struct usb_softc *sc;
534 int unit = minor(devt);
535
536 if (unit == USB_DEV_MINOR) {
537 switch (cmd) {
538 case FIONBIO:
539 /* All handled in the upper FS layer. */
540 return (0);
541
542 case FIOASYNC:
543 if (*(int *)data)
544 usb_async_proc = l->l_proc;
545 else
546 usb_async_proc = 0;
547 return (0);
548
549 default:
550 return (EINVAL);
551 }
552 }
553
554 USB_GET_SC(usb, unit, sc);
555
556 if (sc->sc_dying)
557 return (EIO);
558
559 switch (cmd) {
560 #ifdef USB_DEBUG
561 case USB_SETDEBUG:
562 if (!(flag & FWRITE))
563 return (EBADF);
564 usbdebug = ((*(int *)data) & 0x000000ff);
565 #if defined(UHCI_DEBUG) && NUHCI > 0
566 uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8;
567 #endif
568 #if defined(OHCI_DEBUG) && NOHCI > 0
569 ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16;
570 #endif
571 break;
572 #endif /* USB_DEBUG */
573 case USB_REQUEST:
574 {
575 struct usb_ctl_request *ur = (void *)data;
576 int len = UGETW(ur->ucr_request.wLength);
577 struct iovec iov;
578 struct uio uio;
579 void *ptr = 0;
580 int addr = ur->ucr_addr;
581 usbd_status err;
582 int error = 0;
583
584 if (!(flag & FWRITE))
585 return (EBADF);
586
587 DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
588 if (len < 0 || len > 32768)
589 return (EINVAL);
590 if (addr < 0 || addr >= USB_MAX_DEVICES ||
591 sc->sc_bus->devices[addr] == 0)
592 return (EINVAL);
593 if (len != 0) {
594 iov.iov_base = (void *)ur->ucr_data;
595 iov.iov_len = len;
596 uio.uio_iov = &iov;
597 uio.uio_iovcnt = 1;
598 uio.uio_resid = len;
599 uio.uio_offset = 0;
600 uio.uio_rw =
601 ur->ucr_request.bmRequestType & UT_READ ?
602 UIO_READ : UIO_WRITE;
603 uio.uio_vmspace = l->l_proc->p_vmspace;
604 ptr = malloc(len, M_TEMP, M_WAITOK);
605 if (uio.uio_rw == UIO_WRITE) {
606 error = uiomove(ptr, len, &uio);
607 if (error)
608 goto ret;
609 }
610 }
611 err = usbd_do_request_flags(sc->sc_bus->devices[addr],
612 &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen,
613 USBD_DEFAULT_TIMEOUT);
614 if (err) {
615 error = EIO;
616 goto ret;
617 }
618 if (len != 0) {
619 if (uio.uio_rw == UIO_READ) {
620 error = uiomove(ptr, len, &uio);
621 if (error)
622 goto ret;
623 }
624 }
625 ret:
626 if (ptr)
627 free(ptr, M_TEMP);
628 return (error);
629 }
630
631 case USB_DEVICEINFO:
632 {
633 usbd_device_handle dev;
634 struct usb_device_info *di = (void *)data;
635 int addr = di->udi_addr;
636
637 if (addr < 1 || addr >= USB_MAX_DEVICES)
638 return EINVAL;
639 if ((dev = sc->sc_bus->devices[addr]) == NULL)
640 return ENXIO;
641 usbd_fill_deviceinfo(dev, di, 1);
642 break;
643 }
644
645 #ifdef COMPAT_30
646 case USB_DEVICEINFO_OLD:
647 {
648 usbd_device_handle dev;
649 struct usb_device_info_old *di = (void *)data;
650 int addr = di->udi_addr;
651
652 if (addr < 1 || addr >= USB_MAX_DEVICES)
653 return EINVAL;
654 if ((dev = sc->sc_bus->devices[addr]) == NULL)
655 return ENXIO;
656 usbd_fill_deviceinfo_old(dev, di, 1);
657 break;
658 }
659 #endif
660
661 case USB_DEVICESTATS:
662 *(struct usb_device_stats *)data = sc->sc_bus->stats;
663 break;
664
665 default:
666 return (EINVAL);
667 }
668 return (0);
669 }
670
671 int
672 usbpoll(dev_t dev, int events, struct lwp *l)
673 {
674 int revents, mask, s;
675
676 if (minor(dev) == USB_DEV_MINOR) {
677 revents = 0;
678 mask = POLLIN | POLLRDNORM;
679
680 s = splusb();
681 if (events & mask && usb_nevents > 0)
682 revents |= events & mask;
683 if (revents == 0 && events & mask)
684 selrecord(l, &usb_selevent);
685 splx(s);
686
687 return (revents);
688 } else {
689 return (0);
690 }
691 }
692
693 static void
694 filt_usbrdetach(struct knote *kn)
695 {
696 int s;
697
698 s = splusb();
699 SLIST_REMOVE(&usb_selevent.sel_klist, kn, knote, kn_selnext);
700 splx(s);
701 }
702
703 static int
704 filt_usbread(struct knote *kn, long hint)
705 {
706
707 if (usb_nevents == 0)
708 return (0);
709
710 kn->kn_data = sizeof(struct usb_event);
711 return (1);
712 }
713
714 static const struct filterops usbread_filtops =
715 { 1, NULL, filt_usbrdetach, filt_usbread };
716
717 int
718 usbkqfilter(dev_t dev, struct knote *kn)
719 {
720 struct klist *klist;
721 int s;
722
723 switch (kn->kn_filter) {
724 case EVFILT_READ:
725 if (minor(dev) != USB_DEV_MINOR)
726 return (1);
727 klist = &usb_selevent.sel_klist;
728 kn->kn_fop = &usbread_filtops;
729 break;
730
731 default:
732 return (1);
733 }
734
735 kn->kn_hook = NULL;
736
737 s = splusb();
738 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
739 splx(s);
740
741 return (0);
742 }
743
744 /* Explore device tree from the root. */
745 Static void
746 usb_discover(void *v)
747 {
748 struct usb_softc *sc = v;
749
750 DPRINTFN(2,("usb_discover\n"));
751 #ifdef USB_DEBUG
752 if (usb_noexplore > 1)
753 return;
754 #endif
755 /*
756 * We need mutual exclusion while traversing the device tree,
757 * but this is guaranteed since this function is only called
758 * from the event thread for the controller.
759 */
760 while (sc->sc_bus->needs_explore && !sc->sc_dying) {
761 sc->sc_bus->needs_explore = 0;
762 sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
763 }
764 }
765
766 void
767 usb_needs_explore(usbd_device_handle dev)
768 {
769 DPRINTFN(2,("usb_needs_explore\n"));
770 dev->bus->needs_explore = 1;
771 wakeup(&dev->bus->needs_explore);
772 }
773
774 void
775 usb_needs_reattach(usbd_device_handle dev)
776 {
777 DPRINTFN(2,("usb_needs_reattach\n"));
778 dev->powersrc->reattach = 1;
779 dev->bus->needs_explore = 1;
780 wakeup(&dev->bus->needs_explore);
781 }
782
783 /* Called at splusb() */
784 int
785 usb_get_next_event(struct usb_event *ue)
786 {
787 struct usb_event_q *ueq;
788
789 if (usb_nevents <= 0)
790 return (0);
791 ueq = SIMPLEQ_FIRST(&usb_events);
792 #ifdef DIAGNOSTIC
793 if (ueq == NULL) {
794 printf("usb: usb_nevents got out of sync! %d\n", usb_nevents);
795 usb_nevents = 0;
796 return (0);
797 }
798 #endif
799 if (ue)
800 *ue = ueq->ue;
801 SIMPLEQ_REMOVE_HEAD(&usb_events, next);
802 usb_free_event((struct usb_event *)(void *)ueq);
803 usb_nevents--;
804 return (1);
805 }
806
807 void
808 usbd_add_dev_event(int type, usbd_device_handle udev)
809 {
810 struct usb_event *ue = usb_alloc_event();
811
812 usbd_fill_deviceinfo(udev, &ue->u.ue_device, USB_EVENT_IS_ATTACH(type));
813 usb_add_event(type, ue);
814 }
815
816 void
817 usbd_add_drv_event(int type, usbd_device_handle udev, device_ptr_t dev)
818 {
819 struct usb_event *ue = usb_alloc_event();
820
821 ue->u.ue_driver.ue_cookie = udev->cookie;
822 strncpy(ue->u.ue_driver.ue_devname, USBDEVPTRNAME(dev),
823 sizeof ue->u.ue_driver.ue_devname);
824 usb_add_event(type, ue);
825 }
826
827 Static struct usb_event *
828 usb_alloc_event(void)
829 {
830 /* Yes, this is right; we allocate enough so that we can use it later */
831 return malloc(sizeof(struct usb_event_q), M_USBDEV, M_WAITOK|M_ZERO);
832 }
833
834 Static void
835 usb_free_event(struct usb_event *uep)
836 {
837 free(uep, M_USBDEV);
838 }
839
840 Static void
841 usb_add_event(int type, struct usb_event *uep)
842 {
843 struct usb_event_q *ueq;
844 struct timeval thetime;
845 int s;
846
847 microtime(&thetime);
848 /* Don't want to wait here inside splusb() */
849 ueq = (struct usb_event_q *)(void *)uep;
850 ueq->ue = *uep;
851 ueq->ue.ue_type = type;
852 TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
853
854 s = splusb();
855 if (++usb_nevents >= USB_MAX_EVENTS) {
856 /* Too many queued events, drop an old one. */
857 DPRINTFN(-1,("usb: event dropped\n"));
858 (void)usb_get_next_event(0);
859 }
860 SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next);
861 wakeup(&usb_events);
862 selnotify(&usb_selevent, 0);
863 if (usb_async_proc != NULL) {
864 mutex_enter(&proclist_mutex);
865 psignal(usb_async_proc, SIGIO);
866 mutex_exit(&proclist_mutex);
867 }
868 splx(s);
869 }
870
871 void
872 usb_schedsoftintr(usbd_bus_handle bus)
873 {
874 DPRINTFN(10,("usb_schedsoftintr: polling=%d\n", bus->use_polling));
875 #ifdef USB_USE_SOFTINTR
876 if (bus->use_polling) {
877 bus->methods->soft_intr(bus);
878 } else {
879 softint_schedule(bus->soft);
880 }
881 #else
882 bus->methods->soft_intr(bus);
883 #endif /* USB_USE_SOFTINTR */
884 }
885
886 int
887 usb_activate(device_ptr_t self, enum devact act)
888 {
889 struct usb_softc *sc = (struct usb_softc *)self;
890 usbd_device_handle dev = sc->sc_port.device;
891 int i, rv = 0;
892
893 switch (act) {
894 case DVACT_ACTIVATE:
895 return (EOPNOTSUPP);
896
897 case DVACT_DEACTIVATE:
898 sc->sc_dying = 1;
899 if (dev != NULL && dev->cdesc != NULL && dev->subdevs != NULL) {
900 for (i = 0; dev->subdevs[i]; i++)
901 rv |= config_deactivate(dev->subdevs[i]);
902 }
903 break;
904 }
905 return (rv);
906 }
907
908 int
909 usb_detach(device_ptr_t self, int flags)
910 {
911 struct usb_softc *sc = (struct usb_softc *)self;
912 struct usb_event *ue;
913
914 DPRINTF(("usb_detach: start\n"));
915
916 /* Kill off event thread. */
917 while (sc->sc_event_thread != NULL) {
918 wakeup(&sc->sc_bus->needs_explore);
919 tsleep(sc, PWAIT, "usbdet", hz * 60);
920 }
921 DPRINTF(("usb_detach: event thread dead\n"));
922
923 /* Make all devices disconnect. */
924 if (sc->sc_port.device != NULL)
925 usb_disconnect_port(&sc->sc_port, self);
926
927 #ifdef USB_USE_SOFTINTR
928 if (sc->sc_bus->soft != NULL) {
929 softint_disestablish(sc->sc_bus->soft);
930 sc->sc_bus->soft = NULL;
931 }
932 #endif
933
934 ue = usb_alloc_event();
935 ue->u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
936 usb_add_event(USB_EVENT_CTRLR_DETACH, ue);
937
938 return (0);
939 }
940
941 #ifdef COMPAT_30
942 Static void
943 usb_copy_old_devinfo(struct usb_device_info_old *uo,
944 const struct usb_device_info *ue)
945 {
946 const unsigned char *p;
947 unsigned char *q;
948 int i, n;
949
950 uo->udi_bus = ue->udi_bus;
951 uo->udi_addr = ue->udi_addr;
952 uo->udi_cookie = ue->udi_cookie;
953 for (i = 0, p = (const unsigned char *)ue->udi_product,
954 q = (unsigned char *)uo->udi_product;
955 *p && i < USB_MAX_STRING_LEN - 1; p++) {
956 if (*p < 0x80)
957 q[i++] = *p;
958 else {
959 q[i++] = '?';
960 if ((*p & 0xe0) == 0xe0)
961 p++;
962 p++;
963 }
964 }
965 q[i] = 0;
966
967 for (i = 0, p = ue->udi_vendor, q = uo->udi_vendor;
968 *p && i < USB_MAX_STRING_LEN - 1; p++) {
969 if (* p < 0x80)
970 q[i++] = *p;
971 else {
972 q[i++] = '?';
973 p++;
974 if ((*p & 0xe0) == 0xe0)
975 p++;
976 }
977 }
978 q[i] = 0;
979
980 memcpy(uo->udi_release, ue->udi_release, sizeof(uo->udi_release));
981
982 uo->udi_productNo = ue->udi_productNo;
983 uo->udi_vendorNo = ue->udi_vendorNo;
984 uo->udi_releaseNo = ue->udi_releaseNo;
985 uo->udi_class = ue->udi_class;
986 uo->udi_subclass = ue->udi_subclass;
987 uo->udi_protocol = ue->udi_protocol;
988 uo->udi_config = ue->udi_config;
989 uo->udi_speed = ue->udi_speed;
990 uo->udi_power = ue->udi_power;
991 uo->udi_nports = ue->udi_nports;
992
993 for (n=0; n<USB_MAX_DEVNAMES; n++)
994 memcpy(uo->udi_devnames[n],
995 ue->udi_devnames[n], USB_MAX_DEVNAMELEN);
996 memcpy(uo->udi_ports, ue->udi_ports, sizeof(uo->udi_ports));
997 }
998 #endif
999