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