1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-NetBSD 3 * 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org> 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/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #include "opt_hid.h" 42 43 #include <sys/param.h> 44 #include <sys/bus.h> 45 #include <sys/conf.h> 46 #include <sys/fcntl.h> 47 #include <sys/filio.h> 48 #include <sys/ioccom.h> 49 #include <sys/kernel.h> 50 #include <sys/lock.h> 51 #include <sys/malloc.h> 52 #include <sys/module.h> 53 #include <sys/mutex.h> 54 #include <sys/poll.h> 55 #include <sys/priv.h> 56 #include <sys/proc.h> 57 #include <sys/selinfo.h> 58 #include <sys/sysctl.h> 59 #include <sys/systm.h> 60 #include <sys/tty.h> 61 #include <sys/uio.h> 62 63 #define HID_DEBUG_VAR hidraw_debug 64 #include <dev/hid/hid.h> 65 #include <dev/hid/hidbus.h> 66 #include <dev/hid/hidraw.h> 67 68 #ifdef HID_DEBUG 69 static int hidraw_debug = 0; 70 static SYSCTL_NODE(_hw_hid, OID_AUTO, hidraw, CTLFLAG_RW, 0, 71 "HID raw interface"); 72 SYSCTL_INT(_hw_hid_hidraw, OID_AUTO, debug, CTLFLAG_RWTUN, 73 &hidraw_debug, 0, "Debug level"); 74 #endif 75 76 #define HIDRAW_INDEX 0xFF /* Arbitrary high value */ 77 78 #define HIDRAW_LOCAL_BUFSIZE 64 /* Size of on-stack buffer. */ 79 #define HIDRAW_LOCAL_ALLOC(local_buf, size) \ 80 (sizeof(local_buf) > (size) ? (local_buf) : \ 81 malloc((size), M_DEVBUF, M_ZERO | M_WAITOK)) 82 #define HIDRAW_LOCAL_FREE(local_buf, buf) \ 83 if ((local_buf) != (buf)) { \ 84 free((buf), M_DEVBUF); \ 85 } 86 87 struct hidraw_softc { 88 device_t sc_dev; /* base device */ 89 90 struct mtx sc_mtx; /* hidbus private mutex */ 91 92 struct hid_rdesc_info *sc_rdesc; 93 const struct hid_device_info *sc_hw; 94 95 uint8_t *sc_q; 96 hid_size_t *sc_qlen; 97 int sc_head; 98 int sc_tail; 99 int sc_sleepcnt; 100 101 struct selinfo sc_rsel; 102 struct proc *sc_async; /* process that wants SIGIO */ 103 struct { /* driver state */ 104 bool open:1; /* device is open */ 105 bool aslp:1; /* waiting for device data in read() */ 106 bool sel:1; /* waiting for device data in poll() */ 107 bool quiet:1; /* Ignore input data */ 108 bool immed:1; /* return read data immediately */ 109 bool uhid:1; /* driver switched in to uhid mode */ 110 bool lock:1; /* input queue sleepable lock */ 111 bool flush:1; /* do not wait for data in read() */ 112 } sc_state; 113 int sc_fflags; /* access mode for open lifetime */ 114 115 struct cdev *dev; 116 }; 117 118 static d_open_t hidraw_open; 119 static d_read_t hidraw_read; 120 static d_write_t hidraw_write; 121 static d_ioctl_t hidraw_ioctl; 122 static d_poll_t hidraw_poll; 123 static d_kqfilter_t hidraw_kqfilter; 124 125 static d_priv_dtor_t hidraw_dtor; 126 127 static struct cdevsw hidraw_cdevsw = { 128 .d_version = D_VERSION, 129 .d_open = hidraw_open, 130 .d_read = hidraw_read, 131 .d_write = hidraw_write, 132 .d_ioctl = hidraw_ioctl, 133 .d_poll = hidraw_poll, 134 .d_kqfilter = hidraw_kqfilter, 135 .d_name = "hidraw", 136 }; 137 138 static hid_intr_t hidraw_intr; 139 140 static device_identify_t hidraw_identify; 141 static device_probe_t hidraw_probe; 142 static device_attach_t hidraw_attach; 143 static device_detach_t hidraw_detach; 144 145 static int hidraw_kqread(struct knote *, long); 146 static void hidraw_kqdetach(struct knote *); 147 static void hidraw_notify(struct hidraw_softc *); 148 149 static struct filterops hidraw_filterops_read = { 150 .f_isfd = 1, 151 .f_detach = hidraw_kqdetach, 152 .f_event = hidraw_kqread, 153 }; 154 155 static void 156 hidraw_identify(driver_t *driver, device_t parent) 157 { 158 device_t child; 159 160 if (device_find_child(parent, "hidraw", -1) == NULL) { 161 child = BUS_ADD_CHILD(parent, 0, "hidraw", 162 device_get_unit(parent)); 163 if (child != NULL) 164 hidbus_set_index(child, HIDRAW_INDEX); 165 } 166 } 167 168 static int 169 hidraw_probe(device_t self) 170 { 171 172 if (hidbus_get_index(self) != HIDRAW_INDEX) 173 return (ENXIO); 174 175 hidbus_set_desc(self, "Raw HID Device"); 176 177 return (BUS_PROBE_GENERIC); 178 } 179 180 static int 181 hidraw_attach(device_t self) 182 { 183 struct hidraw_softc *sc = device_get_softc(self); 184 struct make_dev_args mda; 185 int error; 186 187 sc->sc_dev = self; 188 sc->sc_rdesc = hidbus_get_rdesc_info(self); 189 sc->sc_hw = hid_get_device_info(self); 190 191 /* Hidraw mode does not require report descriptor to work */ 192 if (sc->sc_rdesc->data == NULL || sc->sc_rdesc->len == 0) 193 device_printf(self, "no report descriptor\n"); 194 195 mtx_init(&sc->sc_mtx, "hidraw lock", NULL, MTX_DEF); 196 knlist_init_mtx(&sc->sc_rsel.si_note, &sc->sc_mtx); 197 198 make_dev_args_init(&mda); 199 mda.mda_flags = MAKEDEV_WAITOK; 200 mda.mda_devsw = &hidraw_cdevsw; 201 mda.mda_uid = UID_ROOT; 202 mda.mda_gid = GID_OPERATOR; 203 mda.mda_mode = 0600; 204 mda.mda_si_drv1 = sc; 205 206 error = make_dev_s(&mda, &sc->dev, "hidraw%d", device_get_unit(self)); 207 if (error) { 208 device_printf(self, "Can not create character device\n"); 209 hidraw_detach(self); 210 return (error); 211 } 212 #ifdef HIDRAW_MAKE_UHID_ALIAS 213 (void)make_dev_alias(sc->dev, "uhid%d", device_get_unit(self)); 214 #endif 215 216 hidbus_set_lock(self, &sc->sc_mtx); 217 hidbus_set_intr(self, hidraw_intr, sc); 218 219 return (0); 220 } 221 222 static int 223 hidraw_detach(device_t self) 224 { 225 struct hidraw_softc *sc = device_get_softc(self); 226 227 DPRINTF("sc=%p\n", sc); 228 229 if (sc->dev != NULL) { 230 mtx_lock(&sc->sc_mtx); 231 sc->dev->si_drv1 = NULL; 232 /* Wake everyone */ 233 hidraw_notify(sc); 234 mtx_unlock(&sc->sc_mtx); 235 destroy_dev(sc->dev); 236 } 237 238 knlist_clear(&sc->sc_rsel.si_note, 0); 239 knlist_destroy(&sc->sc_rsel.si_note); 240 seldrain(&sc->sc_rsel); 241 mtx_destroy(&sc->sc_mtx); 242 243 return (0); 244 } 245 246 void 247 hidraw_intr(void *context, void *buf, hid_size_t len) 248 { 249 struct hidraw_softc *sc = context; 250 int next; 251 252 DPRINTFN(5, "len=%d\n", len); 253 DPRINTFN(5, "data = %*D\n", len, buf, " "); 254 255 next = (sc->sc_tail + 1) % HIDRAW_BUFFER_SIZE; 256 if (sc->sc_state.quiet || next == sc->sc_head) 257 return; 258 259 bcopy(buf, sc->sc_q + sc->sc_tail * sc->sc_rdesc->rdsize, len); 260 261 /* Make sure we don't process old data */ 262 if (len < sc->sc_rdesc->rdsize) 263 bzero(sc->sc_q + sc->sc_tail * sc->sc_rdesc->rdsize + len, 264 sc->sc_rdesc->isize - len); 265 266 sc->sc_qlen[sc->sc_tail] = len; 267 sc->sc_tail = next; 268 269 hidraw_notify(sc); 270 } 271 272 static inline int 273 hidraw_lock_queue(struct hidraw_softc *sc, bool flush) 274 { 275 int error = 0; 276 277 mtx_assert(&sc->sc_mtx, MA_OWNED); 278 279 if (flush) 280 sc->sc_state.flush = true; 281 ++sc->sc_sleepcnt; 282 while (sc->sc_state.lock && error == 0) { 283 /* Flush is requested. Wakeup all readers and forbid sleeps */ 284 if (flush && sc->sc_state.aslp) { 285 sc->sc_state.aslp = false; 286 DPRINTFN(5, "waking %p\n", &sc->sc_q); 287 wakeup(&sc->sc_q); 288 } 289 error = mtx_sleep(&sc->sc_sleepcnt, &sc->sc_mtx, 290 PZERO | PCATCH, "hidrawio", 0); 291 } 292 --sc->sc_sleepcnt; 293 if (flush) 294 sc->sc_state.flush = false; 295 if (error == 0) 296 sc->sc_state.lock = true; 297 298 return (error); 299 } 300 301 static inline void 302 hidraw_unlock_queue(struct hidraw_softc *sc) 303 { 304 305 mtx_assert(&sc->sc_mtx, MA_OWNED); 306 KASSERT(sc->sc_state.lock, ("input buffer is not locked")); 307 308 if (sc->sc_sleepcnt != 0) 309 wakeup_one(&sc->sc_sleepcnt); 310 sc->sc_state.lock = false; 311 } 312 313 static int 314 hidraw_open(struct cdev *dev, int flag, int mode, struct thread *td) 315 { 316 struct hidraw_softc *sc; 317 int error; 318 319 sc = dev->si_drv1; 320 if (sc == NULL) 321 return (ENXIO); 322 323 DPRINTF("sc=%p\n", sc); 324 325 mtx_lock(&sc->sc_mtx); 326 if (sc->sc_state.open) { 327 mtx_unlock(&sc->sc_mtx); 328 return (EBUSY); 329 } 330 sc->sc_state.open = true; 331 mtx_unlock(&sc->sc_mtx); 332 333 error = devfs_set_cdevpriv(sc, hidraw_dtor); 334 if (error != 0) { 335 mtx_lock(&sc->sc_mtx); 336 sc->sc_state.open = false; 337 mtx_unlock(&sc->sc_mtx); 338 return (error); 339 } 340 341 sc->sc_q = malloc(sc->sc_rdesc->rdsize * HIDRAW_BUFFER_SIZE, M_DEVBUF, 342 M_ZERO | M_WAITOK); 343 sc->sc_qlen = malloc(sizeof(hid_size_t) * HIDRAW_BUFFER_SIZE, M_DEVBUF, 344 M_ZERO | M_WAITOK); 345 346 /* Set up interrupt pipe. */ 347 sc->sc_state.immed = false; 348 sc->sc_async = 0; 349 sc->sc_state.uhid = false; /* hidraw mode is default */ 350 sc->sc_state.quiet = false; 351 sc->sc_head = sc->sc_tail = 0; 352 sc->sc_fflags = flag; 353 354 hidbus_intr_start(sc->sc_dev); 355 356 return (0); 357 } 358 359 static void 360 hidraw_dtor(void *data) 361 { 362 struct hidraw_softc *sc = data; 363 364 DPRINTF("sc=%p\n", sc); 365 366 /* Disable interrupts. */ 367 hidbus_intr_stop(sc->sc_dev); 368 369 sc->sc_tail = sc->sc_head = 0; 370 sc->sc_async = 0; 371 free(sc->sc_q, M_DEVBUF); 372 free(sc->sc_qlen, M_DEVBUF); 373 sc->sc_q = NULL; 374 375 mtx_lock(&sc->sc_mtx); 376 sc->sc_state.open = false; 377 mtx_unlock(&sc->sc_mtx); 378 } 379 380 static int 381 hidraw_read(struct cdev *dev, struct uio *uio, int flag) 382 { 383 struct hidraw_softc *sc; 384 size_t length; 385 int error; 386 387 DPRINTFN(1, "\n"); 388 389 sc = dev->si_drv1; 390 if (sc == NULL) 391 return (EIO); 392 393 mtx_lock(&sc->sc_mtx); 394 error = dev->si_drv1 == NULL ? EIO : hidraw_lock_queue(sc, false); 395 if (error != 0) { 396 mtx_unlock(&sc->sc_mtx); 397 return (error); 398 } 399 400 if (sc->sc_state.immed) { 401 mtx_unlock(&sc->sc_mtx); 402 DPRINTFN(1, "immed\n"); 403 404 error = hid_get_report(sc->sc_dev, sc->sc_q, 405 sc->sc_rdesc->isize, NULL, HID_INPUT_REPORT, 406 sc->sc_rdesc->iid); 407 if (error == 0) 408 error = uiomove(sc->sc_q, sc->sc_rdesc->isize, uio); 409 mtx_lock(&sc->sc_mtx); 410 goto exit; 411 } 412 413 while (sc->sc_tail == sc->sc_head && !sc->sc_state.flush) { 414 if (flag & O_NONBLOCK) { 415 error = EWOULDBLOCK; 416 goto exit; 417 } 418 sc->sc_state.aslp = true; 419 DPRINTFN(5, "sleep on %p\n", &sc->sc_q); 420 error = mtx_sleep(&sc->sc_q, &sc->sc_mtx, PZERO | PCATCH, 421 "hidrawrd", 0); 422 DPRINTFN(5, "woke, error=%d\n", error); 423 if (dev->si_drv1 == NULL) 424 error = EIO; 425 if (error) { 426 sc->sc_state.aslp = false; 427 goto exit; 428 } 429 } 430 431 while (sc->sc_tail != sc->sc_head && uio->uio_resid > 0) { 432 length = min(uio->uio_resid, sc->sc_state.uhid ? 433 sc->sc_rdesc->isize : sc->sc_qlen[sc->sc_head]); 434 mtx_unlock(&sc->sc_mtx); 435 436 /* Copy the data to the user process. */ 437 DPRINTFN(5, "got %lu chars\n", (u_long)length); 438 error = uiomove(sc->sc_q + sc->sc_head * sc->sc_rdesc->rdsize, 439 length, uio); 440 441 mtx_lock(&sc->sc_mtx); 442 if (error != 0) 443 goto exit; 444 /* Remove a small chunk from the input queue. */ 445 sc->sc_head = (sc->sc_head + 1) % HIDRAW_BUFFER_SIZE; 446 /* 447 * In uhid mode transfer as many chunks as possible. Hidraw 448 * packets are transferred one by one due to different length. 449 */ 450 if (!sc->sc_state.uhid) 451 goto exit; 452 } 453 exit: 454 hidraw_unlock_queue(sc); 455 mtx_unlock(&sc->sc_mtx); 456 457 return (error); 458 } 459 460 static int 461 hidraw_write(struct cdev *dev, struct uio *uio, int flag) 462 { 463 uint8_t local_buf[HIDRAW_LOCAL_BUFSIZE], *buf; 464 struct hidraw_softc *sc; 465 int error; 466 int size; 467 size_t buf_offset; 468 uint8_t id = 0; 469 470 DPRINTFN(1, "\n"); 471 472 sc = dev->si_drv1; 473 if (sc == NULL) 474 return (EIO); 475 476 if (sc->sc_rdesc->osize == 0) 477 return (EOPNOTSUPP); 478 479 buf_offset = 0; 480 if (sc->sc_state.uhid) { 481 size = sc->sc_rdesc->osize; 482 if (uio->uio_resid != size) 483 return (EINVAL); 484 } else { 485 size = uio->uio_resid; 486 if (size < 2) 487 return (EINVAL); 488 /* Strip leading 0 if the device doesnt use numbered reports */ 489 error = uiomove(&id, 1, uio); 490 if (error) 491 return (error); 492 if (id != 0) 493 buf_offset++; 494 else 495 size--; 496 /* Check if underlying driver could process this request */ 497 if (size > sc->sc_rdesc->wrsize) 498 return (ENOBUFS); 499 } 500 buf = HIDRAW_LOCAL_ALLOC(local_buf, size); 501 buf[0] = id; 502 error = uiomove(buf + buf_offset, uio->uio_resid, uio); 503 if (error == 0) 504 error = hid_write(sc->sc_dev, buf, size); 505 HIDRAW_LOCAL_FREE(local_buf, buf); 506 507 return (error); 508 } 509 510 static int 511 hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, 512 struct thread *td) 513 { 514 uint8_t local_buf[HIDRAW_LOCAL_BUFSIZE]; 515 void *buf; 516 struct hidraw_softc *sc; 517 struct hidraw_gen_descriptor *hgd; 518 struct hidraw_report_descriptor *hrd; 519 struct hidraw_devinfo *hdi; 520 uint32_t size; 521 int id, len; 522 int error = 0; 523 524 DPRINTFN(2, "cmd=%lx\n", cmd); 525 526 sc = dev->si_drv1; 527 if (sc == NULL) 528 return (EIO); 529 530 /* fixed-length ioctls handling */ 531 switch (cmd) { 532 case FIONBIO: 533 /* All handled in the upper FS layer. */ 534 return (0); 535 536 case FIOASYNC: 537 mtx_lock(&sc->sc_mtx); 538 if (*(int *)addr) { 539 if (sc->sc_async == NULL) { 540 sc->sc_async = td->td_proc; 541 DPRINTF("FIOASYNC %p\n", sc->sc_async); 542 } else 543 error = EBUSY; 544 } else 545 sc->sc_async = NULL; 546 mtx_unlock(&sc->sc_mtx); 547 return (error); 548 549 /* XXX this is not the most general solution. */ 550 case TIOCSPGRP: 551 mtx_lock(&sc->sc_mtx); 552 if (sc->sc_async == NULL) 553 error = EINVAL; 554 else if (*(int *)addr != sc->sc_async->p_pgid) 555 error = EPERM; 556 mtx_unlock(&sc->sc_mtx); 557 return (error); 558 559 case HIDRAW_GET_REPORT_DESC: 560 if (sc->sc_rdesc->data == NULL || sc->sc_rdesc->len == 0) 561 return (EOPNOTSUPP); 562 mtx_lock(&sc->sc_mtx); 563 sc->sc_state.uhid = true; 564 mtx_unlock(&sc->sc_mtx); 565 hgd = (struct hidraw_gen_descriptor *)addr; 566 if (sc->sc_rdesc->len > hgd->hgd_maxlen) { 567 size = hgd->hgd_maxlen; 568 } else { 569 size = sc->sc_rdesc->len; 570 } 571 hgd->hgd_actlen = size; 572 if (hgd->hgd_data == NULL) 573 return (0); /* descriptor length only */ 574 return (copyout(sc->sc_rdesc->data, hgd->hgd_data, size)); 575 576 577 case HIDRAW_SET_REPORT_DESC: 578 if (!(sc->sc_fflags & FWRITE)) 579 return (EPERM); 580 581 /* check privileges */ 582 error = priv_check(curthread, PRIV_DRIVER); 583 if (error) 584 return (error); 585 586 /* Stop interrupts and clear input report buffer */ 587 mtx_lock(&sc->sc_mtx); 588 sc->sc_tail = sc->sc_head = 0; 589 error = hidraw_lock_queue(sc, true); 590 if (error == 0) 591 sc->sc_state.quiet = true; 592 mtx_unlock(&sc->sc_mtx); 593 if (error != 0) 594 return(error); 595 596 hgd = (struct hidraw_gen_descriptor *)addr; 597 buf = HIDRAW_LOCAL_ALLOC(local_buf, hgd->hgd_maxlen); 598 copyin(hgd->hgd_data, buf, hgd->hgd_maxlen); 599 /* Lock newbus around set_report_descr call */ 600 mtx_lock(&Giant); 601 error = hid_set_report_descr(sc->sc_dev, buf, hgd->hgd_maxlen); 602 mtx_unlock(&Giant); 603 HIDRAW_LOCAL_FREE(local_buf, buf); 604 605 /* Realloc hidraw input queue */ 606 if (error == 0) 607 sc->sc_q = realloc(sc->sc_q, 608 sc->sc_rdesc->rdsize * HIDRAW_BUFFER_SIZE, 609 M_DEVBUF, M_ZERO | M_WAITOK); 610 611 /* Start interrupts again */ 612 mtx_lock(&sc->sc_mtx); 613 sc->sc_state.quiet = false; 614 hidraw_unlock_queue(sc); 615 mtx_unlock(&sc->sc_mtx); 616 return (error); 617 case HIDRAW_SET_IMMED: 618 if (!(sc->sc_fflags & FREAD)) 619 return (EPERM); 620 if (*(int *)addr) { 621 /* XXX should read into ibuf, but does it matter? */ 622 size = sc->sc_rdesc->isize; 623 buf = HIDRAW_LOCAL_ALLOC(local_buf, size); 624 error = hid_get_report(sc->sc_dev, buf, size, NULL, 625 HID_INPUT_REPORT, sc->sc_rdesc->iid); 626 HIDRAW_LOCAL_FREE(local_buf, buf); 627 if (error) 628 return (EOPNOTSUPP); 629 630 mtx_lock(&sc->sc_mtx); 631 sc->sc_state.immed = true; 632 mtx_unlock(&sc->sc_mtx); 633 } else { 634 mtx_lock(&sc->sc_mtx); 635 sc->sc_state.immed = false; 636 mtx_unlock(&sc->sc_mtx); 637 } 638 return (0); 639 640 case HIDRAW_GET_REPORT: 641 if (!(sc->sc_fflags & FREAD)) 642 return (EPERM); 643 hgd = (struct hidraw_gen_descriptor *)addr; 644 switch (hgd->hgd_report_type) { 645 case HID_INPUT_REPORT: 646 size = sc->sc_rdesc->isize; 647 id = sc->sc_rdesc->iid; 648 break; 649 case HID_OUTPUT_REPORT: 650 size = sc->sc_rdesc->osize; 651 id = sc->sc_rdesc->oid; 652 break; 653 case HID_FEATURE_REPORT: 654 size = sc->sc_rdesc->fsize; 655 id = sc->sc_rdesc->fid; 656 break; 657 default: 658 return (EINVAL); 659 } 660 if (id != 0) 661 copyin(hgd->hgd_data, &id, 1); 662 size = MIN(hgd->hgd_maxlen, size); 663 buf = HIDRAW_LOCAL_ALLOC(local_buf, size); 664 error = hid_get_report(sc->sc_dev, buf, size, NULL, 665 hgd->hgd_report_type, id); 666 if (!error) 667 error = copyout(buf, hgd->hgd_data, size); 668 HIDRAW_LOCAL_FREE(local_buf, buf); 669 return (error); 670 671 case HIDRAW_SET_REPORT: 672 if (!(sc->sc_fflags & FWRITE)) 673 return (EPERM); 674 hgd = (struct hidraw_gen_descriptor *)addr; 675 switch (hgd->hgd_report_type) { 676 case HID_INPUT_REPORT: 677 size = sc->sc_rdesc->isize; 678 id = sc->sc_rdesc->iid; 679 break; 680 case HID_OUTPUT_REPORT: 681 size = sc->sc_rdesc->osize; 682 id = sc->sc_rdesc->oid; 683 break; 684 case HID_FEATURE_REPORT: 685 size = sc->sc_rdesc->fsize; 686 id = sc->sc_rdesc->fid; 687 break; 688 default: 689 return (EINVAL); 690 } 691 size = MIN(hgd->hgd_maxlen, size); 692 buf = HIDRAW_LOCAL_ALLOC(local_buf, size); 693 copyin(hgd->hgd_data, buf, size); 694 if (id != 0) 695 id = *(uint8_t *)buf; 696 error = hid_set_report(sc->sc_dev, buf, size, 697 hgd->hgd_report_type, id); 698 HIDRAW_LOCAL_FREE(local_buf, buf); 699 return (error); 700 701 case HIDRAW_GET_REPORT_ID: 702 *(int *)addr = 0; /* XXX: we only support reportid 0? */ 703 return (0); 704 705 case HIDIOCGRDESCSIZE: 706 *(int *)addr = sc->sc_hw->rdescsize; 707 return (0); 708 709 case HIDIOCGRDESC: 710 hrd = *(struct hidraw_report_descriptor **)addr; 711 error = copyin(&hrd->size, &size, sizeof(uint32_t)); 712 if (error) 713 return (error); 714 /* 715 * HID_MAX_DESCRIPTOR_SIZE-1 is a limit of report descriptor 716 * size in current Linux implementation. 717 */ 718 if (size >= HID_MAX_DESCRIPTOR_SIZE) 719 return (EINVAL); 720 buf = HIDRAW_LOCAL_ALLOC(local_buf, size); 721 error = hid_get_rdesc(sc->sc_dev, buf, size); 722 if (error == 0) { 723 size = MIN(size, sc->sc_rdesc->len); 724 error = copyout(buf, hrd->value, size); 725 } 726 HIDRAW_LOCAL_FREE(local_buf, buf); 727 return (error); 728 729 case HIDIOCGRAWINFO: 730 hdi = (struct hidraw_devinfo *)addr; 731 hdi->bustype = sc->sc_hw->idBus; 732 hdi->vendor = sc->sc_hw->idVendor; 733 hdi->product = sc->sc_hw->idProduct; 734 return (0); 735 } 736 737 /* variable-length ioctls handling */ 738 len = IOCPARM_LEN(cmd); 739 switch (IOCBASECMD(cmd)) { 740 case HIDIOCGRAWNAME(0): 741 strlcpy(addr, sc->sc_hw->name, len); 742 return (0); 743 744 case HIDIOCGRAWPHYS(0): 745 strlcpy(addr, device_get_nameunit(sc->sc_dev), len); 746 return (0); 747 748 case HIDIOCSFEATURE(0): 749 if (!(sc->sc_fflags & FWRITE)) 750 return (EPERM); 751 if (len < 2) 752 return (EINVAL); 753 id = *(uint8_t *)addr; 754 if (id == 0) { 755 addr = (uint8_t *)addr + 1; 756 len--; 757 } 758 return (hid_set_report(sc->sc_dev, addr, len, 759 HID_FEATURE_REPORT, id)); 760 761 case HIDIOCGFEATURE(0): 762 if (!(sc->sc_fflags & FREAD)) 763 return (EPERM); 764 if (len < 2) 765 return (EINVAL); 766 id = *(uint8_t *)addr; 767 if (id == 0) { 768 addr = (uint8_t *)addr + 1; 769 len--; 770 } 771 return (hid_get_report(sc->sc_dev, addr, len, NULL, 772 HID_FEATURE_REPORT, id)); 773 774 case HIDIOCGRAWUNIQ(0): 775 strlcpy(addr, sc->sc_hw->serial, len); 776 return (0); 777 } 778 779 return (EINVAL); 780 } 781 782 static int 783 hidraw_poll(struct cdev *dev, int events, struct thread *td) 784 { 785 struct hidraw_softc *sc; 786 int revents = 0; 787 788 sc = dev->si_drv1; 789 if (sc == NULL) 790 return (POLLHUP); 791 792 if (events & (POLLOUT | POLLWRNORM) && (sc->sc_fflags & FWRITE)) 793 revents |= events & (POLLOUT | POLLWRNORM); 794 if (events & (POLLIN | POLLRDNORM) && (sc->sc_fflags & FREAD)) { 795 mtx_lock(&sc->sc_mtx); 796 if (sc->sc_head != sc->sc_tail) 797 revents |= events & (POLLIN | POLLRDNORM); 798 else { 799 sc->sc_state.sel = true; 800 selrecord(td, &sc->sc_rsel); 801 } 802 mtx_unlock(&sc->sc_mtx); 803 } 804 805 return (revents); 806 } 807 808 static int 809 hidraw_kqfilter(struct cdev *dev, struct knote *kn) 810 { 811 struct hidraw_softc *sc; 812 813 sc = dev->si_drv1; 814 if (sc == NULL) 815 return (ENXIO); 816 817 switch(kn->kn_filter) { 818 case EVFILT_READ: 819 if (sc->sc_fflags & FREAD) { 820 kn->kn_fop = &hidraw_filterops_read; 821 break; 822 } 823 /* FALLTHROUGH */ 824 default: 825 return(EINVAL); 826 } 827 kn->kn_hook = sc; 828 829 knlist_add(&sc->sc_rsel.si_note, kn, 0); 830 return (0); 831 } 832 833 static int 834 hidraw_kqread(struct knote *kn, long hint) 835 { 836 struct hidraw_softc *sc; 837 int ret; 838 839 sc = kn->kn_hook; 840 841 mtx_assert(&sc->sc_mtx, MA_OWNED); 842 843 if (sc->dev->si_drv1 == NULL) { 844 kn->kn_flags |= EV_EOF; 845 ret = 1; 846 } else 847 ret = (sc->sc_head != sc->sc_tail) ? 1 : 0; 848 849 return (ret); 850 } 851 852 static void 853 hidraw_kqdetach(struct knote *kn) 854 { 855 struct hidraw_softc *sc; 856 857 sc = kn->kn_hook; 858 knlist_remove(&sc->sc_rsel.si_note, kn, 0); 859 } 860 861 static void 862 hidraw_notify(struct hidraw_softc *sc) 863 { 864 865 mtx_assert(&sc->sc_mtx, MA_OWNED); 866 867 if (sc->sc_state.aslp) { 868 sc->sc_state.aslp = false; 869 DPRINTFN(5, "waking %p\n", &sc->sc_q); 870 wakeup(&sc->sc_q); 871 } 872 if (sc->sc_state.sel) { 873 sc->sc_state.sel = false; 874 selwakeuppri(&sc->sc_rsel, PZERO); 875 } 876 if (sc->sc_async != NULL) { 877 DPRINTFN(3, "sending SIGIO %p\n", sc->sc_async); 878 PROC_LOCK(sc->sc_async); 879 kern_psignal(sc->sc_async, SIGIO); 880 PROC_UNLOCK(sc->sc_async); 881 } 882 KNOTE_LOCKED(&sc->sc_rsel.si_note, 0); 883 } 884 885 static device_method_t hidraw_methods[] = { 886 /* Device interface */ 887 DEVMETHOD(device_identify, hidraw_identify), 888 DEVMETHOD(device_probe, hidraw_probe), 889 DEVMETHOD(device_attach, hidraw_attach), 890 DEVMETHOD(device_detach, hidraw_detach), 891 892 DEVMETHOD_END 893 }; 894 895 static driver_t hidraw_driver = { 896 "hidraw", 897 hidraw_methods, 898 sizeof(struct hidraw_softc) 899 }; 900 901 #ifndef HIDRAW_MAKE_UHID_ALIAS 902 devclass_t hidraw_devclass; 903 #endif 904 905 DRIVER_MODULE(hidraw, hidbus, hidraw_driver, hidraw_devclass, NULL, 0); 906 MODULE_DEPEND(hidraw, hidbus, 1, 1, 1); 907 MODULE_DEPEND(hidraw, hid, 1, 1, 1); 908 MODULE_DEPEND(hidraw, usb, 1, 1, 1); 909 MODULE_VERSION(hidraw, 1); 910