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