xref: /openbsd-src/sys/dev/usb/usb.c (revision 589e08aa702d75a34159ae4f7d5f9dcb955916c9)
1 /*	$OpenBSD: usb.c,v 1.7 1999/11/11 15:57:40 ho Exp $	*/
2 /*	$NetBSD: usb.c,v 1.28 1999/10/13 08:10:57 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 #endif
60 #include <sys/conf.h>
61 #include <sys/poll.h>
62 #include <sys/proc.h>
63 #include <sys/select.h>
64 #include <sys/vnode.h>
65 #include <sys/signalvar.h>
66 
67 #include <dev/usb/usb.h>
68 #include <dev/usb/usbdi.h>
69 #include <dev/usb/usbdi_util.h>
70 
71 #define USB_DEV_MINOR 255
72 
73 #if defined(__FreeBSD__)
74 MALLOC_DEFINE(M_USB, "USB", "USB");
75 MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device");
76 MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller");
77 
78 #include "usb_if.h"
79 #endif /* defined(__FreeBSD__) */
80 
81 #include <machine/bus.h>
82 
83 #include <dev/usb/usbdivar.h>
84 #include <dev/usb/usb_quirks.h>
85 
86 #ifdef USB_DEBUG
87 #define DPRINTF(x)	if (usbdebug) logprintf x
88 #define DPRINTFN(n,x)	if (usbdebug>(n)) logprintf x
89 int	usbdebug = 0;
90 int	uhcidebug;
91 int	ohcidebug;
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 selinfo	sc_consel;	/* waiting for connect change */
104 	struct proc    *sc_event_thread;
105 
106 	char		sc_dying;
107 };
108 
109 #if defined(__NetBSD__) || defined(__OpenBSD__)
110 cdev_decl(usb);
111 #elif defined(__FreeBSD__)
112 d_open_t  usbopen;
113 d_close_t usbclose;
114 d_ioctl_t usbioctl;
115 int usbpoll __P((dev_t, int, struct proc *));
116 
117 struct cdevsw usb_cdevsw = {
118 	/* open */      usbopen,
119 	/* close */     usbclose,
120 	/* read */      noread,
121 	/* write */     nowrite,
122 	/* ioctl */     usbioctl,
123 	/* poll */      usbpoll,
124 	/* mmap */      nommap,
125 	/* strategy */  nostrategy,
126 	/* name */      "usb",
127 	/* maj */       USB_CDEV_MAJOR,
128 	/* dump */      nodump,
129 	/* psize */     nopsize,
130 	/* flags */     0,
131 	/* bmaj */      -1
132 };
133 #endif
134 
135 usbd_status usb_discover __P((struct usb_softc *));
136 void	usb_create_event_thread __P((void *));
137 void	usb_event_thread __P((void *));
138 
139 #define USB_MAX_EVENTS 50
140 struct usb_event_q {
141 	struct usb_event ue;
142 	SIMPLEQ_ENTRY(usb_event_q) next;
143 };
144 SIMPLEQ_HEAD(, usb_event_q) usb_events = SIMPLEQ_HEAD_INITIALIZER(usb_events);
145 int usb_nevents = 0;
146 struct selinfo usb_selevent;
147 struct proc *usb_async_proc;  /* process who wants USB SIGIO */
148 int usb_dev_open = 0;
149 
150 int usb_get_next_event __P((struct usb_event *));
151 
152 /* Flag to see if we are in the cold boot process. */
153 extern int cold;
154 
155 USB_DECLARE_DRIVER(usb);
156 
157 USB_MATCH(usb)
158 {
159 	DPRINTF(("usbd_match\n"));
160 	return (UMATCH_GENERIC);
161 }
162 
163 USB_ATTACH(usb)
164 {
165 #if defined(__NetBSD__) || defined(__OpenBSD__)
166 	struct usb_softc *sc = (struct usb_softc *)self;
167 #elif defined(__FreeBSD__)
168 	struct usb_softc *sc = device_get_softc(self);
169 	void *aux = device_get_ivars(self);
170 #endif
171 	usbd_device_handle dev;
172 	usbd_status r;
173 
174 #if defined(__NetBSD__) || defined(__OpenBSD__)
175 	printf("\n");
176 #elif defined(__FreeBSD__)
177 	sc->sc_dev = self;
178 #endif
179 
180 	DPRINTF(("usbd_attach\n"));
181 	usbd_init();
182 	sc->sc_bus = aux;
183 	sc->sc_bus->usbctl = sc;
184 	sc->sc_port.power = USB_MAX_POWER;
185 	r = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0,
186 			    &sc->sc_port);
187 
188 	if (r == USBD_NORMAL_COMPLETION) {
189 		dev = sc->sc_port.device;
190 		if (!dev->hub) {
191 			sc->sc_dying = 1;
192 			printf("%s: root device is not a hub\n",
193 			       USBDEVNAME(sc->sc_dev));
194 			USB_ATTACH_ERROR_RETURN;
195 		}
196 		sc->sc_bus->root_hub = dev;
197 #if 0
198 		/*
199 		 * Turning this code off will delay attachment of USB devices
200 		 * until the USB event thread is running, which means that
201 		 * the keyboard will not work until after cold boot.
202 		 */
203 		if (cold) {
204 			sc->sc_bus->use_polling++;
205 			dev->hub->explore(sc->sc_bus->root_hub);
206 			sc->sc_bus->use_polling--;
207 		}
208 #endif
209 	} else {
210 		printf("%s: root hub problem, error=%d\n",
211 		       USBDEVNAME(sc->sc_dev), r);
212 		sc->sc_dying = 1;
213 	}
214 
215 #if defined(__NetBSD__)
216 	kthread_create(usb_create_event_thread, sc);
217 #elif defined(__OpenBSD__)
218 	kthread_create_deferred(usb_create_event_thread, sc);
219 #endif
220 
221 #if defined(__FreeBSD__)
222 	make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR,
223 		 0644, "usb%d", device_get_unit(self));
224 #endif
225 
226 	USB_ATTACH_SUCCESS_RETURN;
227 }
228 
229 #if defined(__NetBSD__) || defined(__OpenBSD__)
230 void
231 usb_create_event_thread(arg)
232 	void *arg;
233 {
234 	struct usb_softc *sc = arg;
235 
236 #if defined(__NetBSD__)
237 	if (kthread_create1(usb_event_thread, sc, &sc->sc_event_thread,
238 #else
239 	if (kthread_create(usb_event_thread, sc, &sc->sc_event_thread,
240 #endif
241 			   "%s", sc->sc_dev.dv_xname)) {
242 		printf("%s: unable to create event thread for\n",
243 		       sc->sc_dev.dv_xname);
244 		panic("usb_create_event_thread");
245 	}
246 }
247 
248 void
249 usb_event_thread(arg)
250 	void *arg;
251 {
252 	struct usb_softc *sc = arg;
253 
254 	DPRINTF(("usb_event_thread: start\n"));
255 
256 	while (!sc->sc_dying) {
257 #ifdef USB_DEBUG
258 		if (!usb_noexplore)
259 #endif
260 		usb_discover(sc);
261 		(void)tsleep(&sc->sc_bus->needs_explore,
262 			     PWAIT, "usbevt", hz*60);
263 		DPRINTFN(2,("usb_event_thread: woke up\n"));
264 	}
265 	sc->sc_event_thread = 0;
266 
267 	/* In case parent is waiting for us to exit. */
268 	wakeup(sc);
269 
270 	DPRINTF(("usb_event_thread: exit\n"));
271 	kthread_exit(0);
272 }
273 
274 int
275 usbctlprint(aux, pnp)
276 	void *aux;
277 	const char *pnp;
278 {
279 	/* only "usb"es can attach to host controllers */
280 	if (pnp)
281 		printf("usb at %s", pnp);
282 
283 	return (UNCONF);
284 }
285 #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
286 
287 int
288 usbopen(dev, flag, mode, p)
289 	dev_t dev;
290 	int flag, mode;
291 	struct proc *p;
292 {
293 	int unit = minor(dev);
294 	struct usb_softc *sc;
295 
296 	if (unit == USB_DEV_MINOR) {
297 		if (usb_dev_open)
298 			return (EBUSY);
299 		usb_dev_open = 1;
300 		usb_async_proc = 0;
301 		return (0);
302 	}
303 
304 	USB_GET_SC_OPEN(usb, unit, sc);
305 
306 	if (sc->sc_dying)
307 		return (EIO);
308 
309 	return (0);
310 }
311 
312 int
313 usbread(dev, uio, flag)
314 	dev_t dev;
315 	struct uio *uio;
316 	int flag;
317 {
318 	struct usb_event ue;
319 	int s, error, n;
320 
321 	if (minor(dev) != USB_DEV_MINOR)
322 		return (ENXIO);
323 
324 	if (uio->uio_resid != sizeof(struct usb_event))
325 		return (EINVAL);
326 
327 	error = 0;
328 	s = splusb();
329 	for (;;) {
330 		n = usb_get_next_event(&ue);
331 		if (n != 0)
332 			break;
333 		if (flag & IO_NDELAY) {
334 			error = EWOULDBLOCK;
335 			break;
336 		}
337 		error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0);
338 		if (error)
339 			break;
340 	}
341 	splx(s);
342 	if (!error)
343 		error = uiomove((caddr_t)&ue, uio->uio_resid, uio);
344 
345 	return (error);
346 }
347 
348 int
349 usbclose(dev, flag, mode, p)
350 	dev_t dev;
351 	int flag, mode;
352 	struct proc *p;
353 {
354 	int unit = minor(dev);
355 
356 	if (unit == USB_DEV_MINOR) {
357 		usb_async_proc = 0;
358 		usb_dev_open = 0;
359 	}
360 
361 	return (0);
362 }
363 
364 int
365 usbioctl(devt, cmd, data, flag, p)
366 	dev_t devt;
367 	u_long cmd;
368 	caddr_t data;
369 	int flag;
370 	struct proc *p;
371 {
372 	struct usb_softc *sc;
373 	int unit = minor(devt);
374 
375 	if (unit == USB_DEV_MINOR) {
376 		switch (cmd) {
377 		case FIONBIO:
378 			/* All handled in the upper FS layer. */
379 			return (0);
380 
381 		case FIOASYNC:
382 			if (*(int *)data)
383 				usb_async_proc = p;
384 			else
385 				usb_async_proc = 0;
386 			return (0);
387 
388 		default:
389 			return (EINVAL);
390 		}
391 	}
392 
393 	USB_GET_SC(usb, unit, sc);
394 
395 	if (sc->sc_dying)
396 		return (EIO);
397 
398 	switch (cmd) {
399 #if defined(__FreeBSD__)
400   	case USB_DISCOVER:
401   		usb_discover(sc);
402   		break;
403 #endif
404 #ifdef USB_DEBUG
405 	case USB_SETDEBUG:
406 		usbdebug = uhcidebug = ohcidebug = *(int *)data;
407 		break;
408 #endif
409 	case USB_REQUEST:
410 	{
411 		struct usb_ctl_request *ur = (void *)data;
412 		int len = UGETW(ur->request.wLength);
413 		struct iovec iov;
414 		struct uio uio;
415 		void *ptr = 0;
416 		int addr = ur->addr;
417 		usbd_status r;
418 		int error = 0;
419 
420 		DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
421 		if (len < 0 || len > 32768)
422 			return (EINVAL);
423 		if (addr < 0 || addr >= USB_MAX_DEVICES ||
424 		    sc->sc_bus->devices[addr] == 0)
425 			return (EINVAL);
426 		if (len != 0) {
427 			iov.iov_base = (caddr_t)ur->data;
428 			iov.iov_len = len;
429 			uio.uio_iov = &iov;
430 			uio.uio_iovcnt = 1;
431 			uio.uio_resid = len;
432 			uio.uio_offset = 0;
433 			uio.uio_segflg = UIO_USERSPACE;
434 			uio.uio_rw =
435 				ur->request.bmRequestType & UT_READ ?
436 				UIO_READ : UIO_WRITE;
437 			uio.uio_procp = p;
438 			ptr = malloc(len, M_TEMP, M_WAITOK);
439 			if (uio.uio_rw == UIO_WRITE) {
440 				error = uiomove(ptr, len, &uio);
441 				if (error)
442 					goto ret;
443 			}
444 		}
445 		r = usbd_do_request_flags(sc->sc_bus->devices[addr],
446 					  &ur->request, ptr,
447 					  ur->flags, &ur->actlen);
448 		if (r != USBD_NORMAL_COMPLETION) {
449 			error = EIO;
450 			goto ret;
451 		}
452 		if (len != 0) {
453 			if (uio.uio_rw == UIO_READ) {
454 				error = uiomove(ptr, len, &uio);
455 				if (error)
456 					goto ret;
457 			}
458 		}
459 	ret:
460 		if (ptr)
461 			free(ptr, M_TEMP);
462 		return (error);
463 	}
464 
465 	case USB_DEVICEINFO:
466 	{
467 		struct usb_device_info *di = (void *)data;
468 		int addr = di->addr;
469 		usbd_device_handle devh;
470 
471 		if (addr < 1 || addr >= USB_MAX_DEVICES)
472 			return (EINVAL);
473 		devh = sc->sc_bus->devices[addr];
474 		if (devh == 0)
475 			return (ENXIO);
476 		usbd_fill_deviceinfo(devh, di);
477 		break;
478 	}
479 
480 	case USB_DEVICESTATS:
481 		*(struct usb_device_stats *)data = sc->sc_bus->stats;
482 		break;
483 
484 	default:
485 		return (EINVAL);
486 	}
487 	return (0);
488 }
489 
490 int
491 usbpoll(dev, events, p)
492 	dev_t dev;
493 	int events;
494 	struct proc *p;
495 {
496 	int revents, mask, s;
497 
498 	if (minor(dev) != USB_DEV_MINOR)
499 		return (ENXIO);
500 
501 	revents = 0;
502 	s = splusb();
503 	mask = POLLIN | POLLRDNORM;
504 	if (events & mask)
505 		if (usb_nevents > 0)
506 			revents |= events & mask;
507 
508 	DPRINTFN(2, ("usbpoll: revents=0x%x\n", revents));
509 	if (revents == 0) {
510 		if (events & mask) {
511 			DPRINTFN(2, ("usbpoll: selrecord\n"));
512 			selrecord(p, &usb_selevent);
513 		}
514 	}
515 	splx(s);
516 	return (revents);
517 }
518 
519 /* Explore device tree from the root. */
520 usbd_status
521 usb_discover(sc)
522 	struct usb_softc *sc;
523 {
524 	/*
525 	 * We need mutual exclusion while traversing the device tree,
526 	 * but this is guaranteed since this function is only called
527 	 * from the event thread for the controller.
528 	 */
529 	do {
530 		sc->sc_bus->needs_explore = 0;
531 		sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
532 	} while (sc->sc_bus->needs_explore && !sc->sc_dying);
533 	return (USBD_NORMAL_COMPLETION);
534 }
535 
536 void
537 usb_needs_explore(bus)
538 	usbd_bus_handle bus;
539 {
540 	bus->needs_explore = 1;
541 	wakeup(&bus->needs_explore);
542 }
543 
544 /* Called at splusb() */
545 int
546 usb_get_next_event(ue)
547 	struct usb_event *ue;
548 {
549 	struct usb_event_q *ueq;
550 
551 	if (usb_nevents <= 0)
552 		return (0);
553 	ueq = SIMPLEQ_FIRST(&usb_events);
554 	*ue = ueq->ue;
555 	SIMPLEQ_REMOVE_HEAD(&usb_events, ueq, next);
556 	free(ueq, M_USBDEV);
557 	usb_nevents--;
558 	return (1);
559 }
560 
561 void
562 usbd_add_event(type, devh)
563 	int type;
564 	usbd_device_handle devh;
565 {
566 	struct usb_event_q *ueq;
567 	struct usb_event ue;
568 	struct timeval thetime;
569 	int s;
570 
571 	s = splusb();
572 	if (++usb_nevents >= USB_MAX_EVENTS) {
573 		/* Too many queued events, drop an old one. */
574 		DPRINTFN(-1,("usb: event dropped\n"));
575 		(void)usb_get_next_event(&ue);
576 	}
577 	/* Don't want to wait here inside splusb() */
578 	ueq = malloc(sizeof *ueq, M_USBDEV, M_NOWAIT);
579 	if (ueq == 0) {
580 		printf("usb: no memory, event dropped\n");
581 		splx(s);
582 		return;
583 	}
584 	ueq->ue.ue_type = type;
585 	ueq->ue.ue_cookie = devh->cookie;
586 	usbd_fill_deviceinfo(devh, &ueq->ue.ue_device);
587 	microtime(&thetime);
588 	TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
589 	SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next);
590 	wakeup(&usb_events);
591 	selwakeup(&usb_selevent);
592 	if (usb_async_proc)
593 		psignal(usb_async_proc, SIGIO);
594 	splx(s);
595 }
596 
597 #if defined(__NetBSD__) || defined(__OpenBSD__)
598 int
599 usb_activate(self, act)
600 	device_ptr_t self;
601 	enum devact act;
602 {
603 	struct usb_softc *sc = (struct usb_softc *)self;
604 	usbd_device_handle dev = sc->sc_port.device;
605 	int i, rv = 0;
606 
607 	switch (act) {
608 	case DVACT_ACTIVATE:
609 		return (EOPNOTSUPP);
610 		break;
611 
612 	case DVACT_DEACTIVATE:
613 		sc->sc_dying = 1;
614 		if (dev && dev->cdesc && dev->subdevs) {
615 			for (i = 0; dev->subdevs[i]; i++)
616 				rv |= config_deactivate(dev->subdevs[i]);
617 		}
618 		break;
619 	}
620 	return (rv);
621 }
622 
623 int
624 usb_detach(self, flags)
625 	device_ptr_t self;
626 	int flags;
627 {
628 	struct usb_softc *sc = (struct usb_softc *)self;
629 
630 	DPRINTF(("usb_detach: start\n"));
631 
632 	sc->sc_dying = 1;
633 
634 	/* Make all devices disconnect. */
635 	if (sc->sc_port.device)
636 		usb_disconnect_port(&sc->sc_port, self);
637 
638 	/* Kill off event thread. */
639 	if (sc->sc_event_thread) {
640 		wakeup(&sc->sc_bus->needs_explore);
641 		if (tsleep(sc, PWAIT, "usbdet", hz * 60))
642 			printf("%s: event thread didn't die\n",
643 			       USBDEVNAME(sc->sc_dev));
644 		DPRINTF(("usb_detach: event thread dead\n"));
645 	}
646 
647 	usbd_finish();
648 	return (0);
649 }
650 #elif defined(__FreeBSD__)
651 int
652 usb_detach(device_t self)
653 {
654 	DPRINTF(("%s: unload, prevented\n", USBDEVNAME(self)));
655 
656 	return (EINVAL);
657 }
658 #endif
659 
660 
661 #if defined(__FreeBSD__)
662 DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0);
663 DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0);
664 #endif
665