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