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