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