1 /* $OpenBSD: uhid.c,v 1.42 2008/06/26 05:42:18 ray Exp $ */ 2 /* $NetBSD: uhid.c,v 1.57 2003/03/11 16:44:00 augustss 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 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 #include <sys/signalvar.h> 43 #include <sys/device.h> 44 #include <sys/ioctl.h> 45 #include <sys/conf.h> 46 #include <sys/tty.h> 47 #include <sys/file.h> 48 #include <sys/selinfo.h> 49 #include <sys/proc.h> 50 #include <sys/vnode.h> 51 #include <sys/poll.h> 52 53 #include <dev/usb/usb.h> 54 #include <dev/usb/usbhid.h> 55 56 #include <dev/usb/usbdevs.h> 57 #include <dev/usb/usbdi.h> 58 #include <dev/usb/usbdi_util.h> 59 #include <dev/usb/hid.h> 60 #include <dev/usb/usb_quirks.h> 61 62 #include <dev/usb/uhidev.h> 63 64 #ifdef UHID_DEBUG 65 #define DPRINTF(x) do { if (uhiddebug) printf x; } while (0) 66 #define DPRINTFN(n,x) do { if (uhiddebug>(n)) printf x; } while (0) 67 int uhiddebug = 0; 68 #else 69 #define DPRINTF(x) 70 #define DPRINTFN(n,x) 71 #endif 72 73 struct uhid_softc { 74 struct uhidev sc_hdev; 75 76 int sc_isize; 77 int sc_osize; 78 int sc_fsize; 79 80 u_char *sc_obuf; 81 82 struct clist sc_q; 83 struct selinfo sc_rsel; 84 struct proc *sc_async; /* process that wants SIGIO */ 85 u_char sc_state; /* driver state */ 86 #define UHID_ASLP 0x01 /* waiting for device data */ 87 #define UHID_IMMED 0x02 /* return read data immediately */ 88 89 int sc_refcnt; 90 u_char sc_dying; 91 }; 92 93 #define UHIDUNIT(dev) (minor(dev)) 94 #define UHID_CHUNK 128 /* chunk size for read */ 95 #define UHID_BSIZE 1020 /* buffer size */ 96 97 void uhid_intr(struct uhidev *, void *, u_int len); 98 99 int uhid_do_read(struct uhid_softc *, struct uio *uio, int); 100 int uhid_do_write(struct uhid_softc *, struct uio *uio, int); 101 int uhid_do_ioctl(struct uhid_softc*, u_long, caddr_t, int, 102 struct proc *); 103 104 int uhid_match(struct device *, void *, void *); 105 void uhid_attach(struct device *, struct device *, void *); 106 int uhid_detach(struct device *, int); 107 int uhid_activate(struct device *, enum devact); 108 109 struct cfdriver uhid_cd = { 110 NULL, "uhid", DV_DULL 111 }; 112 113 const struct cfattach uhid_ca = { 114 sizeof(struct uhid_softc), 115 uhid_match, 116 uhid_attach, 117 uhid_detach, 118 uhid_activate, 119 }; 120 121 int 122 uhid_match(struct device *parent, void *match, void *aux) 123 { 124 struct usb_attach_arg *uaa = aux; 125 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; 126 127 DPRINTF(("uhid_match: report=%d\n", uha->reportid)); 128 129 if (uha->matchlvl) 130 return (uha->matchlvl); 131 return (UMATCH_IFACECLASS_GENERIC); 132 } 133 134 void 135 uhid_attach(struct device *parent, struct device *self, void *aux) 136 { 137 struct uhid_softc *sc = (struct uhid_softc *)self; 138 struct usb_attach_arg *uaa = aux; 139 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; 140 int size, repid; 141 void *desc; 142 143 sc->sc_hdev.sc_intr = uhid_intr; 144 sc->sc_hdev.sc_parent = uha->parent; 145 sc->sc_hdev.sc_report_id = uha->reportid; 146 147 uhidev_get_report_desc(uha->parent, &desc, &size); 148 repid = uha->reportid; 149 sc->sc_isize = hid_report_size(desc, size, hid_input, repid); 150 sc->sc_osize = hid_report_size(desc, size, hid_output, repid); 151 sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid); 152 153 printf(": input=%d, output=%d, feature=%d\n", 154 sc->sc_isize, sc->sc_osize, sc->sc_fsize); 155 } 156 157 int 158 uhid_activate(struct device *self, enum devact act) 159 { 160 struct uhid_softc *sc = (struct uhid_softc *)self; 161 162 switch (act) { 163 case DVACT_ACTIVATE: 164 break; 165 166 case DVACT_DEACTIVATE: 167 sc->sc_dying = 1; 168 break; 169 } 170 return (0); 171 } 172 173 int 174 uhid_detach(struct device *self, int flags) 175 { 176 struct uhid_softc *sc = (struct uhid_softc *)self; 177 int s; 178 int maj, mn; 179 180 DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags)); 181 182 sc->sc_dying = 1; 183 184 if (sc->sc_hdev.sc_state & UHIDEV_OPEN) { 185 s = splusb(); 186 if (--sc->sc_refcnt >= 0) { 187 /* Wake everyone */ 188 wakeup(&sc->sc_q); 189 /* Wait for processes to go away. */ 190 usb_detach_wait(&sc->sc_hdev.sc_dev); 191 } 192 splx(s); 193 } 194 195 /* locate the major number */ 196 for (maj = 0; maj < nchrdev; maj++) 197 if (cdevsw[maj].d_open == uhidopen) 198 break; 199 200 /* Nuke the vnodes for any open instances (calls close). */ 201 mn = self->dv_unit; 202 vdevgone(maj, mn, mn, VCHR); 203 204 #if 0 205 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, 206 sc->sc_hdev.sc_parent->sc_udev, 207 &sc->sc_hdev.sc_dev); 208 #endif 209 210 return (0); 211 } 212 213 void 214 uhid_intr(struct uhidev *addr, void *data, u_int len) 215 { 216 struct uhid_softc *sc = (struct uhid_softc *)addr; 217 218 #ifdef UHID_DEBUG 219 if (uhiddebug > 5) { 220 u_int32_t i; 221 222 DPRINTF(("uhid_intr: data =")); 223 for (i = 0; i < len; i++) 224 DPRINTF((" %02x", ((u_char *)data)[i])); 225 DPRINTF(("\n")); 226 } 227 #endif 228 229 (void)b_to_q(data, len, &sc->sc_q); 230 231 if (sc->sc_state & UHID_ASLP) { 232 sc->sc_state &= ~UHID_ASLP; 233 DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q)); 234 wakeup(&sc->sc_q); 235 } 236 selwakeup(&sc->sc_rsel); 237 if (sc->sc_async != NULL) { 238 DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async)); 239 psignal(sc->sc_async, SIGIO); 240 } 241 } 242 243 int 244 uhidopen(dev_t dev, int flag, int mode, struct proc *p) 245 { 246 struct uhid_softc *sc; 247 int error; 248 249 if (UHIDUNIT(dev) >= uhid_cd.cd_ndevs) 250 return (ENXIO); 251 sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; 252 if (sc == NULL) 253 return (ENXIO); 254 255 DPRINTF(("uhidopen: sc=%p\n", sc)); 256 257 if (sc->sc_dying) 258 return (ENXIO); 259 260 error = uhidev_open(&sc->sc_hdev); 261 if (error) 262 return (error); 263 264 if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) { 265 uhidev_close(&sc->sc_hdev); 266 return (ENOMEM); 267 } 268 sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK); 269 sc->sc_state &= ~UHID_IMMED; 270 sc->sc_async = NULL; 271 272 return (0); 273 } 274 275 int 276 uhidclose(dev_t dev, int flag, int mode, struct proc *p) 277 { 278 struct uhid_softc *sc; 279 280 sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; 281 282 DPRINTF(("uhidclose: sc=%p\n", sc)); 283 284 clfree(&sc->sc_q); 285 free(sc->sc_obuf, M_USBDEV); 286 sc->sc_async = NULL; 287 uhidev_close(&sc->sc_hdev); 288 289 return (0); 290 } 291 292 int 293 uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag) 294 { 295 int s; 296 int error = 0; 297 int extra; 298 size_t length; 299 u_char buffer[UHID_CHUNK]; 300 usbd_status err; 301 302 DPRINTFN(1, ("uhidread\n")); 303 if (sc->sc_state & UHID_IMMED) { 304 DPRINTFN(1, ("uhidread immed\n")); 305 extra = sc->sc_hdev.sc_report_id != 0; 306 err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT, 307 buffer, sc->sc_isize + extra); 308 if (err) 309 return (EIO); 310 return (uiomove(buffer+extra, sc->sc_isize, uio)); 311 } 312 313 s = splusb(); 314 while (sc->sc_q.c_cc == 0) { 315 if (flag & IO_NDELAY) { 316 splx(s); 317 return (EWOULDBLOCK); 318 } 319 sc->sc_state |= UHID_ASLP; 320 DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q)); 321 error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0); 322 DPRINTFN(5, ("uhidread: woke, error=%d\n", error)); 323 if (sc->sc_dying) 324 error = EIO; 325 if (error) { 326 sc->sc_state &= ~UHID_ASLP; 327 break; 328 } 329 } 330 splx(s); 331 332 /* Transfer as many chunks as possible. */ 333 while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) { 334 length = min(sc->sc_q.c_cc, uio->uio_resid); 335 if (length > sizeof(buffer)) 336 length = sizeof(buffer); 337 338 /* Remove a small chunk from the input queue. */ 339 (void) q_to_b(&sc->sc_q, buffer, length); 340 DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length)); 341 342 /* Copy the data to the user process. */ 343 if ((error = uiomove(buffer, length, uio)) != 0) 344 break; 345 } 346 347 return (error); 348 } 349 350 int 351 uhidread(dev_t dev, struct uio *uio, int flag) 352 { 353 struct uhid_softc *sc; 354 int error; 355 356 sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; 357 358 sc->sc_refcnt++; 359 error = uhid_do_read(sc, uio, flag); 360 if (--sc->sc_refcnt < 0) 361 usb_detach_wakeup(&sc->sc_hdev.sc_dev); 362 return (error); 363 } 364 365 int 366 uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag) 367 { 368 int error; 369 int size; 370 usbd_status err; 371 372 DPRINTFN(1, ("uhidwrite\n")); 373 374 if (sc->sc_dying) 375 return (EIO); 376 377 size = sc->sc_osize; 378 error = 0; 379 if (uio->uio_resid != size) 380 return (EINVAL); 381 error = uiomove(sc->sc_obuf, size, uio); 382 if (!error) { 383 err = uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, 384 sc->sc_obuf, size); 385 if (err) 386 error = EIO; 387 } 388 389 return (error); 390 } 391 392 int 393 uhidwrite(dev_t dev, struct uio *uio, int flag) 394 { 395 struct uhid_softc *sc; 396 int error; 397 398 sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; 399 400 sc->sc_refcnt++; 401 error = uhid_do_write(sc, uio, flag); 402 if (--sc->sc_refcnt < 0) 403 usb_detach_wakeup(&sc->sc_hdev.sc_dev); 404 return (error); 405 } 406 407 int 408 uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, 409 int flag, struct proc *p) 410 { 411 struct usb_ctl_report_desc *rd; 412 struct usb_ctl_report *re; 413 u_char buffer[UHID_CHUNK]; 414 int size, extra; 415 usbd_status err; 416 void *desc; 417 418 DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); 419 420 if (sc->sc_dying) 421 return (EIO); 422 423 switch (cmd) { 424 case FIONBIO: 425 /* All handled in the upper FS layer. */ 426 break; 427 428 case FIOASYNC: 429 if (*(int *)addr) { 430 if (sc->sc_async != NULL) 431 return (EBUSY); 432 sc->sc_async = p; 433 DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", p)); 434 } else 435 sc->sc_async = NULL; 436 break; 437 438 /* XXX this is not the most general solution. */ 439 case TIOCSPGRP: 440 if (sc->sc_async == NULL) 441 return (EINVAL); 442 if (*(int *)addr != sc->sc_async->p_pgid) 443 return (EPERM); 444 break; 445 446 case USB_GET_REPORT_DESC: 447 uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size); 448 rd = (struct usb_ctl_report_desc *)addr; 449 size = min(size, sizeof rd->ucrd_data); 450 rd->ucrd_size = size; 451 memcpy(rd->ucrd_data, desc, size); 452 break; 453 454 case USB_SET_IMMED: 455 if (*(int *)addr) { 456 extra = sc->sc_hdev.sc_report_id != 0; 457 err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT, 458 buffer, sc->sc_isize + extra); 459 if (err) 460 return (EOPNOTSUPP); 461 462 sc->sc_state |= UHID_IMMED; 463 } else 464 sc->sc_state &= ~UHID_IMMED; 465 break; 466 467 case USB_GET_REPORT: 468 re = (struct usb_ctl_report *)addr; 469 switch (re->ucr_report) { 470 case UHID_INPUT_REPORT: 471 size = sc->sc_isize; 472 break; 473 case UHID_OUTPUT_REPORT: 474 size = sc->sc_osize; 475 break; 476 case UHID_FEATURE_REPORT: 477 size = sc->sc_fsize; 478 break; 479 default: 480 return (EINVAL); 481 } 482 extra = sc->sc_hdev.sc_report_id != 0; 483 err = uhidev_get_report(&sc->sc_hdev, re->ucr_report, 484 re->ucr_data, size + extra); 485 if (extra) 486 memcpy(re->ucr_data, re->ucr_data+1, size); 487 if (err) 488 return (EIO); 489 break; 490 491 case USB_SET_REPORT: 492 re = (struct usb_ctl_report *)addr; 493 switch (re->ucr_report) { 494 case UHID_INPUT_REPORT: 495 size = sc->sc_isize; 496 break; 497 case UHID_OUTPUT_REPORT: 498 size = sc->sc_osize; 499 break; 500 case UHID_FEATURE_REPORT: 501 size = sc->sc_fsize; 502 break; 503 default: 504 return (EINVAL); 505 } 506 err = uhidev_set_report(&sc->sc_hdev, re->ucr_report, 507 re->ucr_data, size); 508 if (err) 509 return (EIO); 510 break; 511 512 case USB_GET_REPORT_ID: 513 *(int *)addr = sc->sc_hdev.sc_report_id; 514 break; 515 516 default: 517 return (EINVAL); 518 } 519 return (0); 520 } 521 522 int 523 uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 524 { 525 struct uhid_softc *sc; 526 int error; 527 528 sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; 529 530 sc->sc_refcnt++; 531 error = uhid_do_ioctl(sc, cmd, addr, flag, p); 532 if (--sc->sc_refcnt < 0) 533 usb_detach_wakeup(&sc->sc_hdev.sc_dev); 534 return (error); 535 } 536 537 int 538 uhidpoll(dev_t dev, int events, struct proc *p) 539 { 540 struct uhid_softc *sc; 541 int revents = 0; 542 int s; 543 544 sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; 545 546 if (sc->sc_dying) 547 return (POLLERR); 548 549 s = splusb(); 550 if (events & (POLLOUT | POLLWRNORM)) 551 revents |= events & (POLLOUT | POLLWRNORM); 552 if (events & (POLLIN | POLLRDNORM)) { 553 if (sc->sc_q.c_cc > 0) 554 revents |= events & (POLLIN | POLLRDNORM); 555 else 556 selrecord(p, &sc->sc_rsel); 557 } 558 559 splx(s); 560 return (revents); 561 } 562 563 void filt_uhidrdetach(struct knote *); 564 int filt_uhidread(struct knote *, long); 565 int uhidkqfilter(dev_t, struct knote *); 566 567 void 568 filt_uhidrdetach(struct knote *kn) 569 { 570 struct uhid_softc *sc = (void *)kn->kn_hook; 571 int s; 572 573 s = splusb(); 574 SLIST_REMOVE(&sc->sc_rsel.si_note, kn, knote, kn_selnext); 575 splx(s); 576 } 577 578 int 579 filt_uhidread(struct knote *kn, long hint) 580 { 581 struct uhid_softc *sc = (void *)kn->kn_hook; 582 583 kn->kn_data = sc->sc_q.c_cc; 584 return (kn->kn_data > 0); 585 } 586 587 struct filterops uhidread_filtops = 588 { 1, NULL, filt_uhidrdetach, filt_uhidread }; 589 590 struct filterops uhid_seltrue_filtops = 591 { 1, NULL, filt_uhidrdetach, filt_seltrue }; 592 593 int 594 uhidkqfilter(dev_t dev, struct knote *kn) 595 { 596 struct uhid_softc *sc; 597 struct klist *klist; 598 int s; 599 600 sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; 601 602 if (sc->sc_dying) 603 return (EIO); 604 605 switch (kn->kn_filter) { 606 case EVFILT_READ: 607 klist = &sc->sc_rsel.si_note; 608 kn->kn_fop = &uhidread_filtops; 609 break; 610 611 case EVFILT_WRITE: 612 klist = &sc->sc_rsel.si_note; 613 kn->kn_fop = &uhid_seltrue_filtops; 614 break; 615 616 default: 617 return (1); 618 } 619 620 kn->kn_hook = (void *)sc; 621 622 s = splusb(); 623 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 624 splx(s); 625 626 return (0); 627 } 628