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