1 /* $NetBSD: uhid_common.c,v 1.2 2025/12/15 08:38:21 hannken Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart (at) augustsson.net) at 9 * Carlstedt Research & Technology and Matthew R. Green (mrg (at) eterna23.net). 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: uhid_common.c,v 1.2 2025/12/15 08:38:21 hannken Exp $"); 39 40 #ifdef _KERNEL_OPT 41 #include "opt_hid.h" 42 #endif 43 44 #include <sys/param.h> 45 #include <sys/types.h> 46 47 #include <sys/atomic.h> 48 #include <sys/conf.h> 49 #include <sys/device.h> 50 #include <sys/file.h> 51 #include <sys/intr.h> 52 #include <sys/ioctl.h> 53 #include <sys/kernel.h> 54 #include <sys/kmem.h> 55 #include <sys/poll.h> 56 #include <sys/proc.h> 57 #include <sys/select.h> 58 #include <sys/signalvar.h> 59 #include <sys/systm.h> 60 #include <sys/tty.h> 61 #include <sys/vnode.h> 62 63 #include <dev/hid/hid.h> 64 #include <dev/hid/hidev.h> 65 #include <dev/hid/uhid.h> 66 67 #include <dev/usb/usbhid.h> 68 69 #include "ioconf.h" 70 71 #ifdef UHID_DEBUG 72 #define DPRINTF(x) if (uhiddebug) printf x 73 #define DPRINTFN(n,x) if (uhiddebug>(n)) printf x 74 extern int uhiddebug; 75 #else 76 #define DPRINTF(x) 77 #define DPRINTFN(n,x) 78 #endif 79 80 #define UHIDUNIT(dev) (minor(dev)) 81 #define UHID_CHUNK 128 /* chunk size for read */ 82 #define UHID_BSIZE 1020 /* buffer size */ 83 84 static dev_type_open(uhidopen); 85 static dev_type_cancel(uhidcancel); 86 static dev_type_close(uhidclose); 87 static dev_type_read(uhidread); 88 static dev_type_write(uhidwrite); 89 static dev_type_ioctl(uhidioctl); 90 static dev_type_poll(uhidpoll); 91 static dev_type_kqfilter(uhidkqfilter); 92 93 const struct cdevsw uhid_cdevsw = { 94 .d_open = uhidopen, 95 .d_cancel = uhidcancel, 96 .d_close = uhidclose, 97 .d_read = uhidread, 98 .d_write = uhidwrite, 99 .d_ioctl = uhidioctl, 100 .d_stop = nostop, 101 .d_tty = notty, 102 .d_poll = uhidpoll, 103 .d_mmap = nommap, 104 .d_kqfilter = uhidkqfilter, 105 .d_discard = nodiscard, 106 .d_cfdriver = &uhid_cd, 107 .d_devtounit = dev_minor_unit, 108 .d_flag = D_OTHER 109 }; 110 111 static void uhid_intr(void *, void *, u_int); 112 113 void 114 uhid_attach_common(struct uhid_softc *sc) 115 { 116 int size, repid; 117 void *desc; 118 119 selinit(&sc->sc_rsel); 120 121 hidev_get_report_desc(sc->sc_hidev, &desc, &size); 122 repid = sc->sc_report_id; 123 sc->sc_isize = hid_report_size(desc, size, hid_input, repid); 124 sc->sc_osize = hid_report_size(desc, size, hid_output, repid); 125 sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid); 126 sc->sc_raw = hid_is_collection(desc, size, repid, 127 HID_USAGE2(HUP_FIDO, HUF_U2FHID)); 128 129 aprint_naive("\n"); 130 aprint_normal(": input=%d, output=%d, feature=%d\n", 131 sc->sc_isize, sc->sc_osize, sc->sc_fsize); 132 133 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); 134 cv_init(&sc->sc_cv, "uhidrea"); 135 136 if (!pmf_device_register(sc->sc_dev, NULL, NULL)) { 137 aprint_error_dev(sc->sc_dev, 138 "couldn't establish power handler\n"); 139 } 140 } 141 142 int 143 uhid_detach_common(struct uhid_softc *sc) 144 { 145 int maj, mn; 146 147 DPRINTF(("uhid_detach: sc=%p\n", sc)); 148 149 pmf_device_deregister(sc->sc_dev); 150 151 /* locate the major number */ 152 maj = cdevsw_lookup_major(&uhid_cdevsw); 153 154 /* Nuke the vnodes for any open instances (calls close). */ 155 mn = device_unit(sc->sc_dev); 156 vdevgone(maj, mn, mn, VCHR); 157 158 KASSERTMSG(sc->sc_open == UHID_CLOSED, "open=%d", (int)sc->sc_open); 159 160 cv_destroy(&sc->sc_cv); 161 mutex_destroy(&sc->sc_lock); 162 seldestroy(&sc->sc_rsel); 163 164 return 0; 165 } 166 167 static void 168 uhid_intr(void *cookie, void *data, u_int len) 169 { 170 struct uhid_softc *sc = cookie; 171 172 #ifdef UHID_DEBUG 173 if (uhiddebug > 5) { 174 uint32_t i; 175 176 DPRINTF(("uhid_intr: data =")); 177 for (i = 0; i < len; i++) 178 DPRINTF((" %02x", ((u_char *)data)[i])); 179 DPRINTF(("\n")); 180 } 181 #endif 182 183 mutex_enter(&sc->sc_lock); 184 (void)b_to_q(data, len, &sc->sc_q); 185 186 DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q)); 187 cv_broadcast(&sc->sc_cv); 188 selnotify(&sc->sc_rsel, 0, NOTE_SUBMIT); 189 if (atomic_load_relaxed(&sc->sc_async) != NULL) { 190 mutex_enter(&proc_lock); 191 if (sc->sc_async != NULL) { 192 DPRINTFN(3, ("uhid_intr: sending SIGIO to %jd\n", 193 (intmax_t)sc->sc_async->p_pid)); 194 psignal(sc->sc_async, SIGIO); 195 } 196 mutex_exit(&proc_lock); 197 } 198 mutex_exit(&sc->sc_lock); 199 } 200 201 static int 202 uhidopen(dev_t dev, int flag, int mode, struct lwp *l) 203 { 204 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 205 int error; 206 207 DPRINTF(("uhidopen: sc=%p\n", sc)); 208 if (sc == NULL) 209 return ENXIO; 210 211 /* 212 * Try to open. If closing in progress, give up. If already 213 * open (or opening), fail -- opens are exclusive. 214 */ 215 mutex_enter(&sc->sc_lock); 216 if (sc->sc_open != UHID_CLOSED || sc->sc_closing) { 217 mutex_exit(&sc->sc_lock); 218 return EBUSY; 219 } 220 sc->sc_open = UHID_OPENING; 221 atomic_store_relaxed(&sc->sc_state, 0); 222 mutex_exit(&sc->sc_lock); 223 224 /* uhid interrupts aren't enabled yet, so setup sc_q now */ 225 if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) { 226 error = ENOMEM; 227 goto fail0; 228 } 229 230 /* Allocate an output buffer if needed. */ 231 if (sc->sc_osize > 0) 232 sc->sc_obuf = kmem_alloc(sc->sc_osize, KM_SLEEP); 233 else 234 sc->sc_obuf = NULL; 235 236 /* Paranoia: reset SIGIO before enabling interrupts. */ 237 mutex_enter(&proc_lock); 238 atomic_store_relaxed(&sc->sc_async, NULL); 239 mutex_exit(&proc_lock); 240 241 /* Open the hidev -- after this point we can get interrupts. */ 242 error = hidev_open(sc->sc_hidev, &uhid_intr, sc); 243 if (error) 244 goto fail1; 245 246 /* We are open for business. */ 247 mutex_enter(&sc->sc_lock); 248 sc->sc_open = UHID_OPEN; 249 mutex_exit(&sc->sc_lock); 250 251 return 0; 252 253 fail1: selnotify(&sc->sc_rsel, POLLHUP, 0); 254 mutex_enter(&proc_lock); 255 atomic_store_relaxed(&sc->sc_async, NULL); 256 mutex_exit(&proc_lock); 257 if (sc->sc_osize > 0) { 258 kmem_free(sc->sc_obuf, sc->sc_osize); 259 sc->sc_obuf = NULL; 260 } 261 clfree(&sc->sc_q); 262 fail0: mutex_enter(&sc->sc_lock); 263 KASSERT(sc->sc_open == UHID_OPENING); 264 sc->sc_open = UHID_CLOSED; 265 atomic_store_relaxed(&sc->sc_state, 0); 266 mutex_exit(&sc->sc_lock); 267 return error; 268 } 269 270 static int 271 uhidcancel(dev_t dev, int flag, int mode, struct lwp *l) 272 { 273 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 274 275 DPRINTF(("uhidcancel: sc=%p\n", sc)); 276 if (sc == NULL) 277 return 0; 278 279 /* 280 * Mark it closing, wake any waiters, and suspend output. 281 * After this point, no new xfers can be submitted. 282 */ 283 mutex_enter(&sc->sc_lock); 284 sc->sc_closing = true; 285 cv_broadcast(&sc->sc_cv); 286 mutex_exit(&sc->sc_lock); 287 288 hidev_stop(sc->sc_hidev); 289 290 return 0; 291 } 292 293 static int 294 uhidclose(dev_t dev, int flag, int mode, struct lwp *l) 295 { 296 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 297 298 DPRINTF(("uhidclose: sc=%p\n", sc)); 299 if (sc == NULL) 300 return 0; 301 302 mutex_enter(&sc->sc_lock); 303 KASSERT(sc->sc_closing); 304 KASSERTMSG(sc->sc_open == UHID_OPEN || sc->sc_open == UHID_CLOSED, 305 "sc_open=%d", sc->sc_open); 306 if (sc->sc_open == UHID_CLOSED) 307 goto out; 308 309 /* Release the lock while we free things. */ 310 mutex_exit(&sc->sc_lock); 311 312 /* Prevent further interrupts. */ 313 hidev_close(sc->sc_hidev); 314 315 /* Hang up all select/poll. */ 316 selnotify(&sc->sc_rsel, POLLHUP, 0); 317 318 /* Reset SIGIO. */ 319 mutex_enter(&proc_lock); 320 atomic_store_relaxed(&sc->sc_async, NULL); 321 mutex_exit(&proc_lock); 322 323 /* Free the buffer and queue. */ 324 if (sc->sc_osize > 0) { 325 kmem_free(sc->sc_obuf, sc->sc_osize); 326 sc->sc_obuf = NULL; 327 } 328 clfree(&sc->sc_q); 329 330 mutex_enter(&sc->sc_lock); 331 332 /* All set. We are now closed. */ 333 sc->sc_open = UHID_CLOSED; 334 out: KASSERT(sc->sc_open == UHID_CLOSED); 335 sc->sc_closing = false; 336 atomic_store_relaxed(&sc->sc_state, 0); 337 mutex_exit(&sc->sc_lock); 338 339 return 0; 340 } 341 342 static int 343 uhidread(dev_t dev, struct uio *uio, int flag) 344 { 345 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 346 int error = 0; 347 int extra; 348 size_t length; 349 u_char buffer[UHID_CHUNK]; 350 usbd_status err; 351 352 DPRINTFN(1, ("uhidread\n")); 353 if (atomic_load_relaxed(&sc->sc_state) & UHID_IMMED) { 354 DPRINTFN(1, ("uhidread immed\n")); 355 extra = sc->sc_report_id != 0; 356 if (sc->sc_isize + extra > sizeof(buffer)) 357 return ENOBUFS; 358 err = hidev_get_report(sc->sc_hidev, UHID_INPUT_REPORT, 359 buffer, sc->sc_isize + extra); 360 if (err) 361 return EIO; 362 return uiomove(buffer+extra, sc->sc_isize, uio); 363 } 364 365 mutex_enter(&sc->sc_lock); 366 while (sc->sc_q.c_cc == 0) { 367 if (flag & IO_NDELAY) { 368 mutex_exit(&sc->sc_lock); 369 return EWOULDBLOCK; 370 } 371 if (sc->sc_closing) { 372 mutex_exit(&sc->sc_lock); 373 return EIO; 374 } 375 DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q)); 376 error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock); 377 DPRINTFN(5, ("uhidread: woke, error=%d\n", error)); 378 if (error) { 379 break; 380 } 381 } 382 383 /* Transfer as many chunks as possible. */ 384 while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) { 385 length = uimin(sc->sc_q.c_cc, uio->uio_resid); 386 if (length > sizeof(buffer)) 387 length = sizeof(buffer); 388 389 /* Remove a small chunk from the input queue. */ 390 (void) q_to_b(&sc->sc_q, buffer, length); 391 DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length)); 392 393 /* Copy the data to the user process. */ 394 mutex_exit(&sc->sc_lock); 395 if ((error = uiomove(buffer, length, uio)) != 0) 396 return error; 397 mutex_enter(&sc->sc_lock); 398 } 399 400 mutex_exit(&sc->sc_lock); 401 return error; 402 } 403 404 static int 405 uhidwrite(dev_t dev, struct uio *uio, int flag) 406 { 407 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 408 int error; 409 int size; 410 usbd_status err; 411 412 DPRINTFN(1, ("uhidwrite\n")); 413 414 size = sc->sc_osize; 415 if (uio->uio_resid != size || size == 0) 416 return EINVAL; 417 error = uiomove(sc->sc_obuf, size, uio); 418 #ifdef UHID_DEBUG 419 if (uhiddebug > 5) { 420 uint32_t i; 421 422 DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_dev), 423 error)); 424 for (i = 0; i < size; i++) 425 DPRINTF((" %02x", sc->sc_obuf[i])); 426 DPRINTF(("\n")); 427 } 428 #endif 429 if (!error) { 430 if (sc->sc_raw) 431 err = hidev_write(sc->sc_hidev, sc->sc_obuf, size); 432 else 433 err = hidev_set_report(sc->sc_hidev, 434 UHID_OUTPUT_REPORT, sc->sc_obuf, size); 435 if (err) { 436 DPRINTF(("%s: err = %d\n", 437 device_xname(sc->sc_dev), err)); 438 error = EIO; 439 } 440 } 441 442 return error; 443 } 444 445 static int 446 uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 447 { 448 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 449 struct usb_ctl_report_desc *rd; 450 struct usb_ctl_report *re; 451 u_char buffer[UHID_CHUNK]; 452 int size, extra; 453 usbd_status err; 454 void *desc; 455 456 DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); 457 458 switch (cmd) { 459 case FIONBIO: 460 /* All handled in the upper FS layer. */ 461 break; 462 463 case FIOASYNC: 464 mutex_enter(&proc_lock); 465 if (*(int *)addr) { 466 if (sc->sc_async != NULL) { 467 mutex_exit(&proc_lock); 468 return EBUSY; 469 } 470 atomic_store_relaxed(&sc->sc_async, l->l_proc); 471 DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", l->l_proc)); 472 } else 473 atomic_store_relaxed(&sc->sc_async, NULL); 474 mutex_exit(&proc_lock); 475 break; 476 477 /* XXX this is not the most general solution. */ 478 case TIOCSPGRP: 479 mutex_enter(&proc_lock); 480 if (sc->sc_async == NULL) { 481 mutex_exit(&proc_lock); 482 return EINVAL; 483 } 484 if (*(int *)addr != sc->sc_async->p_pgid) { 485 mutex_exit(&proc_lock); 486 return EPERM; 487 } 488 mutex_exit(&proc_lock); 489 break; 490 491 case FIOSETOWN: 492 mutex_enter(&proc_lock); 493 if (sc->sc_async == NULL) { 494 mutex_exit(&proc_lock); 495 return EINVAL; 496 } 497 if (-*(int *)addr != sc->sc_async->p_pgid 498 && *(int *)addr != sc->sc_async->p_pid) { 499 mutex_exit(&proc_lock); 500 return EPERM; 501 } 502 mutex_exit(&proc_lock); 503 break; 504 505 case USB_HID_GET_RAW: 506 *(int *)addr = sc->sc_raw; 507 break; 508 509 case USB_HID_SET_RAW: 510 sc->sc_raw = *(int *)addr; 511 break; 512 513 case USB_GET_REPORT_DESC: 514 hidev_get_report_desc(sc->sc_hidev, &desc, &size); 515 rd = (struct usb_ctl_report_desc *)addr; 516 size = uimin(size, sizeof(rd->ucrd_data)); 517 rd->ucrd_size = size; 518 memcpy(rd->ucrd_data, desc, size); 519 break; 520 521 case USB_SET_IMMED: 522 if (*(int *)addr) { 523 extra = sc->sc_report_id != 0; 524 if (sc->sc_isize + extra > sizeof(buffer)) 525 return ENOBUFS; 526 err = hidev_get_report(sc->sc_hidev, UHID_INPUT_REPORT, 527 buffer, sc->sc_isize + extra); 528 if (err) 529 return EOPNOTSUPP; 530 531 atomic_or_32(&sc->sc_state, UHID_IMMED); 532 } else 533 atomic_and_32(&sc->sc_state, ~UHID_IMMED); 534 break; 535 536 case USB_GET_REPORT: 537 re = (struct usb_ctl_report *)addr; 538 switch (re->ucr_report) { 539 case UHID_INPUT_REPORT: 540 size = sc->sc_isize; 541 break; 542 case UHID_OUTPUT_REPORT: 543 size = sc->sc_osize; 544 break; 545 case UHID_FEATURE_REPORT: 546 size = sc->sc_fsize; 547 break; 548 default: 549 return EINVAL; 550 } 551 extra = sc->sc_report_id != 0; 552 if (size + extra > sizeof(re->ucr_data)) 553 return ENOBUFS; 554 err = hidev_get_report(sc->sc_hidev, re->ucr_report, 555 re->ucr_data, size + extra); 556 if (extra) 557 memmove(re->ucr_data, re->ucr_data+1, size); 558 if (err) 559 return EIO; 560 break; 561 562 case USB_SET_REPORT: 563 re = (struct usb_ctl_report *)addr; 564 switch (re->ucr_report) { 565 case UHID_INPUT_REPORT: 566 size = sc->sc_isize; 567 break; 568 case UHID_OUTPUT_REPORT: 569 size = sc->sc_osize; 570 break; 571 case UHID_FEATURE_REPORT: 572 size = sc->sc_fsize; 573 break; 574 default: 575 return EINVAL; 576 } 577 if (size > sizeof(re->ucr_data)) 578 return ENOBUFS; 579 err = hidev_set_report(sc->sc_hidev, re->ucr_report, 580 re->ucr_data, size); 581 if (err) 582 return EIO; 583 break; 584 585 case USB_GET_REPORT_ID: 586 *(int *)addr = sc->sc_report_id; 587 break; 588 589 default: 590 if (sc->sc_ioctl != NULL) { 591 return sc->sc_ioctl(sc, cmd, addr, flag, l); 592 } 593 return EINVAL; 594 } 595 return 0; 596 } 597 598 static int 599 uhidpoll(dev_t dev, int events, struct lwp *l) 600 { 601 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 602 int revents = 0; 603 604 mutex_enter(&sc->sc_lock); 605 if (events & (POLLOUT | POLLWRNORM)) 606 revents |= events & (POLLOUT | POLLWRNORM); 607 if (events & (POLLIN | POLLRDNORM)) { 608 if (sc->sc_q.c_cc > 0) 609 revents |= events & (POLLIN | POLLRDNORM); 610 else 611 selrecord(l, &sc->sc_rsel); 612 } 613 mutex_exit(&sc->sc_lock); 614 615 return revents; 616 } 617 618 static void 619 filt_uhidrdetach(struct knote *kn) 620 { 621 struct uhid_softc *sc = kn->kn_hook; 622 623 mutex_enter(&sc->sc_lock); 624 selremove_knote(&sc->sc_rsel, kn); 625 mutex_exit(&sc->sc_lock); 626 } 627 628 static int 629 filt_uhidread(struct knote *kn, long hint) 630 { 631 struct uhid_softc *sc = kn->kn_hook; 632 633 if (hint == NOTE_SUBMIT) 634 KASSERT(mutex_owned(&sc->sc_lock)); 635 else 636 mutex_enter(&sc->sc_lock); 637 638 kn->kn_data = sc->sc_q.c_cc; 639 640 if (hint == NOTE_SUBMIT) 641 KASSERT(mutex_owned(&sc->sc_lock)); 642 else 643 mutex_exit(&sc->sc_lock); 644 645 return kn->kn_data > 0; 646 } 647 648 static const struct filterops uhidread_filtops = { 649 .f_flags = FILTEROP_ISFD, 650 .f_attach = NULL, 651 .f_detach = filt_uhidrdetach, 652 .f_event = filt_uhidread, 653 }; 654 655 static int 656 uhidkqfilter(dev_t dev, struct knote *kn) 657 { 658 struct uhid_softc *sc = device_lookup_private(&uhid_cd, UHIDUNIT(dev)); 659 660 switch (kn->kn_filter) { 661 case EVFILT_READ: 662 kn->kn_fop = &uhidread_filtops; 663 kn->kn_hook = sc; 664 mutex_enter(&sc->sc_lock); 665 selrecord_knote(&sc->sc_rsel, kn); 666 mutex_exit(&sc->sc_lock); 667 return 0; 668 669 case EVFILT_WRITE: 670 kn->kn_fop = &seltrue_filtops; 671 return 0; 672 673 default: 674 return EINVAL; 675 } 676 } 677