1 /* $NetBSD: usb.c,v 1.119 2009/11/12 20:11:35 dyoung Exp $ */
4 * Copyright (c) 1998, 2002, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * USB specifications and other documentation can be found at
35 * http://www.usb.org/developers/docs/ and
36 * http://www.usb.org/developers/devclass_docs/
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.119 2009/11/12 20:11:35 dyoung Exp $");
42 #include "opt_compat_netbsd.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
48 #include <sys/device.h>
49 #include <sys/kthread.h>
52 #include <sys/fcntl.h>
54 #include <sys/select.h>
55 #include <sys/vnode.h>
56 #include <sys/signalvar.h>
59 #include <dev/usb/usb.h>
60 #include <dev/usb/usbdi.h>
61 #include <dev/usb/usbdi_util.h>
63 #define USB_DEV_MINOR 255
67 #include <dev/usb/usbdivar.h>
68 #include <dev/usb/usb_quirks.h>
71 #define DPRINTF(x) if (usbdebug) logprintf x
72 #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
75 * 0 - do usual exploration
76 * 1 - do not use timeout exploration
77 * >1 - do no exploration
79 int usb_noexplore
= 0;
87 USBBASEDEVICE sc_dev
; /* base device */
89 usbd_bus_handle sc_bus
; /* USB controller */
90 struct usbd_port sc_port
; /* dummy port for root hub */
92 struct lwp
*sc_event_thread
;
98 TAILQ_HEAD(, usb_task
) tasks
;
99 struct lwp
*task_thread_lwp
;
101 int taskcreated
; /* task thread exists. */
104 static struct usb_taskq usb_taskq
[USB_NUM_TASKQS
];
106 dev_type_open(usbopen
);
107 dev_type_close(usbclose
);
108 dev_type_read(usbread
);
109 dev_type_ioctl(usbioctl
);
110 dev_type_poll(usbpoll
);
111 dev_type_kqfilter(usbkqfilter
);
113 const struct cdevsw usb_cdevsw
= {
114 usbopen
, usbclose
, usbread
, nowrite
, usbioctl
,
115 nostop
, notty
, usbpoll
, nommap
, usbkqfilter
, D_OTHER
,
118 Static
void usb_discover(struct usb_softc
*);
119 Static
void usb_create_event_thread(device_t
);
120 Static
void usb_event_thread(void *);
121 Static
void usb_task_thread(void *);
123 #define USB_MAX_EVENTS 100
126 SIMPLEQ_ENTRY(usb_event_q
) next
;
128 Static
SIMPLEQ_HEAD(, usb_event_q
) usb_events
=
129 SIMPLEQ_HEAD_INITIALIZER(usb_events
);
130 Static
int usb_nevents
= 0;
131 Static
struct selinfo usb_selevent
;
132 Static usb_proc_ptr usb_async_proc
; /* process that wants USB SIGIO */
133 Static
void *usb_async_sih
;
134 Static
int usb_dev_open
= 0;
135 Static
struct usb_event
*usb_alloc_event(void);
136 Static
void usb_free_event(struct usb_event
*);
137 Static
void usb_add_event(int, struct usb_event
*);
138 Static
int usb_get_next_event(struct usb_event
*);
139 Static
void usb_async_intr(void *);
142 Static
void usb_copy_old_devinfo(struct usb_device_info_old
*, const struct usb_device_info
*);
145 Static
const char *usbrev_str
[] = USBREV_STR
;
147 static int usb_match(device_t
, cfdata_t
, void *);
148 static void usb_attach(device_t
, device_t
, void *);
149 static int usb_detach(device_t
, int);
150 static int usb_activate(device_t
, enum devact
);
151 static void usb_childdet(device_t
, device_t
);
152 static void usb_doattach(device_t
);
154 extern struct cfdriver usb_cd
;
156 CFATTACH_DECL3_NEW(usb
, sizeof(struct usb_softc
),
157 usb_match
, usb_attach
, usb_detach
, usb_activate
, NULL
, usb_childdet
,
158 DVF_DETACH_SHUTDOWN
);
161 usb_match(device_t parent
, cfdata_t match
, void *aux
)
163 DPRINTF(("usbd_match\n"));
164 return (UMATCH_GENERIC
);
168 usb_attach(device_t parent
, device_t self
, void *aux
)
170 struct usb_softc
*sc
= device_private(self
);
174 usbrev
= sc
->sc_bus
->usbrev
;
177 aprint_normal(": USB revision %s", usbrev_str
[usbrev
]);
184 aprint_error(", not supported\n");
186 USB_ATTACH_ERROR_RETURN
;
190 config_interrupts(self
, usb_doattach
);
194 usb_doattach(device_t self
)
196 static bool usb_selevent_init
; /* XXX */
197 struct usb_softc
*sc
= device_private(self
);
198 usbd_device_handle dev
;
201 struct usb_event
*ue
;
203 if (!usb_selevent_init
) {
204 selinit(&usb_selevent
);
205 usb_selevent_init
= true;
207 DPRINTF(("usbd_doattach\n"));
209 sc
->sc_bus
->usbctl
= self
;
210 sc
->sc_port
.power
= USB_MAX_POWER
;
212 switch (sc
->sc_bus
->usbrev
) {
215 speed
= USB_SPEED_FULL
;
218 speed
= USB_SPEED_HIGH
;
221 panic("usb_doattach");
224 ue
= usb_alloc_event();
225 ue
->u
.ue_ctrlr
.ue_bus
= device_unit(self
);
226 usb_add_event(USB_EVENT_CTRLR_ATTACH
, ue
);
228 #ifdef USB_USE_SOFTINTR
229 /* XXX we should have our own level */
230 sc
->sc_bus
->soft
= softint_establish(SOFTINT_NET
,
231 sc
->sc_bus
->methods
->soft_intr
, sc
->sc_bus
);
232 if (sc
->sc_bus
->soft
== NULL
) {
233 aprint_error("%s: can't register softintr\n",
236 USB_ATTACH_ERROR_RETURN
;
240 err
= usbd_new_device(self
, sc
->sc_bus
, 0, speed
, 0,
243 dev
= sc
->sc_port
.device
;
244 if (dev
->hub
== NULL
) {
246 aprint_error("%s: root device is not a hub\n",
248 USB_ATTACH_ERROR_RETURN
;
250 sc
->sc_bus
->root_hub
= dev
;
253 * Turning this code off will delay attachment of USB devices
254 * until the USB event thread is running, which means that
255 * the keyboard will not work until after cold boot.
257 if (cold
&& (device_cfdata(self
)->cf_flags
& 1))
258 dev
->hub
->explore(sc
->sc_bus
->root_hub
);
261 aprint_error("%s: root hub problem, error=%d\n",
262 device_xname(self
), err
);
266 config_pending_incr();
267 usb_create_event_thread(self
);
269 if (!pmf_device_register(self
, NULL
, NULL
))
270 aprint_error_dev(self
, "couldn't establish power handler\n");
272 usb_async_sih
= softint_establish(SOFTINT_CLOCK
| SOFTINT_MPSAFE
,
273 usb_async_intr
, NULL
);
275 USB_ATTACH_SUCCESS_RETURN
;
278 static const char *taskq_names
[] = USB_TASKQ_NAMES
;
281 usb_create_event_thread(device_t self
)
283 struct usb_softc
*sc
= device_private(self
);
284 struct usb_taskq
*taskq
;
287 if (usb_kthread_create1(PRI_NONE
, 0, NULL
, usb_event_thread
, sc
,
288 &sc
->sc_event_thread
, "%s", device_xname(self
))) {
289 printf("%s: unable to create event thread for\n",
291 panic("usb_create_event_thread");
293 for (i
= 0; i
< USB_NUM_TASKQS
; i
++) {
294 taskq
= &usb_taskq
[i
];
296 if (taskq
->taskcreated
)
299 TAILQ_INIT(&taskq
->tasks
);
300 taskq
->taskcreated
= 1;
301 taskq
->name
= taskq_names
[i
];
302 if (usb_kthread_create1(PRI_NONE
, 0, NULL
, usb_task_thread
,
303 taskq
, &taskq
->task_thread_lwp
, taskq
->name
)) {
304 printf("unable to create task thread: %s\n", taskq
->name
);
305 panic("usb_create_event_thread task");
311 * Add a task to be performed by the task thread. This function can be
312 * called from any context and the task will be executed in a process
316 usb_add_task(usbd_device_handle dev
, struct usb_task
*task
, int queue
)
318 struct usb_taskq
*taskq
;
321 taskq
= &usb_taskq
[queue
];
323 if (task
->queue
== -1) {
324 DPRINTFN(2,("usb_add_task: task=%p\n", task
));
325 TAILQ_INSERT_TAIL(&taskq
->tasks
, task
, next
);
328 DPRINTFN(3,("usb_add_task: task=%p on q\n", task
));
330 wakeup(&taskq
->tasks
);
335 usb_rem_task(usbd_device_handle dev
, struct usb_task
*task
)
337 struct usb_taskq
*taskq
;
340 taskq
= &usb_taskq
[task
->queue
];
342 if (task
->queue
!= -1) {
343 TAILQ_REMOVE(&taskq
->tasks
, task
, next
);
350 usb_event_thread(void *arg
)
352 struct usb_softc
*sc
= arg
;
354 DPRINTF(("usb_event_thread: start\n"));
357 * In case this controller is a companion controller to an
358 * EHCI controller we need to wait until the EHCI controller
359 * has grabbed the port.
360 * XXX It would be nicer to do this with a tsleep(), but I don't
361 * know how to synchronize the creation of the threads so it
364 usb_delay_ms(sc
->sc_bus
, 500);
366 /* Make sure first discover does something. */
367 sc
->sc_bus
->needs_explore
= 1;
369 config_pending_decr();
371 while (!sc
->sc_dying
) {
373 if (usb_noexplore
< 2)
377 (void)tsleep(&sc
->sc_bus
->needs_explore
, PWAIT
, "usbevt",
378 usb_noexplore
? 0 : hz
* 60);
380 (void)tsleep(&sc
->sc_bus
->needs_explore
, PWAIT
, "usbevt",
383 DPRINTFN(2,("usb_event_thread: woke up\n"));
385 sc
->sc_event_thread
= NULL
;
387 /* In case parent is waiting for us to exit. */
390 DPRINTF(("usb_event_thread: exit\n"));
395 usb_task_thread(void *arg
)
397 struct usb_task
*task
;
398 struct usb_taskq
*taskq
;
402 DPRINTF(("usb_task_thread: start taskq %s\n", taskq
->name
));
406 task
= TAILQ_FIRST(&taskq
->tasks
);
408 tsleep(&taskq
->tasks
, PWAIT
, "usbtsk", 0);
409 task
= TAILQ_FIRST(&taskq
->tasks
);
411 DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task
));
413 TAILQ_REMOVE(&taskq
->tasks
, task
, next
);
416 task
->fun(task
->arg
);
423 usbctlprint(void *aux
, const char *pnp
)
425 /* only "usb"es can attach to host controllers */
427 aprint_normal("usb at %s", pnp
);
433 usbopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
435 int unit
= minor(dev
);
436 struct usb_softc
*sc
;
438 if (unit
== USB_DEV_MINOR
) {
442 mutex_enter(proc_lock
);
444 mutex_exit(proc_lock
);
448 sc
= device_lookup_private(&usb_cd
, unit
);
459 usbread(dev_t dev
, struct uio
*uio
, int flag
)
461 struct usb_event
*ue
;
463 struct usb_event_old
*ueo
= NULL
; /* XXXGCC */
465 int s
, error
, n
, useold
;
467 if (minor(dev
) != USB_DEV_MINOR
)
471 switch (uio
->uio_resid
) {
473 case sizeof(struct usb_event_old
):
474 ueo
= malloc(sizeof(struct usb_event_old
), M_USBDEV
,
479 case sizeof(struct usb_event
):
480 ue
= usb_alloc_event();
489 n
= usb_get_next_event(ue
);
492 if (flag
& IO_NDELAY
) {
496 error
= tsleep(&usb_events
, PZERO
| PCATCH
, "usbrea", 0);
503 if (useold
) { /* copy fields to old struct */
504 ueo
->ue_type
= ue
->ue_type
;
505 memcpy(&ueo
->ue_time
, &ue
->ue_time
,
506 sizeof(struct timespec
));
507 switch (ue
->ue_type
) {
508 case USB_EVENT_DEVICE_ATTACH
:
509 case USB_EVENT_DEVICE_DETACH
:
510 usb_copy_old_devinfo(&ueo
->u
.ue_device
, &ue
->u
.ue_device
);
513 case USB_EVENT_CTRLR_ATTACH
:
514 case USB_EVENT_CTRLR_DETACH
:
515 ueo
->u
.ue_ctrlr
.ue_bus
=ue
->u
.ue_ctrlr
.ue_bus
;
518 case USB_EVENT_DRIVER_ATTACH
:
519 case USB_EVENT_DRIVER_DETACH
:
520 ueo
->u
.ue_driver
.ue_cookie
=ue
->u
.ue_driver
.ue_cookie
;
521 memcpy(ueo
->u
.ue_driver
.ue_devname
,
522 ue
->u
.ue_driver
.ue_devname
,
523 sizeof(ue
->u
.ue_driver
.ue_devname
));
529 error
= uiomove((void *)ueo
, sizeof *ueo
, uio
);
532 error
= uiomove((void *)ue
, sizeof *ue
, uio
);
544 usbclose(dev_t dev
, int flag
, int mode
,
547 int unit
= minor(dev
);
549 if (unit
== USB_DEV_MINOR
) {
550 mutex_enter(proc_lock
);
552 mutex_exit(proc_lock
);
560 usbioctl(dev_t devt
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
562 struct usb_softc
*sc
;
563 int unit
= minor(devt
);
565 if (unit
== USB_DEV_MINOR
) {
568 /* All handled in the upper FS layer. */
572 mutex_enter(proc_lock
);
574 usb_async_proc
= l
->l_proc
;
577 mutex_exit(proc_lock
);
585 sc
= device_lookup_private(&usb_cd
, unit
);
593 if (!(flag
& FWRITE
))
595 usbdebug
= ((*(int *)data
) & 0x000000ff);
597 #endif /* USB_DEBUG */
600 struct usb_ctl_request
*ur
= (void *)data
;
601 int len
= UGETW(ur
->ucr_request
.wLength
);
605 int addr
= ur
->ucr_addr
;
609 if (!(flag
& FWRITE
))
612 DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr
, len
));
613 if (len
< 0 || len
> 32768)
615 if (addr
< 0 || addr
>= USB_MAX_DEVICES
||
616 sc
->sc_bus
->devices
[addr
] == 0)
619 iov
.iov_base
= (void *)ur
->ucr_data
;
626 ur
->ucr_request
.bmRequestType
& UT_READ
?
627 UIO_READ
: UIO_WRITE
;
628 uio
.uio_vmspace
= l
->l_proc
->p_vmspace
;
629 ptr
= malloc(len
, M_TEMP
, M_WAITOK
);
630 if (uio
.uio_rw
== UIO_WRITE
) {
631 error
= uiomove(ptr
, len
, &uio
);
636 err
= usbd_do_request_flags(sc
->sc_bus
->devices
[addr
],
637 &ur
->ucr_request
, ptr
, ur
->ucr_flags
, &ur
->ucr_actlen
,
638 USBD_DEFAULT_TIMEOUT
);
643 if (len
> ur
->ucr_actlen
)
644 len
= ur
->ucr_actlen
;
646 if (uio
.uio_rw
== UIO_READ
) {
647 error
= uiomove(ptr
, len
, &uio
);
660 usbd_device_handle dev
;
661 struct usb_device_info
*di
= (void *)data
;
662 int addr
= di
->udi_addr
;
664 if (addr
< 1 || addr
>= USB_MAX_DEVICES
)
666 if ((dev
= sc
->sc_bus
->devices
[addr
]) == NULL
)
668 usbd_fill_deviceinfo(dev
, di
, 1);
673 case USB_DEVICEINFO_OLD
:
675 usbd_device_handle dev
;
676 struct usb_device_info_old
*di
= (void *)data
;
677 int addr
= di
->udi_addr
;
679 if (addr
< 1 || addr
>= USB_MAX_DEVICES
)
681 if ((dev
= sc
->sc_bus
->devices
[addr
]) == NULL
)
683 usbd_fill_deviceinfo_old(dev
, di
, 1);
688 case USB_DEVICESTATS
:
689 *(struct usb_device_stats
*)data
= sc
->sc_bus
->stats
;
699 usbpoll(dev_t dev
, int events
, struct lwp
*l
)
701 int revents
, mask
, s
;
703 if (minor(dev
) == USB_DEV_MINOR
) {
705 mask
= POLLIN
| POLLRDNORM
;
708 if (events
& mask
&& usb_nevents
> 0)
709 revents
|= events
& mask
;
710 if (revents
== 0 && events
& mask
)
711 selrecord(l
, &usb_selevent
);
721 filt_usbrdetach(struct knote
*kn
)
726 SLIST_REMOVE(&usb_selevent
.sel_klist
, kn
, knote
, kn_selnext
);
731 filt_usbread(struct knote
*kn
, long hint
)
734 if (usb_nevents
== 0)
737 kn
->kn_data
= sizeof(struct usb_event
);
741 static const struct filterops usbread_filtops
=
742 { 1, NULL
, filt_usbrdetach
, filt_usbread
};
745 usbkqfilter(dev_t dev
, struct knote
*kn
)
750 switch (kn
->kn_filter
) {
752 if (minor(dev
) != USB_DEV_MINOR
)
754 klist
= &usb_selevent
.sel_klist
;
755 kn
->kn_fop
= &usbread_filtops
;
765 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
771 /* Explore device tree from the root. */
773 usb_discover(struct usb_softc
*sc
)
776 DPRINTFN(2,("usb_discover\n"));
778 if (usb_noexplore
> 1)
782 * We need mutual exclusion while traversing the device tree,
783 * but this is guaranteed since this function is only called
784 * from the event thread for the controller.
786 while (sc
->sc_bus
->needs_explore
&& !sc
->sc_dying
) {
787 sc
->sc_bus
->needs_explore
= 0;
788 sc
->sc_bus
->root_hub
->hub
->explore(sc
->sc_bus
->root_hub
);
793 usb_needs_explore(usbd_device_handle dev
)
795 DPRINTFN(2,("usb_needs_explore\n"));
796 dev
->bus
->needs_explore
= 1;
797 wakeup(&dev
->bus
->needs_explore
);
801 usb_needs_reattach(usbd_device_handle dev
)
803 DPRINTFN(2,("usb_needs_reattach\n"));
804 dev
->powersrc
->reattach
= 1;
805 dev
->bus
->needs_explore
= 1;
806 wakeup(&dev
->bus
->needs_explore
);
809 /* Called at splusb() */
811 usb_get_next_event(struct usb_event
*ue
)
813 struct usb_event_q
*ueq
;
815 if (usb_nevents
<= 0)
817 ueq
= SIMPLEQ_FIRST(&usb_events
);
820 printf("usb: usb_nevents got out of sync! %d\n", usb_nevents
);
827 SIMPLEQ_REMOVE_HEAD(&usb_events
, next
);
828 usb_free_event((struct usb_event
*)(void *)ueq
);
834 usbd_add_dev_event(int type
, usbd_device_handle udev
)
836 struct usb_event
*ue
= usb_alloc_event();
838 usbd_fill_deviceinfo(udev
, &ue
->u
.ue_device
, USB_EVENT_IS_ATTACH(type
));
839 usb_add_event(type
, ue
);
843 usbd_add_drv_event(int type
, usbd_device_handle udev
, device_t dev
)
845 struct usb_event
*ue
= usb_alloc_event();
847 ue
->u
.ue_driver
.ue_cookie
= udev
->cookie
;
848 strncpy(ue
->u
.ue_driver
.ue_devname
, USBDEVPTRNAME(dev
),
849 sizeof ue
->u
.ue_driver
.ue_devname
);
850 usb_add_event(type
, ue
);
853 Static
struct usb_event
*
854 usb_alloc_event(void)
856 /* Yes, this is right; we allocate enough so that we can use it later */
857 return malloc(sizeof(struct usb_event_q
), M_USBDEV
, M_WAITOK
|M_ZERO
);
861 usb_free_event(struct usb_event
*uep
)
867 usb_add_event(int type
, struct usb_event
*uep
)
869 struct usb_event_q
*ueq
;
870 struct timeval thetime
;
874 /* Don't want to wait here inside splusb() */
875 ueq
= (struct usb_event_q
*)(void *)uep
;
877 ueq
->ue
.ue_type
= type
;
878 TIMEVAL_TO_TIMESPEC(&thetime
, &ueq
->ue
.ue_time
);
881 if (++usb_nevents
>= USB_MAX_EVENTS
) {
882 /* Too many queued events, drop an old one. */
883 DPRINTFN(-1,("usb: event dropped\n"));
884 (void)usb_get_next_event(0);
886 SIMPLEQ_INSERT_TAIL(&usb_events
, ueq
, next
);
888 selnotify(&usb_selevent
, 0, 0);
889 if (usb_async_proc
!= NULL
) {
890 softint_schedule(usb_async_sih
);
896 usb_async_intr(void *cookie
)
900 mutex_enter(proc_lock
);
901 if ((proc
= usb_async_proc
) != NULL
)
902 psignal(proc
, SIGIO
);
903 mutex_exit(proc_lock
);
907 usb_schedsoftintr(usbd_bus_handle bus
)
909 DPRINTFN(10,("usb_schedsoftintr: polling=%d\n", bus
->use_polling
));
910 #ifdef USB_USE_SOFTINTR
911 if (bus
->use_polling
) {
912 bus
->methods
->soft_intr(bus
);
914 softint_schedule(bus
->soft
);
917 bus
->methods
->soft_intr(bus
);
918 #endif /* USB_USE_SOFTINTR */
922 usb_activate(device_t self
, enum devact act
)
924 struct usb_softc
*sc
= device_private(self
);
927 case DVACT_DEACTIVATE
:
936 usb_childdet(device_t self
, device_t child
)
939 struct usb_softc
*sc
= device_private(self
);
940 struct usbd_device
*dev
;
942 if ((dev
= sc
->sc_port
.device
) == NULL
|| dev
->subdevlen
== 0)
945 for (i
= 0; i
< dev
->subdevlen
; i
++)
946 if (dev
->subdevs
[i
] == child
)
947 dev
->subdevs
[i
] = NULL
;
951 usb_detach(device_t self
, int flags
)
953 struct usb_softc
*sc
= device_private(self
);
954 struct usb_event
*ue
;
957 DPRINTF(("usb_detach: start\n"));
959 /* Make all devices disconnect. */
960 if (sc
->sc_port
.device
!= NULL
&&
961 (rc
= usb_disconnect_port(&sc
->sc_port
, self
, flags
)) != 0)
964 pmf_device_deregister(self
);
965 /* Kill off event thread. */
967 while (sc
->sc_event_thread
!= NULL
) {
968 wakeup(&sc
->sc_bus
->needs_explore
);
969 tsleep(sc
, PWAIT
, "usbdet", hz
* 60);
971 DPRINTF(("usb_detach: event thread dead\n"));
973 #ifdef USB_USE_SOFTINTR
974 if (sc
->sc_bus
->soft
!= NULL
) {
975 softint_disestablish(sc
->sc_bus
->soft
);
976 sc
->sc_bus
->soft
= NULL
;
980 ue
= usb_alloc_event();
981 ue
->u
.ue_ctrlr
.ue_bus
= device_unit(self
);
982 usb_add_event(USB_EVENT_CTRLR_DETACH
, ue
);
989 usb_copy_old_devinfo(struct usb_device_info_old
*uo
,
990 const struct usb_device_info
*ue
)
992 const unsigned char *p
;
996 uo
->udi_bus
= ue
->udi_bus
;
997 uo
->udi_addr
= ue
->udi_addr
;
998 uo
->udi_cookie
= ue
->udi_cookie
;
999 for (i
= 0, p
= (const unsigned char *)ue
->udi_product
,
1000 q
= (unsigned char *)uo
->udi_product
;
1001 *p
&& i
< USB_MAX_STRING_LEN
- 1; p
++) {
1006 if ((*p
& 0xe0) == 0xe0)
1013 for (i
= 0, p
= ue
->udi_vendor
, q
= uo
->udi_vendor
;
1014 *p
&& i
< USB_MAX_STRING_LEN
- 1; p
++) {
1020 if ((*p
& 0xe0) == 0xe0)
1026 memcpy(uo
->udi_release
, ue
->udi_release
, sizeof(uo
->udi_release
));
1028 uo
->udi_productNo
= ue
->udi_productNo
;
1029 uo
->udi_vendorNo
= ue
->udi_vendorNo
;
1030 uo
->udi_releaseNo
= ue
->udi_releaseNo
;
1031 uo
->udi_class
= ue
->udi_class
;
1032 uo
->udi_subclass
= ue
->udi_subclass
;
1033 uo
->udi_protocol
= ue
->udi_protocol
;
1034 uo
->udi_config
= ue
->udi_config
;
1035 uo
->udi_speed
= ue
->udi_speed
;
1036 uo
->udi_power
= ue
->udi_power
;
1037 uo
->udi_nports
= ue
->udi_nports
;
1039 for (n
=0; n
<USB_MAX_DEVNAMES
; n
++)
1040 memcpy(uo
->udi_devnames
[n
],
1041 ue
->udi_devnames
[n
], USB_MAX_DEVNAMELEN
);
1042 memcpy(uo
->udi_ports
, ue
->udi_ports
, sizeof(uo
->udi_ports
));