1/*- 2 * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org> 3 * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@FreeBSD.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: stable/11/sys/dev/evdev/cdev.c 359907 2020-04-13 22:21:01Z wulf $ 28 */ 29 30#include "opt_evdev.h" 31 32#include <sys/param.h> 33#include <sys/bitstring.h> 34#include <sys/conf.h> 35#include <sys/filio.h> 36#include <sys/fcntl.h> 37#include <sys/kernel.h> 38#include <sys/malloc.h> 39#include <sys/poll.h> 40#include <sys/proc.h> 41#include <sys/selinfo.h> 42#include <sys/systm.h> 43#include <sys/time.h> 44#include <sys/uio.h> 45 46#include <dev/evdev/evdev.h> 47#include <dev/evdev/evdev_private.h> 48#include <dev/evdev/input.h> 49 50#ifdef COMPAT_FREEBSD32 51#include <sys/mount.h> 52#include <sys/sysent.h> 53#include <compat/freebsd32/freebsd32.h> 54struct input_event32 { 55 struct timeval32 time; 56 uint16_t type; 57 uint16_t code; 58 int32_t value; 59}; 60#endif 61 62#ifdef EVDEV_DEBUG 63#define debugf(client, fmt, args...) printf("evdev cdev: "fmt"\n", ##args) 64#else 65#define debugf(client, fmt, args...) 66#endif 67 68#define DEF_RING_REPORTS 8 69 70static d_open_t evdev_open; 71static d_read_t evdev_read; 72static d_write_t evdev_write; 73static d_ioctl_t evdev_ioctl; 74static d_poll_t evdev_poll; 75static d_kqfilter_t evdev_kqfilter; 76 77static int evdev_kqread(struct knote *kn, long hint); 78static void evdev_kqdetach(struct knote *kn); 79static void evdev_dtor(void *); 80static int evdev_ioctl_eviocgbit(struct evdev_dev *, int, int, caddr_t); 81static void evdev_client_filter_queue(struct evdev_client *, uint16_t); 82 83static struct cdevsw evdev_cdevsw = { 84 .d_version = D_VERSION, 85 .d_open = evdev_open, 86 .d_read = evdev_read, 87 .d_write = evdev_write, 88 .d_ioctl = evdev_ioctl, 89 .d_poll = evdev_poll, 90 .d_kqfilter = evdev_kqfilter, 91 .d_name = "evdev", 92}; 93 94static struct filterops evdev_cdev_filterops = { 95 .f_isfd = 1, 96 .f_attach = NULL, 97 .f_detach = evdev_kqdetach, 98 .f_event = evdev_kqread, 99}; 100 101static int 102evdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 103{ 104 struct evdev_dev *evdev = dev->si_drv1; 105 struct evdev_client *client; 106 size_t buffer_size; 107 int ret; 108 109 if (evdev == NULL) 110 return (ENODEV); 111 112 /* Initialize client structure */ 113 buffer_size = evdev->ev_report_size * DEF_RING_REPORTS; 114 client = malloc(offsetof(struct evdev_client, ec_buffer) + 115 sizeof(struct input_event) * buffer_size, 116 M_EVDEV, M_WAITOK | M_ZERO); 117 118 /* Initialize ring buffer */ 119 client->ec_buffer_size = buffer_size; 120 client->ec_buffer_head = 0; 121 client->ec_buffer_tail = 0; 122 client->ec_buffer_ready = 0; 123 124 client->ec_evdev = evdev; 125 mtx_init(&client->ec_buffer_mtx, "evclient", "evdev", MTX_DEF); 126 knlist_init_mtx(&client->ec_selp.si_note, &client->ec_buffer_mtx); 127 128 /* Avoid race with evdev_unregister */ 129 EVDEV_LOCK(evdev); 130 if (dev->si_drv1 == NULL) 131 ret = ENODEV; 132 else 133 ret = evdev_register_client(evdev, client); 134 135 if (ret != 0) 136 evdev_revoke_client(client); 137 /* 138 * Unlock evdev here because non-sleepable lock held 139 * while calling devfs_set_cdevpriv upsets WITNESS 140 */ 141 EVDEV_UNLOCK(evdev); 142 143 if (!ret) 144 ret = devfs_set_cdevpriv(client, evdev_dtor); 145 146 if (ret != 0) { 147 debugf(client, "cannot register evdev client"); 148 evdev_dtor(client); 149 } 150 151 return (ret); 152} 153 154static void 155evdev_dtor(void *data) 156{ 157 struct evdev_client *client = (struct evdev_client *)data; 158 159 EVDEV_LOCK(client->ec_evdev); 160 if (!client->ec_revoked) 161 evdev_dispose_client(client->ec_evdev, client); 162 EVDEV_UNLOCK(client->ec_evdev); 163 164 knlist_clear(&client->ec_selp.si_note, 0); 165 seldrain(&client->ec_selp); 166 knlist_destroy(&client->ec_selp.si_note); 167 funsetown(&client->ec_sigio); 168 mtx_destroy(&client->ec_buffer_mtx); 169 free(client, M_EVDEV); 170} 171 172static int 173evdev_read(struct cdev *dev, struct uio *uio, int ioflag) 174{ 175 struct evdev_client *client; 176 union { 177 struct input_event t; 178#ifdef COMPAT_FREEBSD32 179 struct input_event32 t32; 180#endif 181 } event; 182 struct input_event *head; 183 size_t evsize; 184 int ret = 0; 185 int remaining; 186 187 ret = devfs_get_cdevpriv((void **)&client); 188 if (ret != 0) 189 return (ret); 190 191 debugf(client, "read %zd bytes by thread %d", uio->uio_resid, 192 uio->uio_td->td_tid); 193 194 if (client->ec_revoked) 195 return (ENODEV); 196 197#ifdef COMPAT_FREEBSD32 198 if (SV_CURPROC_FLAG(SV_ILP32)) 199 evsize = sizeof(struct input_event32); 200 else 201#endif 202 evsize = sizeof(struct input_event); 203 204 /* Zero-sized reads are allowed for error checking */ 205 if (uio->uio_resid != 0 && uio->uio_resid < evsize) 206 return (EINVAL); 207 208 remaining = uio->uio_resid / evsize; 209 210 EVDEV_CLIENT_LOCKQ(client); 211 212 if (EVDEV_CLIENT_EMPTYQ(client)) { 213 if (ioflag & O_NONBLOCK) 214 ret = EWOULDBLOCK; 215 else { 216 if (remaining != 0) { 217 client->ec_blocked = true; 218 ret = mtx_sleep(client, &client->ec_buffer_mtx, 219 PCATCH, "evread", 0); 220 if (ret == 0 && client->ec_revoked) 221 ret = ENODEV; 222 } 223 } 224 } 225 226 while (ret == 0 && !EVDEV_CLIENT_EMPTYQ(client) && remaining > 0) { 227 head = client->ec_buffer + client->ec_buffer_head; 228#ifdef COMPAT_FREEBSD32 229 if (SV_CURPROC_FLAG(SV_ILP32)) { 230 bzero(&event.t32, sizeof(struct input_event32)); 231 TV_CP(*head, event.t32, time); 232 CP(*head, event.t32, type); 233 CP(*head, event.t32, code); 234 CP(*head, event.t32, value); 235 } else 236#endif 237 bcopy(head, &event.t, evsize); 238 239 client->ec_buffer_head = 240 (client->ec_buffer_head + 1) % client->ec_buffer_size; 241 remaining--; 242 243 EVDEV_CLIENT_UNLOCKQ(client); 244 ret = uiomove(&event, evsize, uio); 245 EVDEV_CLIENT_LOCKQ(client); 246 } 247 248 EVDEV_CLIENT_UNLOCKQ(client); 249 250 return (ret); 251} 252 253static int 254evdev_write(struct cdev *dev, struct uio *uio, int ioflag) 255{ 256 struct evdev_dev *evdev = dev->si_drv1; 257 struct evdev_client *client; 258 union { 259 struct input_event t; 260#ifdef COMPAT_FREEBSD32 261 struct input_event32 t32; 262#endif 263 } event; 264 size_t evsize; 265 int ret = 0; 266 267 ret = devfs_get_cdevpriv((void **)&client); 268 if (ret != 0) 269 return (ret); 270 271 debugf(client, "write %zd bytes by thread %d", uio->uio_resid, 272 uio->uio_td->td_tid); 273 274 if (client->ec_revoked || evdev == NULL) 275 return (ENODEV); 276 277#ifdef COMPAT_FREEBSD32 278 if (SV_CURPROC_FLAG(SV_ILP32)) 279 evsize = sizeof(struct input_event32); 280 else 281#endif 282 evsize = sizeof(struct input_event); 283 284 if (uio->uio_resid % evsize != 0) { 285 debugf(client, "write size not multiple of input_event size"); 286 return (EINVAL); 287 } 288 289 while (uio->uio_resid > 0 && ret == 0) { 290 ret = uiomove(&event, evsize, uio); 291 if (ret == 0) { 292#ifdef COMPAT_FREEBSD32 293 if (SV_CURPROC_FLAG(SV_ILP32)) 294 ret = evdev_inject_event(evdev, event.t32.type, 295 event.t32.code, event.t32.value); 296 else 297#endif 298 ret = evdev_inject_event(evdev, event.t.type, 299 event.t.code, event.t.value); 300 } 301 } 302 303 return (ret); 304} 305 306static int 307evdev_poll(struct cdev *dev, int events, struct thread *td) 308{ 309 struct evdev_client *client; 310 int ret; 311 int revents = 0; 312 313 ret = devfs_get_cdevpriv((void **)&client); 314 if (ret != 0) 315 return (POLLNVAL); 316 317 debugf(client, "poll by thread %d", td->td_tid); 318 319 if (client->ec_revoked) 320 return (POLLHUP); 321 322 if (events & (POLLIN | POLLRDNORM)) { 323 EVDEV_CLIENT_LOCKQ(client); 324 if (!EVDEV_CLIENT_EMPTYQ(client)) 325 revents = events & (POLLIN | POLLRDNORM); 326 else { 327 client->ec_selected = true; 328 selrecord(td, &client->ec_selp); 329 } 330 EVDEV_CLIENT_UNLOCKQ(client); 331 } 332 333 return (revents); 334} 335 336static int 337evdev_kqfilter(struct cdev *dev, struct knote *kn) 338{ 339 struct evdev_client *client; 340 int ret; 341 342 ret = devfs_get_cdevpriv((void **)&client); 343 if (ret != 0) 344 return (ret); 345 346 if (client->ec_revoked) 347 return (ENODEV); 348 349 switch(kn->kn_filter) { 350 case EVFILT_READ: 351 kn->kn_fop = &evdev_cdev_filterops; 352 break; 353 default: 354 return(EINVAL); 355 } 356 kn->kn_hook = (caddr_t)client; 357 358 knlist_add(&client->ec_selp.si_note, kn, 0); 359 return (0); 360} 361 362static int 363evdev_kqread(struct knote *kn, long hint) 364{ 365 struct evdev_client *client; 366 int ret; 367 368 client = (struct evdev_client *)kn->kn_hook; 369 370 EVDEV_CLIENT_LOCKQ_ASSERT(client); 371 372 if (client->ec_revoked) { 373 kn->kn_flags |= EV_EOF; 374 ret = 1; 375 } else { 376 kn->kn_data = EVDEV_CLIENT_SIZEQ(client) * 377 sizeof(struct input_event); 378 ret = !EVDEV_CLIENT_EMPTYQ(client); 379 } 380 return (ret); 381} 382 383static void 384evdev_kqdetach(struct knote *kn) 385{ 386 struct evdev_client *client; 387 388 client = (struct evdev_client *)kn->kn_hook; 389 knlist_remove(&client->ec_selp.si_note, kn, 0); 390} 391 392static int 393evdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 394 struct thread *td) 395{ 396 struct evdev_dev *evdev = dev->si_drv1; 397 struct evdev_client *client; 398 struct input_keymap_entry *ke; 399 int ret, len, limit, type_num; 400 uint32_t code; 401 size_t nvalues; 402 403 ret = devfs_get_cdevpriv((void **)&client); 404 if (ret != 0) 405 return (ret); 406 407 if (client->ec_revoked || evdev == NULL) 408 return (ENODEV); 409 410 /* file I/O ioctl handling */ 411 switch (cmd) { 412 case FIOSETOWN: 413 return (fsetown(*(int *)data, &client->ec_sigio)); 414 415 case FIOGETOWN: 416 *(int *)data = fgetown(&client->ec_sigio); 417 return (0); 418 419 case FIONBIO: 420 return (0); 421 422 case FIOASYNC: 423 if (*(int *)data) 424 client->ec_async = true; 425 else 426 client->ec_async = false; 427 428 return (0); 429 430 case FIONREAD: 431 EVDEV_CLIENT_LOCKQ(client); 432 *(int *)data = 433 EVDEV_CLIENT_SIZEQ(client) * sizeof(struct input_event); 434 EVDEV_CLIENT_UNLOCKQ(client); 435 return (0); 436 } 437 438 len = IOCPARM_LEN(cmd); 439 debugf(client, "ioctl called: cmd=0x%08lx, data=%p", cmd, data); 440 441 /* evdev fixed-length ioctls handling */ 442 switch (cmd) { 443 case EVIOCGVERSION: 444 *(int *)data = EV_VERSION; 445 return (0); 446 447 case EVIOCGID: 448 debugf(client, "EVIOCGID: bus=%d vendor=0x%04x product=0x%04x", 449 evdev->ev_id.bustype, evdev->ev_id.vendor, 450 evdev->ev_id.product); 451 memcpy(data, &evdev->ev_id, sizeof(struct input_id)); 452 return (0); 453 454 case EVIOCGREP: 455 if (!evdev_event_supported(evdev, EV_REP)) 456 return (ENOTSUP); 457 458 memcpy(data, evdev->ev_rep, sizeof(evdev->ev_rep)); 459 return (0); 460 461 case EVIOCSREP: 462 if (!evdev_event_supported(evdev, EV_REP)) 463 return (ENOTSUP); 464 465 evdev_inject_event(evdev, EV_REP, REP_DELAY, ((int *)data)[0]); 466 evdev_inject_event(evdev, EV_REP, REP_PERIOD, 467 ((int *)data)[1]); 468 return (0); 469 470 case EVIOCGKEYCODE: 471 /* Fake unsupported ioctl */ 472 return (0); 473 474 case EVIOCGKEYCODE_V2: 475 if (evdev->ev_methods == NULL || 476 evdev->ev_methods->ev_get_keycode == NULL) 477 return (ENOTSUP); 478 479 ke = (struct input_keymap_entry *)data; 480 evdev->ev_methods->ev_get_keycode(evdev, evdev->ev_softc, ke); 481 return (0); 482 483 case EVIOCSKEYCODE: 484 /* Fake unsupported ioctl */ 485 return (0); 486 487 case EVIOCSKEYCODE_V2: 488 if (evdev->ev_methods == NULL || 489 evdev->ev_methods->ev_set_keycode == NULL) 490 return (ENOTSUP); 491 492 ke = (struct input_keymap_entry *)data; 493 evdev->ev_methods->ev_set_keycode(evdev, evdev->ev_softc, ke); 494 return (0); 495 496 case EVIOCGABS(0) ... EVIOCGABS(ABS_MAX): 497 if (evdev->ev_absinfo == NULL) 498 return (EINVAL); 499 500 memcpy(data, &evdev->ev_absinfo[cmd - EVIOCGABS(0)], 501 sizeof(struct input_absinfo)); 502 return (0); 503 504 case EVIOCSABS(0) ... EVIOCSABS(ABS_MAX): 505 if (evdev->ev_absinfo == NULL) 506 return (EINVAL); 507 508 code = cmd - EVIOCSABS(0); 509 /* mt-slot number can not be changed */ 510 if (code == ABS_MT_SLOT) 511 return (EINVAL); 512 513 EVDEV_LOCK(evdev); 514 evdev_set_absinfo(evdev, code, (struct input_absinfo *)data); 515 EVDEV_UNLOCK(evdev); 516 return (0); 517 518 case EVIOCSFF: 519 case EVIOCRMFF: 520 case EVIOCGEFFECTS: 521 /* Fake unsupported ioctls */ 522 return (0); 523 524 case EVIOCGRAB: 525 EVDEV_LOCK(evdev); 526 if (*(int *)data) 527 ret = evdev_grab_client(evdev, client); 528 else 529 ret = evdev_release_client(evdev, client); 530 EVDEV_UNLOCK(evdev); 531 return (ret); 532 533 case EVIOCREVOKE: 534 if (*(int *)data != 0) 535 return (EINVAL); 536 537 EVDEV_LOCK(evdev); 538 if (dev->si_drv1 != NULL && !client->ec_revoked) { 539 evdev_dispose_client(evdev, client); 540 evdev_revoke_client(client); 541 } 542 EVDEV_UNLOCK(evdev); 543 return (0); 544 545 case EVIOCSCLOCKID: 546 switch (*(int *)data) { 547 case CLOCK_REALTIME: 548 client->ec_clock_id = EV_CLOCK_REALTIME; 549 return (0); 550 case CLOCK_MONOTONIC: 551 client->ec_clock_id = EV_CLOCK_MONOTONIC; 552 return (0); 553 default: 554 return (EINVAL); 555 } 556 } 557 558 /* evdev variable-length ioctls handling */ 559 switch (IOCBASECMD(cmd)) { 560 case EVIOCGNAME(0): 561 strlcpy(data, evdev->ev_name, len); 562 return (0); 563 564 case EVIOCGPHYS(0): 565 if (evdev->ev_shortname[0] == 0) 566 return (ENOENT); 567 568 strlcpy(data, evdev->ev_shortname, len); 569 return (0); 570 571 case EVIOCGUNIQ(0): 572 if (evdev->ev_serial[0] == 0) 573 return (ENOENT); 574 575 strlcpy(data, evdev->ev_serial, len); 576 return (0); 577 578 case EVIOCGPROP(0): 579 limit = MIN(len, bitstr_size(INPUT_PROP_CNT)); 580 memcpy(data, evdev->ev_prop_flags, limit); 581 return (0); 582 583 case EVIOCGMTSLOTS(0): 584 if (evdev->ev_mt == NULL) 585 return (EINVAL); 586 if (len < sizeof(uint32_t)) 587 return (EINVAL); 588 code = *(uint32_t *)data; 589 if (!ABS_IS_MT(code)) 590 return (EINVAL); 591 592 nvalues = 593 MIN(len / sizeof(int32_t) - 1, MAXIMAL_MT_SLOT(evdev) + 1); 594 for (int i = 0; i < nvalues; i++) 595 ((int32_t *)data)[i + 1] = 596 evdev_get_mt_value(evdev, i, code); 597 return (0); 598 599 case EVIOCGKEY(0): 600 limit = MIN(len, bitstr_size(KEY_CNT)); 601 EVDEV_LOCK(evdev); 602 evdev_client_filter_queue(client, EV_KEY); 603 memcpy(data, evdev->ev_key_states, limit); 604 EVDEV_UNLOCK(evdev); 605 return (0); 606 607 case EVIOCGLED(0): 608 limit = MIN(len, bitstr_size(LED_CNT)); 609 EVDEV_LOCK(evdev); 610 evdev_client_filter_queue(client, EV_LED); 611 memcpy(data, evdev->ev_led_states, limit); 612 EVDEV_UNLOCK(evdev); 613 return (0); 614 615 case EVIOCGSND(0): 616 limit = MIN(len, bitstr_size(SND_CNT)); 617 EVDEV_LOCK(evdev); 618 evdev_client_filter_queue(client, EV_SND); 619 memcpy(data, evdev->ev_snd_states, limit); 620 EVDEV_UNLOCK(evdev); 621 return (0); 622 623 case EVIOCGSW(0): 624 limit = MIN(len, bitstr_size(SW_CNT)); 625 EVDEV_LOCK(evdev); 626 evdev_client_filter_queue(client, EV_SW); 627 memcpy(data, evdev->ev_sw_states, limit); 628 EVDEV_UNLOCK(evdev); 629 return (0); 630 631 case EVIOCGBIT(0, 0) ... EVIOCGBIT(EV_MAX, 0): 632 type_num = IOCBASECMD(cmd) - EVIOCGBIT(0, 0); 633 debugf(client, "EVIOCGBIT(%d): data=%p, len=%d", type_num, 634 data, len); 635 return (evdev_ioctl_eviocgbit(evdev, type_num, len, data)); 636 } 637 638 return (EINVAL); 639} 640 641static int 642evdev_ioctl_eviocgbit(struct evdev_dev *evdev, int type, int len, caddr_t data) 643{ 644 unsigned long *bitmap; 645 int limit; 646 647 switch (type) { 648 case 0: 649 bitmap = evdev->ev_type_flags; 650 limit = EV_CNT; 651 break; 652 case EV_KEY: 653 bitmap = evdev->ev_key_flags; 654 limit = KEY_CNT; 655 break; 656 case EV_REL: 657 bitmap = evdev->ev_rel_flags; 658 limit = REL_CNT; 659 break; 660 case EV_ABS: 661 bitmap = evdev->ev_abs_flags; 662 limit = ABS_CNT; 663 break; 664 case EV_MSC: 665 bitmap = evdev->ev_msc_flags; 666 limit = MSC_CNT; 667 break; 668 case EV_LED: 669 bitmap = evdev->ev_led_flags; 670 limit = LED_CNT; 671 break; 672 case EV_SND: 673 bitmap = evdev->ev_snd_flags; 674 limit = SND_CNT; 675 break; 676 case EV_SW: 677 bitmap = evdev->ev_sw_flags; 678 limit = SW_CNT; 679 break; 680 case EV_FF: 681 /* 682 * We don't support EV_FF now, so let's 683 * just fake it returning only zeros. 684 */ 685 bzero(data, len); 686 return (0); 687 default: 688 return (ENOTTY); 689 } 690 691 /* 692 * Clear ioctl data buffer in case it's bigger than 693 * bitmap size 694 */ 695 bzero(data, len); 696 697 limit = bitstr_size(limit); 698 len = MIN(limit, len); 699 memcpy(data, bitmap, len); 700 return (0); 701} 702 703void 704evdev_revoke_client(struct evdev_client *client) 705{ 706 707 EVDEV_LOCK_ASSERT(client->ec_evdev); 708 709 client->ec_revoked = true; 710} 711 712void 713evdev_notify_event(struct evdev_client *client) 714{ 715 716 EVDEV_CLIENT_LOCKQ_ASSERT(client); 717 718 if (client->ec_blocked) { 719 client->ec_blocked = false; 720 wakeup(client); 721 } 722 if (client->ec_selected) { 723 client->ec_selected = false; 724 selwakeup(&client->ec_selp); 725 } 726 KNOTE_LOCKED(&client->ec_selp.si_note, 0); 727 728 if (client->ec_async && client->ec_sigio != NULL) 729 pgsigio(&client->ec_sigio, SIGIO, 0); 730} 731 732int 733evdev_cdev_create(struct evdev_dev *evdev) 734{ 735 struct make_dev_args mda; 736 int ret, unit = 0; 737 738 make_dev_args_init(&mda); 739 mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME; 740 mda.mda_devsw = &evdev_cdevsw; 741 mda.mda_uid = UID_ROOT; 742 mda.mda_gid = GID_WHEEL; 743 mda.mda_mode = 0600; 744 mda.mda_si_drv1 = evdev; 745 746 /* Try to coexist with cuse-backed input/event devices */ 747 while ((ret = make_dev_s(&mda, &evdev->ev_cdev, "input/event%d", unit)) 748 == EEXIST) 749 unit++; 750 751 if (ret == 0) 752 evdev->ev_unit = unit; 753 754 return (ret); 755} 756 757int 758evdev_cdev_destroy(struct evdev_dev *evdev) 759{ 760 761 destroy_dev(evdev->ev_cdev); 762 return (0); 763} 764 765static void 766evdev_client_gettime(struct evdev_client *client, struct timeval *tv) 767{ 768 769 switch (client->ec_clock_id) { 770 case EV_CLOCK_BOOTTIME: 771 /* 772 * XXX: FreeBSD does not support true POSIX monotonic clock. 773 * So aliase EV_CLOCK_BOOTTIME to EV_CLOCK_MONOTONIC. 774 */ 775 case EV_CLOCK_MONOTONIC: 776 microuptime(tv); 777 break; 778 779 case EV_CLOCK_REALTIME: 780 default: 781 microtime(tv); 782 break; 783 } 784} 785 786void 787evdev_client_push(struct evdev_client *client, uint16_t type, uint16_t code, 788 int32_t value) 789{ 790 struct timeval time; 791 size_t count, head, tail, ready; 792 793 EVDEV_CLIENT_LOCKQ_ASSERT(client); 794 head = client->ec_buffer_head; 795 tail = client->ec_buffer_tail; 796 ready = client->ec_buffer_ready; 797 count = client->ec_buffer_size; 798 799 /* If queue is full drop its content and place SYN_DROPPED event */ 800 if ((tail + 1) % count == head) { 801 debugf(client, "client %p: buffer overflow", client); 802 803 head = (tail + count - 1) % count; 804 client->ec_buffer[head] = (struct input_event) { 805 .type = EV_SYN, 806 .code = SYN_DROPPED, 807 .value = 0 808 }; 809 /* 810 * XXX: Here is a small race window from now till the end of 811 * report. The queue is empty but client has been already 812 * notified of data readyness. Can be fixed in two ways: 813 * 1. Implement bulk insert so queue lock would not be dropped 814 * till the SYN_REPORT event. 815 * 2. Insert SYN_REPORT just now and skip remaining events 816 */ 817 client->ec_buffer_head = head; 818 client->ec_buffer_ready = head; 819 } 820 821 client->ec_buffer[tail].type = type; 822 client->ec_buffer[tail].code = code; 823 client->ec_buffer[tail].value = value; 824 client->ec_buffer_tail = (tail + 1) % count; 825 826 /* Allow users to read events only after report has been completed */ 827 if (type == EV_SYN && code == SYN_REPORT) { 828 evdev_client_gettime(client, &time); 829 for (; ready != client->ec_buffer_tail; 830 ready = (ready + 1) % count) 831 client->ec_buffer[ready].time = time; 832 client->ec_buffer_ready = client->ec_buffer_tail; 833 } 834} 835 836void 837evdev_client_dumpqueue(struct evdev_client *client) 838{ 839 struct input_event *event; 840 size_t i, head, tail, ready, size; 841 842 head = client->ec_buffer_head; 843 tail = client->ec_buffer_tail; 844 ready = client->ec_buffer_ready; 845 size = client->ec_buffer_size; 846 847 printf("evdev client: %p\n", client); 848 printf("event queue: head=%zu ready=%zu tail=%zu size=%zu\n", 849 head, ready, tail, size); 850 851 printf("queue contents:\n"); 852 853 for (i = 0; i < size; i++) { 854 event = &client->ec_buffer[i]; 855 printf("%zu: ", i); 856 857 if (i < head || i > tail) 858 printf("unused\n"); 859 else 860 printf("type=%d code=%d value=%d ", event->type, 861 event->code, event->value); 862 863 if (i == head) 864 printf("<- head\n"); 865 else if (i == tail) 866 printf("<- tail\n"); 867 else if (i == ready) 868 printf("<- ready\n"); 869 else 870 printf("\n"); 871 } 872} 873 874static void 875evdev_client_filter_queue(struct evdev_client *client, uint16_t type) 876{ 877 struct input_event *event; 878 size_t head, tail, count, i; 879 bool last_was_syn = false; 880 881 EVDEV_CLIENT_LOCKQ(client); 882 883 i = head = client->ec_buffer_head; 884 tail = client->ec_buffer_tail; 885 count = client->ec_buffer_size; 886 client->ec_buffer_ready = client->ec_buffer_tail; 887 888 while (i != client->ec_buffer_tail) { 889 event = &client->ec_buffer[i]; 890 i = (i + 1) % count; 891 892 /* Skip event of given type */ 893 if (event->type == type) 894 continue; 895 896 /* Remove empty SYN_REPORT events */ 897 if (event->type == EV_SYN && event->code == SYN_REPORT) { 898 if (last_was_syn) 899 continue; 900 else 901 client->ec_buffer_ready = (tail + 1) % count; 902 } 903 904 /* Rewrite entry */ 905 memcpy(&client->ec_buffer[tail], event, 906 sizeof(struct input_event)); 907 908 last_was_syn = (event->type == EV_SYN && 909 event->code == SYN_REPORT); 910 911 tail = (tail + 1) % count; 912 } 913 914 client->ec_buffer_head = i; 915 client->ec_buffer_tail = tail; 916 917 EVDEV_CLIENT_UNLOCKQ(client); 918} 919