FreeBSD/Linux Kernel Cross Reference
sys/dev/evdev/cdev.c
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 COMPAT_FREEBSD32
51 #include <sys/mount.h>
52 #include <sys/sysent.h>
53 #include <compat/freebsd32/freebsd32.h>
54 struct 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
70 static d_open_t evdev_open;
71 static d_read_t evdev_read;
72 static d_write_t evdev_write;
73 static d_ioctl_t evdev_ioctl;
74 static d_poll_t evdev_poll;
75 static d_kqfilter_t evdev_kqfilter;
76
77 static int evdev_kqread(struct knote *kn, long hint);
78 static void evdev_kqdetach(struct knote *kn);
79 static void evdev_dtor(void *);
80 static int evdev_ioctl_eviocgbit(struct evdev_dev *, int, int, caddr_t);
81 static void evdev_client_filter_queue(struct evdev_client *, uint16_t);
82
83 static 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
94 static 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
101 static int
102 evdev_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
154 static void
155 evdev_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
172 static int
173 evdev_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
253 static int
254 evdev_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
306 static int
307 evdev_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
336 static int
337 evdev_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
362 static int
363 evdev_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
383 static void
384 evdev_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
392 static int
393 evdev_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 /*
411 * Fix evdev state corrupted with discarding of kdb events.
412 * EVIOCGKEY and EVIOCGLED ioctls can suffer from this.
413 */
414 if (evdev->ev_kdb_active) {
415 EVDEV_LOCK(evdev);
416 if (evdev->ev_kdb_active) {
417 evdev->ev_kdb_active = false;
418 evdev_restore_after_kdb(evdev);
419 }
420 EVDEV_UNLOCK(evdev);
421 }
422
423 /* file I/O ioctl handling */
424 switch (cmd) {
425 case FIOSETOWN:
426 return (fsetown(*(int *)data, &client->ec_sigio));
427
428 case FIOGETOWN:
429 *(int *)data = fgetown(&client->ec_sigio);
430 return (0);
431
432 case FIONBIO:
433 return (0);
434
435 case FIOASYNC:
436 if (*(int *)data)
437 client->ec_async = true;
438 else
439 client->ec_async = false;
440
441 return (0);
442
443 case FIONREAD:
444 EVDEV_CLIENT_LOCKQ(client);
445 *(int *)data =
446 EVDEV_CLIENT_SIZEQ(client) * sizeof(struct input_event);
447 EVDEV_CLIENT_UNLOCKQ(client);
448 return (0);
449 }
450
451 len = IOCPARM_LEN(cmd);
452 debugf(client, "ioctl called: cmd=0x%08lx, data=%p", cmd, data);
453
454 /* evdev fixed-length ioctls handling */
455 switch (cmd) {
456 case EVIOCGVERSION:
457 *(int *)data = EV_VERSION;
458 return (0);
459
460 case EVIOCGID:
461 debugf(client, "EVIOCGID: bus=%d vendor=0x%04x product=0x%04x",
462 evdev->ev_id.bustype, evdev->ev_id.vendor,
463 evdev->ev_id.product);
464 memcpy(data, &evdev->ev_id, sizeof(struct input_id));
465 return (0);
466
467 case EVIOCGREP:
468 if (!evdev_event_supported(evdev, EV_REP))
469 return (ENOTSUP);
470
471 memcpy(data, evdev->ev_rep, sizeof(evdev->ev_rep));
472 return (0);
473
474 case EVIOCSREP:
475 if (!evdev_event_supported(evdev, EV_REP))
476 return (ENOTSUP);
477
478 evdev_inject_event(evdev, EV_REP, REP_DELAY, ((int *)data)[0]);
479 evdev_inject_event(evdev, EV_REP, REP_PERIOD,
480 ((int *)data)[1]);
481 return (0);
482
483 case EVIOCGKEYCODE:
484 /* Fake unsupported ioctl */
485 return (0);
486
487 case EVIOCGKEYCODE_V2:
488 if (evdev->ev_methods == NULL ||
489 evdev->ev_methods->ev_get_keycode == NULL)
490 return (ENOTSUP);
491
492 ke = (struct input_keymap_entry *)data;
493 evdev->ev_methods->ev_get_keycode(evdev, ke);
494 return (0);
495
496 case EVIOCSKEYCODE:
497 /* Fake unsupported ioctl */
498 return (0);
499
500 case EVIOCSKEYCODE_V2:
501 if (evdev->ev_methods == NULL ||
502 evdev->ev_methods->ev_set_keycode == NULL)
503 return (ENOTSUP);
504
505 ke = (struct input_keymap_entry *)data;
506 evdev->ev_methods->ev_set_keycode(evdev, ke);
507 return (0);
508
509 case EVIOCGABS(0) ... EVIOCGABS(ABS_MAX):
510 if (evdev->ev_absinfo == NULL)
511 return (EINVAL);
512
513 memcpy(data, &evdev->ev_absinfo[cmd - EVIOCGABS(0)],
514 sizeof(struct input_absinfo));
515 return (0);
516
517 case EVIOCSABS(0) ... EVIOCSABS(ABS_MAX):
518 if (evdev->ev_absinfo == NULL)
519 return (EINVAL);
520
521 code = cmd - EVIOCSABS(0);
522 /* mt-slot number can not be changed */
523 if (code == ABS_MT_SLOT)
524 return (EINVAL);
525
526 EVDEV_LOCK(evdev);
527 evdev_set_absinfo(evdev, code, (struct input_absinfo *)data);
528 EVDEV_UNLOCK(evdev);
529 return (0);
530
531 case EVIOCSFF:
532 case EVIOCRMFF:
533 case EVIOCGEFFECTS:
534 /* Fake unsupported ioctls */
535 return (0);
536
537 case EVIOCGRAB:
538 EVDEV_LOCK(evdev);
539 if (*(int *)data)
540 ret = evdev_grab_client(evdev, client);
541 else
542 ret = evdev_release_client(evdev, client);
543 EVDEV_UNLOCK(evdev);
544 return (ret);
545
546 case EVIOCREVOKE:
547 if (*(int *)data != 0)
548 return (EINVAL);
549
550 EVDEV_LOCK(evdev);
551 if (dev->si_drv1 != NULL && !client->ec_revoked) {
552 evdev_dispose_client(evdev, client);
553 evdev_revoke_client(client);
554 }
555 EVDEV_UNLOCK(evdev);
556 return (0);
557
558 case EVIOCSCLOCKID:
559 switch (*(int *)data) {
560 case CLOCK_REALTIME:
561 client->ec_clock_id = EV_CLOCK_REALTIME;
562 return (0);
563 case CLOCK_MONOTONIC:
564 client->ec_clock_id = EV_CLOCK_MONOTONIC;
565 return (0);
566 default:
567 return (EINVAL);
568 }
569 }
570
571 /* evdev variable-length ioctls handling */
572 switch (IOCBASECMD(cmd)) {
573 case EVIOCGNAME(0):
574 strlcpy(data, evdev->ev_name, len);
575 return (0);
576
577 case EVIOCGPHYS(0):
578 if (evdev->ev_shortname[0] == 0)
579 return (ENOENT);
580
581 strlcpy(data, evdev->ev_shortname, len);
582 return (0);
583
584 case EVIOCGUNIQ(0):
585 if (evdev->ev_serial[0] == 0)
586 return (ENOENT);
587
588 strlcpy(data, evdev->ev_serial, len);
589 return (0);
590
591 case EVIOCGPROP(0):
592 limit = MIN(len, bitstr_size(INPUT_PROP_CNT));
593 memcpy(data, evdev->ev_prop_flags, limit);
594 return (0);
595
596 case EVIOCGMTSLOTS(0):
597 if (evdev->ev_mt == NULL)
598 return (EINVAL);
599 if (len < sizeof(uint32_t))
600 return (EINVAL);
601 code = *(uint32_t *)data;
602 if (!ABS_IS_MT(code))
603 return (EINVAL);
604
605 nvalues =
606 MIN(len / sizeof(int32_t) - 1, MAXIMAL_MT_SLOT(evdev) + 1);
607 for (int i = 0; i < nvalues; i++)
608 ((int32_t *)data)[i + 1] =
609 evdev_get_mt_value(evdev, i, code);
610 return (0);
611
612 case EVIOCGKEY(0):
613 limit = MIN(len, bitstr_size(KEY_CNT));
614 EVDEV_LOCK(evdev);
615 evdev_client_filter_queue(client, EV_KEY);
616 memcpy(data, evdev->ev_key_states, limit);
617 EVDEV_UNLOCK(evdev);
618 return (0);
619
620 case EVIOCGLED(0):
621 limit = MIN(len, bitstr_size(LED_CNT));
622 EVDEV_LOCK(evdev);
623 evdev_client_filter_queue(client, EV_LED);
624 memcpy(data, evdev->ev_led_states, limit);
625 EVDEV_UNLOCK(evdev);
626 return (0);
627
628 case EVIOCGSND(0):
629 limit = MIN(len, bitstr_size(SND_CNT));
630 EVDEV_LOCK(evdev);
631 evdev_client_filter_queue(client, EV_SND);
632 memcpy(data, evdev->ev_snd_states, limit);
633 EVDEV_UNLOCK(evdev);
634 return (0);
635
636 case EVIOCGSW(0):
637 limit = MIN(len, bitstr_size(SW_CNT));
638 EVDEV_LOCK(evdev);
639 evdev_client_filter_queue(client, EV_SW);
640 memcpy(data, evdev->ev_sw_states, limit);
641 EVDEV_UNLOCK(evdev);
642 return (0);
643
644 case EVIOCGBIT(0, 0) ... EVIOCGBIT(EV_MAX, 0):
645 type_num = IOCBASECMD(cmd) - EVIOCGBIT(0, 0);
646 debugf(client, "EVIOCGBIT(%d): data=%p, len=%d", type_num,
647 data, len);
648 return (evdev_ioctl_eviocgbit(evdev, type_num, len, data));
649 }
650
651 return (EINVAL);
652 }
653
654 static int
655 evdev_ioctl_eviocgbit(struct evdev_dev *evdev, int type, int len, caddr_t data)
656 {
657 unsigned long *bitmap;
658 int limit;
659
660 switch (type) {
661 case 0:
662 bitmap = evdev->ev_type_flags;
663 limit = EV_CNT;
664 break;
665 case EV_KEY:
666 bitmap = evdev->ev_key_flags;
667 limit = KEY_CNT;
668 break;
669 case EV_REL:
670 bitmap = evdev->ev_rel_flags;
671 limit = REL_CNT;
672 break;
673 case EV_ABS:
674 bitmap = evdev->ev_abs_flags;
675 limit = ABS_CNT;
676 break;
677 case EV_MSC:
678 bitmap = evdev->ev_msc_flags;
679 limit = MSC_CNT;
680 break;
681 case EV_LED:
682 bitmap = evdev->ev_led_flags;
683 limit = LED_CNT;
684 break;
685 case EV_SND:
686 bitmap = evdev->ev_snd_flags;
687 limit = SND_CNT;
688 break;
689 case EV_SW:
690 bitmap = evdev->ev_sw_flags;
691 limit = SW_CNT;
692 break;
693 case EV_FF:
694 /*
695 * We don't support EV_FF now, so let's
696 * just fake it returning only zeros.
697 */
698 bzero(data, len);
699 return (0);
700 default:
701 return (ENOTTY);
702 }
703
704 /*
705 * Clear ioctl data buffer in case it's bigger than
706 * bitmap size
707 */
708 bzero(data, len);
709
710 limit = bitstr_size(limit);
711 len = MIN(limit, len);
712 memcpy(data, bitmap, len);
713 return (0);
714 }
715
716 void
717 evdev_revoke_client(struct evdev_client *client)
718 {
719
720 EVDEV_LOCK_ASSERT(client->ec_evdev);
721
722 client->ec_revoked = true;
723 }
724
725 void
726 evdev_notify_event(struct evdev_client *client)
727 {
728
729 EVDEV_CLIENT_LOCKQ_ASSERT(client);
730
731 if (client->ec_blocked) {
732 client->ec_blocked = false;
733 wakeup(client);
734 }
735 if (client->ec_selected) {
736 client->ec_selected = false;
737 selwakeup(&client->ec_selp);
738 }
739 KNOTE_LOCKED(&client->ec_selp.si_note, 0);
740
741 if (client->ec_async && client->ec_sigio != NULL)
742 pgsigio(&client->ec_sigio, SIGIO, 0);
743 }
744
745 int
746 evdev_cdev_create(struct evdev_dev *evdev)
747 {
748 struct make_dev_args mda;
749 int ret, unit = 0;
750
751 make_dev_args_init(&mda);
752 mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
753 mda.mda_devsw = &evdev_cdevsw;
754 mda.mda_uid = UID_ROOT;
755 mda.mda_gid = GID_WHEEL;
756 mda.mda_mode = 0600;
757 mda.mda_si_drv1 = evdev;
758
759 /* Try to coexist with cuse-backed input/event devices */
760 while ((ret = make_dev_s(&mda, &evdev->ev_cdev, "input/event%d", unit))
761 == EEXIST)
762 unit++;
763
764 if (ret == 0)
765 evdev->ev_unit = unit;
766
767 return (ret);
768 }
769
770 int
771 evdev_cdev_destroy(struct evdev_dev *evdev)
772 {
773
774 destroy_dev(evdev->ev_cdev);
775 return (0);
776 }
777
778 static void
779 evdev_client_gettime(struct evdev_client *client, struct timeval *tv)
780 {
781
782 switch (client->ec_clock_id) {
783 case EV_CLOCK_BOOTTIME:
784 /*
785 * XXX: FreeBSD does not support true POSIX monotonic clock.
786 * So aliase EV_CLOCK_BOOTTIME to EV_CLOCK_MONOTONIC.
787 */
788 case EV_CLOCK_MONOTONIC:
789 microuptime(tv);
790 break;
791
792 case EV_CLOCK_REALTIME:
793 default:
794 microtime(tv);
795 break;
796 }
797 }
798
799 void
800 evdev_client_push(struct evdev_client *client, uint16_t type, uint16_t code,
801 int32_t value)
802 {
803 struct timeval time;
804 size_t count, head, tail, ready;
805
806 EVDEV_CLIENT_LOCKQ_ASSERT(client);
807 head = client->ec_buffer_head;
808 tail = client->ec_buffer_tail;
809 ready = client->ec_buffer_ready;
810 count = client->ec_buffer_size;
811
812 /* If queue is full drop its content and place SYN_DROPPED event */
813 if ((tail + 1) % count == head) {
814 debugf(client, "client %p: buffer overflow", client);
815
816 head = (tail + count - 1) % count;
817 client->ec_buffer[head] = (struct input_event) {
818 .type = EV_SYN,
819 .code = SYN_DROPPED,
820 .value = 0
821 };
822 /*
823 * XXX: Here is a small race window from now till the end of
824 * report. The queue is empty but client has been already
825 * notified of data readyness. Can be fixed in two ways:
826 * 1. Implement bulk insert so queue lock would not be dropped
827 * till the SYN_REPORT event.
828 * 2. Insert SYN_REPORT just now and skip remaining events
829 */
830 client->ec_buffer_head = head;
831 client->ec_buffer_ready = head;
832 }
833
834 client->ec_buffer[tail].type = type;
835 client->ec_buffer[tail].code = code;
836 client->ec_buffer[tail].value = value;
837 client->ec_buffer_tail = (tail + 1) % count;
838
839 /* Allow users to read events only after report has been completed */
840 if (type == EV_SYN && code == SYN_REPORT) {
841 evdev_client_gettime(client, &time);
842 for (; ready != client->ec_buffer_tail;
843 ready = (ready + 1) % count)
844 client->ec_buffer[ready].time = time;
845 client->ec_buffer_ready = client->ec_buffer_tail;
846 }
847 }
848
849 void
850 evdev_client_dumpqueue(struct evdev_client *client)
851 {
852 struct input_event *event;
853 size_t i, head, tail, ready, size;
854
855 head = client->ec_buffer_head;
856 tail = client->ec_buffer_tail;
857 ready = client->ec_buffer_ready;
858 size = client->ec_buffer_size;
859
860 printf("evdev client: %p\n", client);
861 printf("event queue: head=%zu ready=%zu tail=%zu size=%zu\n",
862 head, ready, tail, size);
863
864 printf("queue contents:\n");
865
866 for (i = 0; i < size; i++) {
867 event = &client->ec_buffer[i];
868 printf("%zu: ", i);
869
870 if (i < head || i > tail)
871 printf("unused\n");
872 else
873 printf("type=%d code=%d value=%d ", event->type,
874 event->code, event->value);
875
876 if (i == head)
877 printf("<- head\n");
878 else if (i == tail)
879 printf("<- tail\n");
880 else if (i == ready)
881 printf("<- ready\n");
882 else
883 printf("\n");
884 }
885 }
886
887 static void
888 evdev_client_filter_queue(struct evdev_client *client, uint16_t type)
889 {
890 struct input_event *event;
891 size_t head, tail, count, i;
892 bool last_was_syn = false;
893
894 EVDEV_CLIENT_LOCKQ(client);
895
896 i = head = client->ec_buffer_head;
897 tail = client->ec_buffer_tail;
898 count = client->ec_buffer_size;
899 client->ec_buffer_ready = client->ec_buffer_tail;
900
901 while (i != client->ec_buffer_tail) {
902 event = &client->ec_buffer[i];
903 i = (i + 1) % count;
904
905 /* Skip event of given type */
906 if (event->type == type)
907 continue;
908
909 /* Remove empty SYN_REPORT events */
910 if (event->type == EV_SYN && event->code == SYN_REPORT) {
911 if (last_was_syn)
912 continue;
913 else
914 client->ec_buffer_ready = (tail + 1) % count;
915 }
916
917 /* Rewrite entry */
918 memcpy(&client->ec_buffer[tail], event,
919 sizeof(struct input_event));
920
921 last_was_syn = (event->type == EV_SYN &&
922 event->code == SYN_REPORT);
923
924 tail = (tail + 1) % count;
925 }
926
927 client->ec_buffer_head = i;
928 client->ec_buffer_tail = tail;
929
930 EVDEV_CLIENT_UNLOCKQ(client);
931 }
Cache object: f424dc780e92d3e0754988c7968967e2
|