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