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