xref: /netbsd-src/sys/dev/usb/uhid.c (revision 95d875fb90b1458e4f1de6950286ddcd6644bc61)
1 /*	$NetBSD: uhid.c,v 1.29 1999/12/18 22:47:11 augustss Exp $	*/
2 /*	$FreeBSD: src/sys/dev/usb/uhid.c,v 1.22 1999/11/17 22:33:43 n_hibma 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  * HID spec: http://www.usb.org/developers/data/usbhid10.pdf
43  */
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #if defined(__NetBSD__) || defined(__OpenBSD__)
50 #include <sys/device.h>
51 #include <sys/ioctl.h>
52 #elif defined(__FreeBSD__)
53 #include <sys/ioccom.h>
54 #include <sys/filio.h>
55 #include <sys/module.h>
56 #include <sys/bus.h>
57 #include <sys/ioccom.h>
58 #endif
59 #include <sys/conf.h>
60 #include <sys/tty.h>
61 #include <sys/file.h>
62 #include <sys/select.h>
63 #include <sys/proc.h>
64 #include <sys/vnode.h>
65 #include <sys/poll.h>
66 
67 #include <dev/usb/usb.h>
68 #include <dev/usb/usbhid.h>
69 
70 #include <dev/usb/usbdi.h>
71 #include <dev/usb/usbdi_util.h>
72 #include <dev/usb/hid.h>
73 #include <dev/usb/usb_quirks.h>
74 
75 #ifdef UHID_DEBUG
76 #define DPRINTF(x)	if (uhiddebug) logprintf x
77 #define DPRINTFN(n,x)	if (uhiddebug>(n)) logprintf x
78 int	uhiddebug = 0;
79 #else
80 #define DPRINTF(x)
81 #define DPRINTFN(n,x)
82 #endif
83 
84 struct uhid_softc {
85 	USBBASEDEVICE sc_dev;			/* base device */
86 	usbd_interface_handle sc_iface;	/* interface */
87 	usbd_pipe_handle sc_intrpipe;	/* interrupt pipe */
88 	int sc_ep_addr;
89 
90 	int sc_isize;
91 	int sc_osize;
92 	int sc_fsize;
93 	u_int8_t sc_iid;
94 	u_int8_t sc_oid;
95 	u_int8_t sc_fid;
96 
97 	char *sc_ibuf;
98 	char *sc_obuf;
99 
100 	void *sc_repdesc;
101 	int sc_repdesc_size;
102 
103 	struct clist sc_q;
104 	struct selinfo sc_rsel;
105 	u_char sc_state;	/* driver state */
106 #define	UHID_OPEN	0x01	/* device is open */
107 #define	UHID_ASLP	0x02	/* waiting for device data */
108 #define UHID_NEEDCLEAR	0x04	/* needs clearing endpoint stall */
109 #define UHID_IMMED	0x08	/* return read data immediately */
110 
111 	int sc_refcnt;
112 	u_char sc_dying;
113 };
114 
115 #define	UHIDUNIT(dev)	(minor(dev))
116 #define	UHID_CHUNK	128	/* chunk size for read */
117 #define	UHID_BSIZE	1020	/* buffer size */
118 
119 #if defined(__NetBSD__) || defined(__OpenBSD__)
120 cdev_decl(uhid);
121 #elif defined(__FreeBSD__)
122 d_open_t	uhidopen;
123 d_close_t	uhidclose;
124 d_read_t	uhidread;
125 d_write_t	uhidwrite;
126 d_ioctl_t	uhidioctl;
127 d_poll_t	uhidpoll;
128 
129 #define		UHID_CDEV_MAJOR 122
130 
131 static struct cdevsw uhid_cdevsw = {
132 	/* open */	uhidopen,
133 	/* close */	uhidclose,
134 	/* read */	uhidread,
135 	/* write */	uhidwrite,
136 	/* ioctl */	uhidioctl,
137 	/* poll */	uhidpoll,
138 	/* mmap */	nommap,
139 	/* strategy */	nostrategy,
140 	/* name */	"uhid",
141 	/* maj */	UHID_CDEV_MAJOR,
142 	/* dump */	nodump,
143 	/* psize */	nopsize,
144 	/* flags */	0,
145 	/* bmaj */	-1
146 };
147 #endif
148 
149 static void uhid_intr __P((usbd_xfer_handle, usbd_private_handle,
150 			   usbd_status));
151 
152 static int uhid_do_read __P((struct uhid_softc *, struct uio *uio, int));
153 static int uhid_do_write __P((struct uhid_softc *, struct uio *uio, int));
154 static int uhid_do_ioctl __P((struct uhid_softc *, u_long, caddr_t, int,
155 			      struct proc *));
156 
157 USB_DECLARE_DRIVER(uhid);
158 
159 USB_MATCH(uhid)
160 {
161 	USB_MATCH_START(uhid, uaa);
162 	usb_interface_descriptor_t *id;
163 
164 	if (uaa->iface == NULL)
165 		return (UMATCH_NONE);
166 	id = usbd_get_interface_descriptor(uaa->iface);
167 	if (id == NULL || id->bInterfaceClass != UCLASS_HID)
168 		return (UMATCH_NONE);
169 	return (UMATCH_IFACECLASS_GENERIC);
170 }
171 
172 USB_ATTACH(uhid)
173 {
174 	USB_ATTACH_START(uhid, sc, uaa);
175 	usbd_interface_handle iface = uaa->iface;
176 	usb_interface_descriptor_t *id;
177 	usb_endpoint_descriptor_t *ed;
178 	int size;
179 	void *desc;
180 	usbd_status err;
181 	char devinfo[1024];
182 
183 	sc->sc_iface = iface;
184 	id = usbd_get_interface_descriptor(iface);
185 	usbd_devinfo(uaa->device, 0, devinfo);
186 	USB_ATTACH_SETUP;
187 	printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
188 	       devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
189 
190 	ed = usbd_interface2endpoint_descriptor(iface, 0);
191 	if (ed == NULL) {
192 		printf("%s: could not read endpoint descriptor\n",
193 		       USBDEVNAME(sc->sc_dev));
194 		sc->sc_dying = 1;
195 		USB_ATTACH_ERROR_RETURN;
196 	}
197 
198 	DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d "
199 		     "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
200 		     " bInterval=%d\n",
201 		     ed->bLength, ed->bDescriptorType,
202 		     ed->bEndpointAddress & UE_ADDR,
203 		     UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
204 		     ed->bmAttributes & UE_XFERTYPE,
205 		     UGETW(ed->wMaxPacketSize), ed->bInterval));
206 
207 	if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
208 	    (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
209 		printf("%s: unexpected endpoint\n", USBDEVNAME(sc->sc_dev));
210 		sc->sc_dying = 1;
211 		USB_ATTACH_ERROR_RETURN;
212 	}
213 
214 	sc->sc_ep_addr = ed->bEndpointAddress;
215 
216 	desc = 0;
217 	err = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV);
218 	if (err) {
219 		printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));
220 		sc->sc_dying = 1;
221 		if (desc != NULL)
222 			free(desc, M_USBDEV);
223 		USB_ATTACH_ERROR_RETURN;
224 	}
225 
226 	(void)usbd_set_idle(iface, 0, 0);
227 
228 	sc->sc_isize = hid_report_size(desc, size, hid_input,   &sc->sc_iid);
229 	sc->sc_osize = hid_report_size(desc, size, hid_output,  &sc->sc_oid);
230 	sc->sc_fsize = hid_report_size(desc, size, hid_feature, &sc->sc_fid);
231 
232 	sc->sc_repdesc = desc;
233 	sc->sc_repdesc_size = size;
234 
235 #ifdef __FreeBSD__
236 	{
237 		static int global_init_done = 0;
238 
239 		if (!global_init_done) {
240 			cdevsw_add(&uhid_cdevsw);
241 			global_init_done = 1;
242 		}
243 	}
244 #endif
245 
246 	USB_ATTACH_SUCCESS_RETURN;
247 }
248 
249 #if defined(__NetBSD__) || defined(__OpenBSD__)
250 int
251 uhid_activate(self, act)
252 	device_ptr_t self;
253 	enum devact act;
254 {
255 	struct uhid_softc *sc = (struct uhid_softc *)self;
256 
257 	switch (act) {
258 	case DVACT_ACTIVATE:
259 		return (EOPNOTSUPP);
260 		break;
261 
262 	case DVACT_DEACTIVATE:
263 		sc->sc_dying = 1;
264 		break;
265 	}
266 	return (0);
267 }
268 #endif
269 
270 USB_DETACH(uhid)
271 {
272 	USB_DETACH_START(uhid, sc);
273 	int s;
274 #if defined(__NetBSD__) || defined(__OpenBSD__)
275 	int maj, mn;
276 
277 	DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags));
278 #else
279 	DPRINTF(("uhid_detach: sc=%p\n", sc));
280 #endif
281 
282 	sc->sc_dying = 1;
283 	if (sc->sc_intrpipe != NULL)
284 		usbd_abort_pipe(sc->sc_intrpipe);
285 
286 	if (sc->sc_state & UHID_OPEN) {
287 		s = splusb();
288 		if (--sc->sc_refcnt >= 0) {
289 			/* Wake everyone */
290 			wakeup(&sc->sc_q);
291 			/* Wait for processes to go away. */
292 			usb_detach_wait(USBDEV(sc->sc_dev));
293 		}
294 		splx(s);
295 	}
296 
297 #if defined(__NetBSD__) || defined(__OpenBSD__)
298 	/* locate the major number */
299 	for (maj = 0; maj < nchrdev; maj++)
300 		if (cdevsw[maj].d_open == uhidopen)
301 			break;
302 
303 	/* Nuke the vnodes for any open instances (calls close). */
304 	mn = self->dv_unit;
305 	vdevgone(maj, mn, mn, VCHR);
306 #elif defined(__FreeBSD__)
307 	/* XXX not implemented yet */
308 #endif
309 
310 	free(sc->sc_repdesc, M_USBDEV);
311 
312 	return (0);
313 }
314 
315 void
316 uhid_intr(xfer, addr, status)
317 	usbd_xfer_handle xfer;
318 	usbd_private_handle addr;
319 	usbd_status status;
320 {
321 	struct uhid_softc *sc = addr;
322 
323 	DPRINTFN(5, ("uhid_intr: status=%d\n", status));
324 	DPRINTFN(5, ("uhid_intr: data = %02x %02x %02x\n",
325 		     sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2]));
326 
327 	if (status == USBD_CANCELLED)
328 		return;
329 
330 	if (status != USBD_NORMAL_COMPLETION) {
331 		DPRINTF(("uhid_intr: status=%d\n", status));
332 		sc->sc_state |= UHID_NEEDCLEAR;
333 		return;
334 	}
335 
336 	(void) b_to_q(sc->sc_ibuf, sc->sc_isize, &sc->sc_q);
337 
338 	if (sc->sc_state & UHID_ASLP) {
339 		sc->sc_state &= ~UHID_ASLP;
340 		DPRINTFN(5, ("uhid_intr: waking %p\n", sc));
341 		wakeup(&sc->sc_q);
342 	}
343 	selwakeup(&sc->sc_rsel);
344 }
345 
346 int
347 uhidopen(dev, flag, mode, p)
348 	dev_t dev;
349 	int flag;
350 	int mode;
351 	struct proc *p;
352 {
353 	struct uhid_softc *sc;
354 	usbd_status err;
355 
356 	USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);
357 
358 	DPRINTF(("uhidopen: sc=%p\n", sc));
359 
360 	if (sc->sc_dying)
361 		return (ENXIO);
362 
363 	if (sc->sc_state & UHID_OPEN)
364 		return (EBUSY);
365 	sc->sc_state |= UHID_OPEN;
366 
367 	if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) {
368 		sc->sc_state &= ~UHID_OPEN;
369 		return (ENOMEM);
370 	}
371 
372 	sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
373 	sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
374 
375 	/* Set up interrupt pipe. */
376 	err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
377 		  USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,
378 		  sc->sc_isize, uhid_intr);
379 	if (err) {
380 		DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
381 			 "error=%d\n",err));
382 		free(sc->sc_ibuf, M_USBDEV);
383 		free(sc->sc_obuf, M_USBDEV);
384 		sc->sc_state &= ~UHID_OPEN;
385 		return (EIO);
386 	}
387 
388 	sc->sc_state &= ~UHID_IMMED;
389 
390 	return (0);
391 }
392 
393 int
394 uhidclose(dev, flag, mode, p)
395 	dev_t dev;
396 	int flag;
397 	int mode;
398 	struct proc *p;
399 {
400 	struct uhid_softc *sc;
401 
402 	USB_GET_SC(uhid, UHIDUNIT(dev), sc);
403 
404 	DPRINTF(("uhidclose: sc=%p\n", sc));
405 
406 	/* Disable interrupts. */
407 	usbd_abort_pipe(sc->sc_intrpipe);
408 	usbd_close_pipe(sc->sc_intrpipe);
409 	sc->sc_intrpipe = 0;
410 
411 	clfree(&sc->sc_q);
412 
413 	free(sc->sc_ibuf, M_USBDEV);
414 	free(sc->sc_obuf, M_USBDEV);
415 
416 	sc->sc_state &= ~UHID_OPEN;
417 
418 	return (0);
419 }
420 
421 int
422 uhid_do_read(sc, uio, flag)
423 	struct uhid_softc *sc;
424 	struct uio *uio;
425 	int flag;
426 {
427 	int s;
428 	int error = 0;
429 	size_t length;
430 	u_char buffer[UHID_CHUNK];
431 	usbd_status err;
432 
433 	DPRINTFN(1, ("uhidread\n"));
434 	if (sc->sc_state & UHID_IMMED) {
435 		DPRINTFN(1, ("uhidread immed\n"));
436 
437 		err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
438 				    sc->sc_iid, buffer, sc->sc_isize);
439 		if (err)
440 			return (EIO);
441 		return (uiomove(buffer, sc->sc_isize, uio));
442 	}
443 
444 	s = splusb();
445 	while (sc->sc_q.c_cc == 0) {
446 		if (flag & IO_NDELAY) {
447 			splx(s);
448 			return (EWOULDBLOCK);
449 		}
450 		sc->sc_state |= UHID_ASLP;
451 		DPRINTFN(5, ("uhidread: sleep on %p\n", sc));
452 		error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0);
453 		DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
454 		if (sc->sc_dying)
455 			error = EIO;
456 		if (error) {
457 			sc->sc_state &= ~UHID_ASLP;
458 			break;
459 		}
460 		if (sc->sc_state & UHID_NEEDCLEAR) {
461 			DPRINTFN(-1,("uhidread: clearing stall\n"));
462 			sc->sc_state &= ~UHID_NEEDCLEAR;
463 			usbd_clear_endpoint_stall(sc->sc_intrpipe);
464 		}
465 	}
466 	splx(s);
467 
468 	/* Transfer as many chunks as possible. */
469 	while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) {
470 		length = min(sc->sc_q.c_cc, uio->uio_resid);
471 		if (length > sizeof(buffer))
472 			length = sizeof(buffer);
473 
474 		/* Remove a small chunk from the input queue. */
475 		(void) q_to_b(&sc->sc_q, buffer, length);
476 		DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length));
477 
478 		/* Copy the data to the user process. */
479 		if ((error = uiomove(buffer, length, uio)) != 0)
480 			break;
481 	}
482 
483 	return (error);
484 }
485 
486 int
487 uhidread(dev, uio, flag)
488 	dev_t dev;
489 	struct uio *uio;
490 	int flag;
491 {
492 	struct uhid_softc *sc;
493 	int error;
494 
495 	USB_GET_SC(uhid, UHIDUNIT(dev), sc);
496 
497 	sc->sc_refcnt++;
498 	error = uhid_do_read(sc, uio, flag);
499 	if (--sc->sc_refcnt < 0)
500 		usb_detach_wakeup(USBDEV(sc->sc_dev));
501 	return (error);
502 }
503 
504 int
505 uhid_do_write(sc, uio, flag)
506 	struct uhid_softc *sc;
507 	struct uio *uio;
508 	int flag;
509 {
510 	int error;
511 	int size;
512 	usbd_status err;
513 
514 	DPRINTFN(1, ("uhidwrite\n"));
515 
516 	if (sc->sc_dying)
517 		return (EIO);
518 
519 	size = sc->sc_osize;
520 	error = 0;
521 	if (uio->uio_resid != size)
522 		return (EINVAL);
523 	error = uiomove(sc->sc_obuf, size, uio);
524 	if (!error) {
525 		if (sc->sc_oid)
526 			err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
527 				  sc->sc_obuf[0], sc->sc_obuf+1, size-1);
528 		else
529 			err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
530 				  0, sc->sc_obuf, size);
531 		if (err)
532 			error = EIO;
533 	}
534 
535 	return (error);
536 }
537 
538 int
539 uhidwrite(dev, uio, flag)
540 	dev_t dev;
541 	struct uio *uio;
542 	int flag;
543 {
544 	struct uhid_softc *sc;
545 	int error;
546 
547 	USB_GET_SC(uhid, UHIDUNIT(dev), sc);
548 
549 	sc->sc_refcnt++;
550 	error = uhid_do_write(sc, uio, flag);
551 	if (--sc->sc_refcnt < 0)
552 		usb_detach_wakeup(USBDEV(sc->sc_dev));
553 	return (error);
554 }
555 
556 int
557 uhid_do_ioctl(sc, cmd, addr, flag, p)
558 	struct uhid_softc *sc;
559 	u_long cmd;
560 	caddr_t addr;
561 	int flag;
562 	struct proc *p;
563 {
564 	struct usb_ctl_report_desc *rd;
565 	struct usb_ctl_report *re;
566 	int size, id;
567 	usbd_status err;
568 
569 	DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
570 
571 	if (sc->sc_dying)
572 		return (EIO);
573 
574 	switch (cmd) {
575 	case FIONBIO:
576 		/* All handled in the upper FS layer. */
577 		break;
578 
579 	case USB_GET_REPORT_DESC:
580 		rd = (struct usb_ctl_report_desc *)addr;
581 		size = min(sc->sc_repdesc_size, sizeof rd->data);
582 		rd->size = size;
583 		memcpy(rd->data, sc->sc_repdesc, size);
584 		break;
585 
586 	case USB_SET_IMMED:
587 		if (*(int *)addr) {
588 			/* XXX should read into ibuf, but does it matter? */
589 			err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
590 				  sc->sc_iid, sc->sc_ibuf, sc->sc_isize);
591 			if (err)
592 				return (EOPNOTSUPP);
593 
594 			sc->sc_state |=  UHID_IMMED;
595 		} else
596 			sc->sc_state &= ~UHID_IMMED;
597 		break;
598 
599 	case USB_GET_REPORT:
600 		re = (struct usb_ctl_report *)addr;
601 		switch (re->report) {
602 		case UHID_INPUT_REPORT:
603 			size = sc->sc_isize;
604 			id = sc->sc_iid;
605 			break;
606 		case UHID_OUTPUT_REPORT:
607 			size = sc->sc_osize;
608 			id = sc->sc_oid;
609 			break;
610 		case UHID_FEATURE_REPORT:
611 			size = sc->sc_fsize;
612 			id = sc->sc_fid;
613 			break;
614 		default:
615 			return (EINVAL);
616 		}
617 		err = usbd_get_report(sc->sc_iface, re->report, id, re->data,
618 			  size);
619 		if (err)
620 			return (EIO);
621 		break;
622 
623 	default:
624 		return (EINVAL);
625 	}
626 	return (0);
627 }
628 
629 int
630 uhidioctl(dev, cmd, addr, flag, p)
631 	dev_t dev;
632 	u_long cmd;
633 	caddr_t addr;
634 	int flag;
635 	struct proc *p;
636 {
637 	struct uhid_softc *sc;
638 	int error;
639 
640 	USB_GET_SC(uhid, UHIDUNIT(dev), sc);
641 
642 	sc->sc_refcnt++;
643 	error = uhid_do_ioctl(sc, cmd, addr, flag, p);
644 	if (--sc->sc_refcnt < 0)
645 		usb_detach_wakeup(USBDEV(sc->sc_dev));
646 	return (error);
647 }
648 
649 int
650 uhidpoll(dev, events, p)
651 	dev_t dev;
652 	int events;
653 	struct proc *p;
654 {
655 	struct uhid_softc *sc;
656 	int revents = 0;
657 	int s;
658 
659 	USB_GET_SC(uhid, UHIDUNIT(dev), sc);
660 
661 	if (sc->sc_dying)
662 		return (EIO);
663 
664 	s = splusb();
665 	if (events & (POLLOUT | POLLWRNORM))
666 		revents |= events & (POLLOUT | POLLWRNORM);
667 	if (events & (POLLIN | POLLRDNORM)) {
668 		if (sc->sc_q.c_cc > 0)
669 			revents |= events & (POLLIN | POLLRDNORM);
670 		else
671 			selrecord(p, &sc->sc_rsel);
672 	}
673 
674 	splx(s);
675 	return (revents);
676 }
677 
678 #if defined(__FreeBSD__)
679 DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0);
680 #endif
681