1 /* $NetBSD: uhid.c,v 1.39 2000/06/01 14:29:00 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 = 0; 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 free(sc->sc_repdesc, M_USBDEV); 312 313 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 314 USBDEV(sc->sc_dev)); 315 316 return (0); 317 } 318 319 void 320 uhid_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) 321 { 322 struct uhid_softc *sc = addr; 323 324 #ifdef UHID_DEBUG 325 if (uhiddebug > 5) { 326 u_int32_t cc, i; 327 328 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 329 DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc)); 330 DPRINTF(("uhid_intr: data =")); 331 for (i = 0; i < cc; i++) 332 DPRINTF((" %02x", sc->sc_ibuf[i])); 333 DPRINTF(("\n")); 334 } 335 #endif 336 337 if (status == USBD_CANCELLED) 338 return; 339 340 if (status != USBD_NORMAL_COMPLETION) { 341 DPRINTF(("uhid_intr: status=%d\n", status)); 342 sc->sc_state |= UHID_NEEDCLEAR; 343 return; 344 } 345 346 (void) b_to_q(sc->sc_ibuf, sc->sc_isize, &sc->sc_q); 347 348 if (sc->sc_state & UHID_ASLP) { 349 sc->sc_state &= ~UHID_ASLP; 350 DPRINTFN(5, ("uhid_intr: waking %p\n", sc)); 351 wakeup(&sc->sc_q); 352 } 353 selwakeup(&sc->sc_rsel); 354 if (sc->sc_async != NULL) { 355 DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async)); 356 psignal(sc->sc_async, SIGIO); 357 } 358 } 359 360 int 361 uhidopen(dev_t dev, int flag, int mode, struct proc *p) 362 { 363 struct uhid_softc *sc; 364 usbd_status err; 365 366 USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc); 367 368 DPRINTF(("uhidopen: sc=%p\n", sc)); 369 370 if (sc->sc_dying) 371 return (ENXIO); 372 373 if (sc->sc_state & UHID_OPEN) 374 return (EBUSY); 375 sc->sc_state |= UHID_OPEN; 376 377 if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) { 378 sc->sc_state &= ~UHID_OPEN; 379 return (ENOMEM); 380 } 381 382 sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); 383 sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK); 384 385 /* Set up interrupt pipe. */ 386 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, 387 USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf, 388 sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL); 389 if (err) { 390 DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " 391 "error=%d\n",err)); 392 free(sc->sc_ibuf, M_USBDEV); 393 free(sc->sc_obuf, M_USBDEV); 394 sc->sc_state &= ~UHID_OPEN; 395 return (EIO); 396 } 397 398 sc->sc_state &= ~UHID_IMMED; 399 400 sc->sc_async = 0; 401 402 return (0); 403 } 404 405 int 406 uhidclose(dev_t dev, int flag, int mode, struct proc *p) 407 { 408 struct uhid_softc *sc; 409 410 USB_GET_SC(uhid, UHIDUNIT(dev), sc); 411 412 DPRINTF(("uhidclose: sc=%p\n", sc)); 413 414 /* Disable interrupts. */ 415 usbd_abort_pipe(sc->sc_intrpipe); 416 usbd_close_pipe(sc->sc_intrpipe); 417 sc->sc_intrpipe = 0; 418 419 clfree(&sc->sc_q); 420 421 free(sc->sc_ibuf, M_USBDEV); 422 free(sc->sc_obuf, M_USBDEV); 423 424 sc->sc_state &= ~UHID_OPEN; 425 426 sc->sc_async = 0; 427 428 return (0); 429 } 430 431 int 432 uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag) 433 { 434 int s; 435 int error = 0; 436 size_t length; 437 u_char buffer[UHID_CHUNK]; 438 usbd_status err; 439 440 DPRINTFN(1, ("uhidread\n")); 441 if (sc->sc_state & UHID_IMMED) { 442 DPRINTFN(1, ("uhidread immed\n")); 443 444 err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, 445 sc->sc_iid, buffer, sc->sc_isize); 446 if (err) 447 return (EIO); 448 return (uiomove(buffer, sc->sc_isize, uio)); 449 } 450 451 s = splusb(); 452 while (sc->sc_q.c_cc == 0) { 453 if (flag & IO_NDELAY) { 454 splx(s); 455 return (EWOULDBLOCK); 456 } 457 sc->sc_state |= UHID_ASLP; 458 DPRINTFN(5, ("uhidread: sleep on %p\n", sc)); 459 error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0); 460 DPRINTFN(5, ("uhidread: woke, error=%d\n", error)); 461 if (sc->sc_dying) 462 error = EIO; 463 if (error) { 464 sc->sc_state &= ~UHID_ASLP; 465 break; 466 } 467 if (sc->sc_state & UHID_NEEDCLEAR) { 468 DPRINTFN(-1,("uhidread: clearing stall\n")); 469 sc->sc_state &= ~UHID_NEEDCLEAR; 470 usbd_clear_endpoint_stall(sc->sc_intrpipe); 471 } 472 } 473 splx(s); 474 475 /* Transfer as many chunks as possible. */ 476 while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) { 477 length = min(sc->sc_q.c_cc, uio->uio_resid); 478 if (length > sizeof(buffer)) 479 length = sizeof(buffer); 480 481 /* Remove a small chunk from the input queue. */ 482 (void) q_to_b(&sc->sc_q, buffer, length); 483 DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length)); 484 485 /* Copy the data to the user process. */ 486 if ((error = uiomove(buffer, length, uio)) != 0) 487 break; 488 } 489 490 return (error); 491 } 492 493 int 494 uhidread(dev_t dev, struct uio *uio, int flag) 495 { 496 struct uhid_softc *sc; 497 int error; 498 499 USB_GET_SC(uhid, UHIDUNIT(dev), sc); 500 501 sc->sc_refcnt++; 502 error = uhid_do_read(sc, uio, flag); 503 if (--sc->sc_refcnt < 0) 504 usb_detach_wakeup(USBDEV(sc->sc_dev)); 505 return (error); 506 } 507 508 int 509 uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag) 510 { 511 int error; 512 int size; 513 usbd_status err; 514 515 DPRINTFN(1, ("uhidwrite\n")); 516 517 if (sc->sc_dying) 518 return (EIO); 519 520 size = sc->sc_osize; 521 error = 0; 522 if (uio->uio_resid != size) 523 return (EINVAL); 524 error = uiomove(sc->sc_obuf, size, uio); 525 if (!error) { 526 if (sc->sc_oid) 527 err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, 528 sc->sc_obuf[0], sc->sc_obuf+1, size-1); 529 else 530 err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, 531 0, sc->sc_obuf, size); 532 if (err) 533 error = EIO; 534 } 535 536 return (error); 537 } 538 539 int 540 uhidwrite(dev_t dev, struct uio *uio, int flag) 541 { 542 struct uhid_softc *sc; 543 int error; 544 545 USB_GET_SC(uhid, UHIDUNIT(dev), sc); 546 547 sc->sc_refcnt++; 548 error = uhid_do_write(sc, uio, flag); 549 if (--sc->sc_refcnt < 0) 550 usb_detach_wakeup(USBDEV(sc->sc_dev)); 551 return (error); 552 } 553 554 int 555 uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, 556 int flag, struct proc *p) 557 { 558 struct usb_ctl_report_desc *rd; 559 struct usb_ctl_report *re; 560 int size, id; 561 usbd_status err; 562 563 DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); 564 565 if (sc->sc_dying) 566 return (EIO); 567 568 switch (cmd) { 569 case FIONBIO: 570 /* All handled in the upper FS layer. */ 571 break; 572 573 case FIOASYNC: 574 if (*(int *)addr) { 575 if (sc->sc_async != NULL) 576 return (EBUSY); 577 sc->sc_async = p; 578 DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", p)); 579 } else 580 sc->sc_async = NULL; 581 break; 582 583 /* XXX this is not the most general solution. */ 584 case TIOCSPGRP: 585 if (sc->sc_async == NULL) 586 return (EINVAL); 587 if (*(int *)addr != sc->sc_async->p_pgid) 588 return (EPERM); 589 break; 590 591 case USB_GET_REPORT_DESC: 592 rd = (struct usb_ctl_report_desc *)addr; 593 size = min(sc->sc_repdesc_size, sizeof rd->data); 594 rd->size = size; 595 memcpy(rd->data, sc->sc_repdesc, size); 596 break; 597 598 case USB_SET_IMMED: 599 if (*(int *)addr) { 600 /* XXX should read into ibuf, but does it matter? */ 601 err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, 602 sc->sc_iid, sc->sc_ibuf, sc->sc_isize); 603 if (err) 604 return (EOPNOTSUPP); 605 606 sc->sc_state |= UHID_IMMED; 607 } else 608 sc->sc_state &= ~UHID_IMMED; 609 break; 610 611 case USB_GET_REPORT: 612 re = (struct usb_ctl_report *)addr; 613 switch (re->report) { 614 case UHID_INPUT_REPORT: 615 size = sc->sc_isize; 616 id = sc->sc_iid; 617 break; 618 case UHID_OUTPUT_REPORT: 619 size = sc->sc_osize; 620 id = sc->sc_oid; 621 break; 622 case UHID_FEATURE_REPORT: 623 size = sc->sc_fsize; 624 id = sc->sc_fid; 625 break; 626 default: 627 return (EINVAL); 628 } 629 err = usbd_get_report(sc->sc_iface, re->report, id, re->data, 630 size); 631 if (err) 632 return (EIO); 633 break; 634 635 case USB_SET_REPORT: 636 re = (struct usb_ctl_report *)addr; 637 switch (re->report) { 638 case UHID_INPUT_REPORT: 639 size = sc->sc_isize; 640 id = sc->sc_iid; 641 break; 642 case UHID_OUTPUT_REPORT: 643 size = sc->sc_osize; 644 id = sc->sc_oid; 645 break; 646 case UHID_FEATURE_REPORT: 647 size = sc->sc_fsize; 648 id = sc->sc_fid; 649 break; 650 default: 651 return (EINVAL); 652 } 653 err = usbd_set_report(sc->sc_iface, re->report, id, re->data, 654 size); 655 if (err) 656 return (EIO); 657 break; 658 659 default: 660 return (EINVAL); 661 } 662 return (0); 663 } 664 665 int 666 uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 667 { 668 struct uhid_softc *sc; 669 int error; 670 671 USB_GET_SC(uhid, UHIDUNIT(dev), sc); 672 673 sc->sc_refcnt++; 674 error = uhid_do_ioctl(sc, cmd, addr, flag, p); 675 if (--sc->sc_refcnt < 0) 676 usb_detach_wakeup(USBDEV(sc->sc_dev)); 677 return (error); 678 } 679 680 int 681 uhidpoll(dev_t dev, int events, struct proc *p) 682 { 683 struct uhid_softc *sc; 684 int revents = 0; 685 int s; 686 687 USB_GET_SC(uhid, UHIDUNIT(dev), sc); 688 689 if (sc->sc_dying) 690 return (EIO); 691 692 s = splusb(); 693 if (events & (POLLOUT | POLLWRNORM)) 694 revents |= events & (POLLOUT | POLLWRNORM); 695 if (events & (POLLIN | POLLRDNORM)) { 696 if (sc->sc_q.c_cc > 0) 697 revents |= events & (POLLIN | POLLRDNORM); 698 else 699 selrecord(p, &sc->sc_rsel); 700 } 701 702 splx(s); 703 return (revents); 704 } 705 706 #if defined(__FreeBSD__) 707 DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0); 708 #endif 709