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