cdev.c revision 324768
1116742Ssam/*-
2116904Ssam * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
3170360Ssam * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@FreeBSD.org>
4116742Ssam * All rights reserved.
5116742Ssam *
6116742Ssam * Redistribution and use in source and binary forms, with or without
7116742Ssam * modification, are permitted provided that the following conditions
8116742Ssam * are met:
9116742Ssam * 1. Redistributions of source code must retain the above copyright
10116742Ssam *    notice, this list of conditions and the following disclaimer.
11116742Ssam * 2. Redistributions in binary form must reproduce the above copyright
12116742Ssam *    notice, this list of conditions and the following disclaimer in the
13116742Ssam *    documentation and/or other materials provided with the distribution.
14116742Ssam *
15116904Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16116904Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17116904Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18116904Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19116904Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20116904Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21116904Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22116904Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23116904Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24116904Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25116904Ssam * SUCH DAMAGE.
26116742Ssam *
27116742Ssam * $FreeBSD: stable/11/sys/dev/evdev/cdev.c 324768 2017-10-19 20:16:40Z wulf $
28116742Ssam */
29116742Ssam
30116742Ssam#include "opt_evdev.h"
31138568Ssam
32170530Ssam#include <sys/param.h>
33116742Ssam#include <sys/bitstring.h>
34138568Ssam#include <sys/conf.h>
35138568Ssam#include <sys/filio.h>
36138568Ssam#include <sys/fcntl.h>
37138568Ssam#include <sys/kernel.h>
38138568Ssam#include <sys/malloc.h>
39138568Ssam#include <sys/poll.h>
40138568Ssam#include <sys/proc.h>
41138568Ssam#include <sys/selinfo.h>
42138568Ssam#include <sys/systm.h>
43138568Ssam#include <sys/time.h>
44138568Ssam#include <sys/uio.h>
45138568Ssam
46138568Ssam#include <dev/evdev/evdev.h>
47138568Ssam#include <dev/evdev/evdev_private.h>
48138568Ssam#include <dev/evdev/input.h>
49138568Ssam
50138568Ssam#ifdef EVDEV_DEBUG
51138568Ssam#define	debugf(client, fmt, args...)	printf("evdev cdev: "fmt"\n", ##args)
52138568Ssam#else
53138568Ssam#define	debugf(client, fmt, args...)
54138568Ssam#endif
55138568Ssam
56170530Ssam#define	DEF_RING_REPORTS	8
57138568Ssam
58116742Ssamstatic d_open_t		evdev_open;
59116742Ssamstatic d_read_t		evdev_read;
60116742Ssamstatic d_write_t	evdev_write;
61170530Ssamstatic d_ioctl_t	evdev_ioctl;
62138568Ssamstatic d_poll_t		evdev_poll;
63116742Ssamstatic d_kqfilter_t	evdev_kqfilter;
64138568Ssam
65170530Ssamstatic int evdev_kqread(struct knote *kn, long hint);
66170530Ssamstatic void evdev_kqdetach(struct knote *kn);
67170530Ssamstatic void evdev_dtor(void *);
68170530Ssamstatic int evdev_ioctl_eviocgbit(struct evdev_dev *, int, int, caddr_t);
69170530Ssamstatic void evdev_client_filter_queue(struct evdev_client *, uint16_t);
70170530Ssam
71170530Ssamstatic struct cdevsw evdev_cdevsw = {
72170530Ssam	.d_version = D_VERSION,
73116742Ssam	.d_open = evdev_open,
74116742Ssam	.d_read = evdev_read,
75138568Ssam	.d_write = evdev_write,
76138568Ssam	.d_ioctl = evdev_ioctl,
77138568Ssam	.d_poll = evdev_poll,
78116742Ssam	.d_kqfilter = evdev_kqfilter,
79116742Ssam	.d_name = "evdev",
80116742Ssam};
81116742Ssam
82116742Ssamstatic struct filterops evdev_cdev_filterops = {
83116742Ssam	.f_isfd = 1,
84116742Ssam	.f_attach = NULL,
85138568Ssam	.f_detach = evdev_kqdetach,
86138568Ssam	.f_event = evdev_kqread,
87116742Ssam};
88116742Ssam
89116742Ssamstatic int
90120483Ssamevdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
91170530Ssam{
92170530Ssam	struct evdev_dev *evdev = dev->si_drv1;
93170530Ssam	struct evdev_client *client;
94170530Ssam	size_t buffer_size;
95170530Ssam	int ret;
96170530Ssam
97170530Ssam	if (evdev == NULL)
98170530Ssam		return (ENODEV);
99170530Ssam
100170530Ssam	/* Initialize client structure */
101170530Ssam	buffer_size = evdev->ev_report_size * DEF_RING_REPORTS;
102170530Ssam	client = malloc(offsetof(struct evdev_client, ec_buffer) +
103138568Ssam	    sizeof(struct input_event) * buffer_size,
104138568Ssam	    M_EVDEV, M_WAITOK | M_ZERO);
105138568Ssam
106138568Ssam	/* Initialize ring buffer */
107138568Ssam	client->ec_buffer_size = buffer_size;
108147788Ssam	client->ec_buffer_head = 0;
109170530Ssam	client->ec_buffer_tail = 0;
110170530Ssam	client->ec_buffer_ready = 0;
111170530Ssam
112170530Ssam	client->ec_evdev = evdev;
113170530Ssam	mtx_init(&client->ec_buffer_mtx, "evclient", "evdev", MTX_DEF);
114170530Ssam	knlist_init_mtx(&client->ec_selp.si_note, &client->ec_buffer_mtx);
115170530Ssam
116170530Ssam	/* Avoid race with evdev_unregister */
117170530Ssam	EVDEV_LOCK(evdev);
118170530Ssam	if (dev->si_drv1 == NULL)
119170530Ssam		ret = ENODEV;
120167439Ssam	else
121170530Ssam		ret = evdev_register_client(evdev, client);
122170530Ssam
123170530Ssam	if (ret != 0)
124138568Ssam		evdev_revoke_client(client);
125138568Ssam	/*
126138568Ssam	 * Unlock evdev here because non-sleepable lock held
127116742Ssam	 * while calling devfs_set_cdevpriv upsets WITNESS
128116742Ssam	 */
129170530Ssam	EVDEV_UNLOCK(evdev);
130170530Ssam
131170530Ssam	if (!ret)
132116742Ssam		ret = devfs_set_cdevpriv(client, evdev_dtor);
133116742Ssam
134170530Ssam	if (ret != 0) {
135170530Ssam		debugf(client, "cannot register evdev client");
136116742Ssam		evdev_dtor(client);
137116742Ssam	}
138138568Ssam
139170530Ssam	return (ret);
140170530Ssam}
141138568Ssam
142170530Ssamstatic void
143170530Ssamevdev_dtor(void *data)
144170530Ssam{
145170530Ssam	struct evdev_client *client = (struct evdev_client *)data;
146116742Ssam
147170530Ssam	EVDEV_LOCK(client->ec_evdev);
148170530Ssam	if (!client->ec_revoked)
149170530Ssam		evdev_dispose_client(client->ec_evdev, client);
150170530Ssam	EVDEV_UNLOCK(client->ec_evdev);
151170530Ssam
152170530Ssam	knlist_clear(&client->ec_selp.si_note, 0);
153170530Ssam	seldrain(&client->ec_selp);
154116742Ssam	knlist_destroy(&client->ec_selp.si_note);
155170530Ssam	funsetown(&client->ec_sigio);
156170530Ssam	mtx_destroy(&client->ec_buffer_mtx);
157170530Ssam	free(client, M_EVDEV);
158170530Ssam}
159170530Ssam
160170530Ssamstatic int
161170530Ssamevdev_read(struct cdev *dev, struct uio *uio, int ioflag)
162170530Ssam{
163170530Ssam	struct evdev_client *client;
164170530Ssam	struct input_event event;
165170530Ssam	int ret = 0;
166170530Ssam	int remaining;
167170530Ssam
168116742Ssam	ret = devfs_get_cdevpriv((void **)&client);
169116742Ssam	if (ret != 0)
170138568Ssam		return (ret);
171138568Ssam
172116742Ssam	debugf(client, "read %zd bytes by thread %d", uio->uio_resid,
173138568Ssam	    uio->uio_td->td_tid);
174138568Ssam
175116742Ssam	if (client->ec_revoked)
176138568Ssam		return (ENODEV);
177116742Ssam
178170530Ssam	/* Zero-sized reads are allowed for error checking */
179170530Ssam	if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event))
180138568Ssam		return (EINVAL);
181138568Ssam
182138568Ssam	remaining = uio->uio_resid / sizeof(struct input_event);
183138568Ssam
184138568Ssam	EVDEV_CLIENT_LOCKQ(client);
185138568Ssam
186116742Ssam	if (EVDEV_CLIENT_EMPTYQ(client)) {
187116742Ssam		if (ioflag & O_NONBLOCK)
188116742Ssam			ret = EWOULDBLOCK;
189138568Ssam		else {
190116742Ssam			if (remaining != 0) {
191116742Ssam				client->ec_blocked = true;
192116742Ssam				ret = mtx_sleep(client, &client->ec_buffer_mtx,
193116742Ssam				    PCATCH, "evread", 0);
194116742Ssam			}
195116742Ssam		}
196138568Ssam	}
197116742Ssam
198116742Ssam	while (ret == 0 && !EVDEV_CLIENT_EMPTYQ(client) && remaining > 0) {
199116742Ssam		memcpy(&event, &client->ec_buffer[client->ec_buffer_head],
200116742Ssam		    sizeof(struct input_event));
201116742Ssam		client->ec_buffer_head =
202144618Ssam		    (client->ec_buffer_head + 1) % client->ec_buffer_size;
203144618Ssam		remaining--;
204144618Ssam
205127877Ssam		EVDEV_CLIENT_UNLOCKQ(client);
206138568Ssam		ret = uiomove(&event, sizeof(struct input_event), uio);
207138568Ssam		EVDEV_CLIENT_LOCKQ(client);
208138568Ssam	}
209138568Ssam
210138568Ssam	EVDEV_CLIENT_UNLOCKQ(client);
211116742Ssam
212148302Ssam	return (ret);
213148302Ssam}
214138568Ssam
215156358Ssamstatic int
216144618Ssamevdev_write(struct cdev *dev, struct uio *uio, int ioflag)
217144618Ssam{
218148306Ssam	struct evdev_dev *evdev = dev->si_drv1;
219170530Ssam	struct evdev_client *client;
220170530Ssam	struct input_event event;
221170530Ssam	int ret = 0;
222144618Ssam
223138568Ssam	ret = devfs_get_cdevpriv((void **)&client);
224138568Ssam	if (ret != 0)
225138568Ssam		return (ret);
226138568Ssam
227138568Ssam	debugf(client, "write %zd bytes by thread %d", uio->uio_resid,
228138568Ssam	    uio->uio_td->td_tid);
229138568Ssam
230138568Ssam	if (client->ec_revoked || evdev == NULL)
231138568Ssam		return (ENODEV);
232138568Ssam
233138568Ssam	if (uio->uio_resid % sizeof(struct input_event) != 0) {
234138568Ssam		debugf(client, "write size not multiple of input_event size");
235170530Ssam		return (EINVAL);
236170530Ssam	}
237138568Ssam
238138568Ssam	while (uio->uio_resid > 0 && ret == 0) {
239138568Ssam		ret = uiomove(&event, sizeof(struct input_event), uio);
240138568Ssam		if (ret == 0)
241138568Ssam			ret = evdev_inject_event(evdev, event.type, event.code,
242138568Ssam			    event.value);
243144618Ssam	}
244170530Ssam
245148777Ssam	return (ret);
246170530Ssam}
247144618Ssam
248170530Ssamstatic int
249138568Ssamevdev_poll(struct cdev *dev, int events, struct thread *td)
250144618Ssam{
251138568Ssam	struct evdev_client *client;
252170530Ssam	int ret;
253170530Ssam	int revents = 0;
254138568Ssam
255170530Ssam	ret = devfs_get_cdevpriv((void **)&client);
256170530Ssam	if (ret != 0)
257138568Ssam		return (POLLNVAL);
258148863Ssam
259148863Ssam	debugf(client, "poll by thread %d", td->td_tid);
260170530Ssam
261148863Ssam	if (client->ec_revoked)
262170530Ssam		return (POLLHUP);
263170530Ssam
264170530Ssam	if (events & (POLLIN | POLLRDNORM)) {
265138568Ssam		EVDEV_CLIENT_LOCKQ(client);
266170530Ssam		if (!EVDEV_CLIENT_EMPTYQ(client))
267170530Ssam			revents = events & (POLLIN | POLLRDNORM);
268170530Ssam		else {
269144618Ssam			client->ec_selected = true;
270170530Ssam			selrecord(td, &client->ec_selp);
271170530Ssam		}
272138568Ssam		EVDEV_CLIENT_UNLOCKQ(client);
273138568Ssam	}
274138568Ssam
275138568Ssam	return (revents);
276138568Ssam}
277138568Ssam
278138568Ssamstatic int
279148863Ssamevdev_kqfilter(struct cdev *dev, struct knote *kn)
280148863Ssam{
281138568Ssam	struct evdev_client *client;
282138568Ssam	int ret;
283138568Ssam
284138568Ssam	ret = devfs_get_cdevpriv((void **)&client);
285138568Ssam	if (ret != 0)
286144618Ssam		return (ret);
287170530Ssam
288170530Ssam	if (client->ec_revoked)
289170530Ssam		return (ENODEV);
290170530Ssam
291148863Ssam	switch(kn->kn_filter) {
292170530Ssam	case EVFILT_READ:
293170530Ssam		kn->kn_fop = &evdev_cdev_filterops;
294170530Ssam		break;
295144618Ssam	default:
296170530Ssam		return(EINVAL);
297170530Ssam	}
298138568Ssam	kn->kn_hook = (caddr_t)client;
299148863Ssam
300170530Ssam	knlist_add(&client->ec_selp.si_note, kn, 0);
301138568Ssam	return (0);
302116742Ssam}
303144618Ssam
304116742Ssamstatic int
305116742Ssamevdev_kqread(struct knote *kn, long hint)
306144618Ssam{
307138568Ssam	struct evdev_client *client;
308144618Ssam	int ret;
309138568Ssam
310144618Ssam	client = (struct evdev_client *)kn->kn_hook;
311170530Ssam
312170530Ssam	EVDEV_CLIENT_LOCKQ_ASSERT(client);
313153073Ssam
314153073Ssam	if (client->ec_revoked) {
315153073Ssam		kn->kn_flags |= EV_EOF;
316148936Ssam		ret = 1;
317148936Ssam	} else {
318148936Ssam		kn->kn_data = EVDEV_CLIENT_SIZEQ(client) *
319170530Ssam		    sizeof(struct input_event);
320170530Ssam		ret = !EVDEV_CLIENT_EMPTYQ(client);
321170530Ssam	}
322170530Ssam	return (ret);
323116742Ssam}
324
325static void
326evdev_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
334static int
335evdev_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
583static int
584evdev_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
645void
646evdev_revoke_client(struct evdev_client *client)
647{
648
649	EVDEV_LOCK_ASSERT(client->ec_evdev);
650
651	client->ec_revoked = true;
652}
653
654void
655evdev_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
674int
675evdev_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
699int
700evdev_cdev_destroy(struct evdev_dev *evdev)
701{
702
703	destroy_dev(evdev->ev_cdev);
704	return (0);
705}
706
707static void
708evdev_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
728void
729evdev_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
778void
779evdev_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
816static void
817evdev_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