xref: /openbsd-src/sys/dev/usb/usb.c (revision ce4d70384102ffb4292ce6d5ad41a0c78ffc56f8)
1 /*	$OpenBSD: usb.c,v 1.5 1999/09/27 18:03:56 fgsch Exp $	*/
2 /*	$NetBSD: usb.c,v 1.24 1999/09/15 21:10:11 augustss Exp $	*/
3 
4 /*
5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Lennart Augustsson (augustss@carlstedt.se) at
10  * Carlstedt Research & Technology.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *        This product includes software developed by the NetBSD
23  *        Foundation, Inc. and its contributors.
24  * 4. Neither the name of The NetBSD Foundation nor the names of its
25  *    contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 /*
42  * USB specifications and other documentation can be found at
43  * http://www.usb.org/developers/data/ and
44  * http://www.usb.org/developers/index.html .
45  */
46 
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/malloc.h>
51 #if defined(__NetBSD__) || defined(__OpenBSD__)
52 #include <sys/device.h>
53 #include <sys/kthread.h>
54 #elif defined(__FreeBSD__)
55 #include <sys/module.h>
56 #include <sys/bus.h>
57 #include <sys/ioccom.h>
58 #include <sys/uio.h>
59 #include <sys/conf.h>
60 #endif
61 #include <sys/conf.h>
62 #include <sys/poll.h>
63 #include <sys/proc.h>
64 #include <sys/select.h>
65 
66 #include <dev/usb/usb.h>
67 #include <dev/usb/usbdi.h>
68 #include <dev/usb/usbdi_util.h>
69 
70 #if defined(__FreeBSD__)
71 MALLOC_DEFINE(M_USB, "USB", "USB");
72 MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device");
73 MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller");
74 
75 #include "usb_if.h"
76 #endif /* defined(__FreeBSD__) */
77 
78 #include <machine/bus.h>
79 
80 #include <dev/usb/usbdivar.h>
81 #include <dev/usb/usb_quirks.h>
82 
83 #ifdef USB_DEBUG
84 #define DPRINTF(x)	if (usbdebug) logprintf x
85 #define DPRINTFN(n,x)	if (usbdebug>(n)) logprintf x
86 int	usbdebug = 0;
87 int	uhcidebug;
88 int	ohcidebug;
89 int	usb_noexplore = 0;
90 #else
91 #define DPRINTF(x)
92 #define DPRINTFN(n,x)
93 #endif
94 
95 int usb_nbus = 0;
96 
97 #define USBUNIT(dev) (minor(dev))
98 
99 struct usb_softc {
100 	USBBASEDEVICE	sc_dev;		/* base device */
101 	usbd_bus_handle sc_bus;		/* USB controller */
102 	struct usbd_port sc_port;	/* dummy port for root hub */
103 
104 	struct selinfo	sc_consel;	/* waiting for connect change */
105 	struct proc    *sc_event_thread;
106 
107 	char		sc_dying;
108 };
109 
110 #if defined(__NetBSD__) || defined(__OpenBSD__)
111 cdev_decl(usb);
112 #elif defined(__FreeBSD__)
113 d_open_t  usbopen;
114 d_close_t usbclose;
115 d_ioctl_t usbioctl;
116 int usbpoll __P((dev_t, int, struct proc *));
117 
118 struct cdevsw usb_cdevsw = {
119 	usbopen,     usbclose,    noread,         nowrite,
120 	usbioctl,    nullstop,    nullreset,      nodevtotty,
121 	usbpoll,     nommap,      nostrat,
122 	"usb",        NULL,   -1
123 };
124 #endif
125 
126 usbd_status usb_discover __P((struct usb_softc *));
127 void	usb_create_event_thread __P((void *));
128 void	usb_event_thread __P((void *));
129 
130 /* Flag to see if we are in the cold boot process. */
131 extern int cold;
132 
133 USB_DECLARE_DRIVER_INIT(usb, DEVMETHOD(bus_print_child, usbd_print_child));
134 
135 USB_MATCH(usb)
136 {
137 	DPRINTF(("usbd_match\n"));
138 	return (UMATCH_GENERIC);
139 }
140 
141 USB_ATTACH(usb)
142 {
143 #if defined(__NetBSD__) || defined(__OpenBSD__)
144 	struct usb_softc *sc = (struct usb_softc *)self;
145 #elif defined(__FreeBSD__)
146 	struct usb_softc *sc = device_get_softc(self);
147 	void *aux = device_get_ivars(self);
148 #endif
149 	usbd_device_handle dev;
150 	usbd_status r;
151 
152 #if defined(__NetBSD__) || defined(__OpenBSD__)
153 	printf("\n");
154 #elif defined(__FreeBSD__)
155 	sc->sc_dev = self;
156 #endif
157 
158 	DPRINTF(("usbd_attach\n"));
159 	usbd_init();
160 	sc->sc_bus = aux;
161 	sc->sc_bus->usbctl = sc;
162 	sc->sc_port.power = USB_MAX_POWER;
163 	r = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0,
164 			    &sc->sc_port);
165 
166 	if (r == USBD_NORMAL_COMPLETION) {
167 		dev = sc->sc_port.device;
168 		if (!dev->hub) {
169 			sc->sc_dying = 1;
170 			printf("%s: root device is not a hub\n",
171 			       USBDEVNAME(sc->sc_dev));
172 			USB_ATTACH_ERROR_RETURN;
173 		}
174 		sc->sc_bus->root_hub = dev;
175 #if 1
176 		/*
177 		 * Turning this code off will delay attachment of USB devices
178 		 * until the USB event thread is running, which means that
179 		 * the keyboard will not work until after cold boot.
180 		 */
181 		if (cold) {
182 			sc->sc_bus->use_polling++;
183 			dev->hub->explore(sc->sc_bus->root_hub);
184 			sc->sc_bus->use_polling--;
185 		}
186 #endif
187 	} else {
188 		printf("%s: root hub problem, error=%d\n",
189 		       USBDEVNAME(sc->sc_dev), r);
190 		sc->sc_dying = 1;
191 	}
192 
193 #if defined(__OpenBSD__)
194 	kthread_create_deferred(usb_create_event_thread, sc);
195 #else
196 	kthread_create(usb_create_event_thread, sc);
197 #endif
198 
199 	usb_nbus++;
200 	USB_ATTACH_SUCCESS_RETURN;
201 }
202 
203 void
204 usb_create_event_thread(arg)
205 	void *arg;
206 {
207 	struct usb_softc *sc = arg;
208 
209 #if !defined(__OpenBSD__)
210 	if (kthread_create1(usb_event_thread, sc, &sc->sc_event_thread,
211 #else
212 	if (kthread_create(usb_event_thread, sc, &sc->sc_event_thread,
213 #endif
214 			   "%s", sc->sc_dev.dv_xname)) {
215 		printf("%s: unable to create event thread for\n",
216 		       sc->sc_dev.dv_xname);
217 		panic("usb_create_event_thread");
218 	}
219 }
220 
221 void
222 usb_event_thread(arg)
223 	void *arg;
224 {
225 	struct usb_softc *sc = arg;
226 
227 	while (!sc->sc_dying) {
228 #ifdef USB_DEBUG
229 		if (!usb_noexplore)
230 #endif
231 		usb_discover(sc);
232 		(void)tsleep(&sc->sc_bus->needs_explore,
233 			     PWAIT, "usbevt", hz*60);
234 		DPRINTFN(2,("usb_event_thread: woke up\n"));
235 	}
236 	sc->sc_event_thread = 0;
237 
238 	/* In case parent is waiting for us to exit. */
239 	wakeup(sc);
240 
241 	kthread_exit(0);
242 }
243 
244 #if defined(__NetBSD__) || defined(__OpenBSD__)
245 int
246 usbctlprint(aux, pnp)
247 	void *aux;
248 	const char *pnp;
249 {
250 	/* only "usb"es can attach to host controllers */
251 	if (pnp)
252 		printf("usb at %s", pnp);
253 
254 	return (UNCONF);
255 }
256 #endif
257 
258 int
259 usbopen(dev, flag, mode, p)
260 	dev_t dev;
261 	int flag, mode;
262 	struct proc *p;
263 {
264 	USB_GET_SC_OPEN(usb, USBUNIT(dev), sc);
265 
266 	if (sc == 0)
267 		return (ENXIO);
268 	if (sc->sc_dying)
269 		return (EIO);
270 
271 	return (0);
272 }
273 
274 int
275 usbclose(dev, flag, mode, p)
276 	dev_t dev;
277 	int flag, mode;
278 	struct proc *p;
279 {
280 	return (0);
281 }
282 
283 int
284 usbioctl(dev, cmd, data, flag, p)
285 	dev_t dev;
286 	u_long cmd;
287 	caddr_t data;
288 	int flag;
289 	struct proc *p;
290 {
291 	USB_GET_SC(usb, USBUNIT(dev), sc);
292 
293 	if (sc->sc_dying)
294 		return (EIO);
295 
296 	switch (cmd) {
297 #ifdef USB_DEBUG
298 	case USB_SETDEBUG:
299 		usbdebug = uhcidebug = ohcidebug = *(int *)data;
300 		break;
301 #endif
302 	case USB_REQUEST:
303 	{
304 		struct usb_ctl_request *ur = (void *)data;
305 		int len = UGETW(ur->request.wLength);
306 		struct iovec iov;
307 		struct uio uio;
308 		void *ptr = 0;
309 		int addr = ur->addr;
310 		usbd_status r;
311 		int error = 0;
312 
313 		DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
314 		if (len < 0 || len > 32768)
315 			return (EINVAL);
316 		if (addr < 0 || addr >= USB_MAX_DEVICES ||
317 		    sc->sc_bus->devices[addr] == 0)
318 			return (EINVAL);
319 		if (len != 0) {
320 			iov.iov_base = (caddr_t)ur->data;
321 			iov.iov_len = len;
322 			uio.uio_iov = &iov;
323 			uio.uio_iovcnt = 1;
324 			uio.uio_resid = len;
325 			uio.uio_offset = 0;
326 			uio.uio_segflg = UIO_USERSPACE;
327 			uio.uio_rw =
328 				ur->request.bmRequestType & UT_READ ?
329 				UIO_READ : UIO_WRITE;
330 			uio.uio_procp = p;
331 			ptr = malloc(len, M_TEMP, M_WAITOK);
332 			if (uio.uio_rw == UIO_WRITE) {
333 				error = uiomove(ptr, len, &uio);
334 				if (error)
335 					goto ret;
336 			}
337 		}
338 		r = usbd_do_request_flags(sc->sc_bus->devices[addr],
339 					  &ur->request, ptr,
340 					  ur->flags, &ur->actlen);
341 		if (r != USBD_NORMAL_COMPLETION) {
342 			error = EIO;
343 			goto ret;
344 		}
345 		if (len != 0) {
346 			if (uio.uio_rw == UIO_READ) {
347 				error = uiomove(ptr, len, &uio);
348 				if (error)
349 					goto ret;
350 			}
351 		}
352 	ret:
353 		if (ptr)
354 			free(ptr, M_TEMP);
355 		return (error);
356 	}
357 
358 	case USB_DEVICEINFO:
359 	{
360 		struct usb_device_info *di = (void *)data;
361 		int addr = di->addr;
362 		usbd_device_handle dev;
363 
364 		if (addr < 1 || addr >= USB_MAX_DEVICES)
365 			return (EINVAL);
366 		dev = sc->sc_bus->devices[addr];
367 		if (dev == 0)
368 			return (ENXIO);
369 		usbd_fill_deviceinfo(dev, di);
370 		break;
371 	}
372 
373 	case USB_DEVICESTATS:
374 		*(struct usb_device_stats *)data = sc->sc_bus->stats;
375 		break;
376 
377 	default:
378 		return (ENXIO);
379 	}
380 	return (0);
381 }
382 
383 int
384 usbpoll(dev, events, p)
385 	dev_t dev;
386 	int events;
387 	struct proc *p;
388 {
389 	int revents, s;
390 	USB_GET_SC(usb, USBUNIT(dev), sc);
391 
392 	if (sc->sc_dying)
393 		return (EIO);
394 
395 	DPRINTFN(2, ("usbpoll: sc=%p events=0x%x\n", sc, events));
396 	s = splusb();
397 	revents = 0;
398 	if (events & (POLLOUT | POLLWRNORM))
399 		if (sc->sc_bus->needs_explore)
400 			revents |= events & (POLLOUT | POLLWRNORM);
401 	DPRINTFN(2, ("usbpoll: revents=0x%x\n", revents));
402 	if (revents == 0) {
403 		if (events & (POLLOUT | POLLWRNORM)) {
404 			DPRINTFN(2, ("usbpoll: selrecord\n"));
405 			selrecord(p, &sc->sc_consel);
406 		}
407 	}
408 	splx(s);
409 	return (revents);
410 }
411 
412 /* Explore device tree from the root. */
413 usbd_status
414 usb_discover(sc)
415 	struct usb_softc *sc;
416 {
417 	/*
418 	 * We need mutual exclusion while traversing the device tree,
419 	 * but this is guaranteed since this function is only called
420 	 * from the event thread for the controller.
421 	 */
422 	do {
423 		sc->sc_bus->needs_explore = 0;
424 		sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
425 	} while (sc->sc_bus->needs_explore && !sc->sc_dying);
426 	return (USBD_NORMAL_COMPLETION);
427 }
428 
429 void
430 usb_needs_explore(bus)
431 	usbd_bus_handle bus;
432 {
433 	bus->needs_explore = 1;
434 	selwakeup(&bus->usbctl->sc_consel);
435 	wakeup(&bus->needs_explore);
436 }
437 
438 int
439 usb_activate(self, act)
440 	device_ptr_t self;
441 	enum devact act;
442 {
443 	struct usb_softc *sc = (struct usb_softc *)self;
444 	usbd_device_handle dev = sc->sc_port.device;
445 	int i, rv = 0;
446 
447 	switch (act) {
448 	case DVACT_ACTIVATE:
449 		return (EOPNOTSUPP);
450 		break;
451 
452 	case DVACT_DEACTIVATE:
453 		sc->sc_dying = 1;
454 		if (dev && dev->cdesc && dev->subdevs) {
455 			for (i = 0; dev->subdevs[i]; i++)
456 				rv |= config_deactivate(dev->subdevs[i]);
457 		}
458 		break;
459 	}
460 	return (rv);
461 }
462 
463 int
464 usb_detach(self, flags)
465 	device_ptr_t self;
466 	int flags;
467 {
468 	struct usb_softc *sc = (struct usb_softc *)self;
469 
470 	sc->sc_dying = 1;
471 
472 	/* Make all devices disconnect. */
473 	if (sc->sc_port.device)
474 		usb_disconnect_port(&sc->sc_port);
475 
476 	/* Kill off event thread. */
477 	if (sc->sc_event_thread) {
478 		wakeup(&sc->sc_bus->needs_explore);
479 		if (tsleep(sc, PWAIT, "usbdet", hz * 60))
480 			printf("%s: event thread didn't die\n",
481 			       USBDEVNAME(sc->sc_dev));
482 	}
483 
484 	usb_nbus--;
485 	return (0);
486 }
487 
488 int
489 usbread(dev, uio, flag)
490 	dev_t dev;
491 	struct uio *uio;
492 	int flag;
493 {
494 	/* XXX */
495 	return (0);
496 }
497 
498 #if defined(__FreeBSD__)
499 DRIVER_MODULE(usb, root, usb_driver, usb_devclass, 0, 0);
500 #endif
501