]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/evdev/cdev.c
Import DTS files from Linux 4.18
[FreeBSD/FreeBSD.git] / sys / dev / evdev / cdev.c
1 /*-
2  * Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
3  * Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #include "opt_evdev.h"
31
32 #include <sys/param.h>
33 #include <sys/bitstring.h>
34 #include <sys/conf.h>
35 #include <sys/filio.h>
36 #include <sys/fcntl.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/poll.h>
40 #include <sys/proc.h>
41 #include <sys/selinfo.h>
42 #include <sys/systm.h>
43 #include <sys/time.h>
44 #include <sys/uio.h>
45
46 #include <dev/evdev/evdev.h>
47 #include <dev/evdev/evdev_private.h>
48 #include <dev/evdev/input.h>
49
50 #ifdef EVDEV_DEBUG
51 #define debugf(client, fmt, args...)    printf("evdev cdev: "fmt"\n", ##args)
52 #else
53 #define debugf(client, fmt, args...)
54 #endif
55
56 #define DEF_RING_REPORTS        8
57
58 static d_open_t         evdev_open;
59 static d_read_t         evdev_read;
60 static d_write_t        evdev_write;
61 static d_ioctl_t        evdev_ioctl;
62 static d_poll_t         evdev_poll;
63 static d_kqfilter_t     evdev_kqfilter;
64
65 static int evdev_kqread(struct knote *kn, long hint);
66 static void evdev_kqdetach(struct knote *kn);
67 static void evdev_dtor(void *);
68 static int evdev_ioctl_eviocgbit(struct evdev_dev *, int, int, caddr_t);
69 static void evdev_client_filter_queue(struct evdev_client *, uint16_t);
70
71 static struct cdevsw evdev_cdevsw = {
72         .d_version = D_VERSION,
73         .d_open = evdev_open,
74         .d_read = evdev_read,
75         .d_write = evdev_write,
76         .d_ioctl = evdev_ioctl,
77         .d_poll = evdev_poll,
78         .d_kqfilter = evdev_kqfilter,
79         .d_name = "evdev",
80 };
81
82 static struct filterops evdev_cdev_filterops = {
83         .f_isfd = 1,
84         .f_attach = NULL,
85         .f_detach = evdev_kqdetach,
86         .f_event = evdev_kqread,
87 };
88
89 static int
90 evdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
91 {
92         struct evdev_dev *evdev = dev->si_drv1;
93         struct evdev_client *client;
94         size_t buffer_size;
95         int ret;
96
97         if (evdev == NULL)
98                 return (ENODEV);
99
100         /* Initialize client structure */
101         buffer_size = evdev->ev_report_size * DEF_RING_REPORTS;
102         client = malloc(offsetof(struct evdev_client, ec_buffer) +
103             sizeof(struct input_event) * buffer_size,
104             M_EVDEV, M_WAITOK | M_ZERO);
105
106         /* Initialize ring buffer */
107         client->ec_buffer_size = buffer_size;
108         client->ec_buffer_head = 0;
109         client->ec_buffer_tail = 0;
110         client->ec_buffer_ready = 0;
111
112         client->ec_evdev = evdev;
113         mtx_init(&client->ec_buffer_mtx, "evclient", "evdev", MTX_DEF);
114         knlist_init_mtx(&client->ec_selp.si_note, &client->ec_buffer_mtx);
115
116         /* Avoid race with evdev_unregister */
117         EVDEV_LOCK(evdev);
118         if (dev->si_drv1 == NULL)
119                 ret = ENODEV;
120         else
121                 ret = evdev_register_client(evdev, client);
122
123         if (ret != 0)
124                 evdev_revoke_client(client);
125         /*
126          * Unlock evdev here because non-sleepable lock held 
127          * while calling devfs_set_cdevpriv upsets WITNESS
128          */
129         EVDEV_UNLOCK(evdev);
130
131         if (!ret)
132                 ret = devfs_set_cdevpriv(client, evdev_dtor);
133
134         if (ret != 0) {
135                 debugf(client, "cannot register evdev client");
136                 evdev_dtor(client);
137         }
138
139         return (ret);
140 }
141
142 static void
143 evdev_dtor(void *data)
144 {
145         struct evdev_client *client = (struct evdev_client *)data;
146
147         EVDEV_LOCK(client->ec_evdev);
148         if (!client->ec_revoked)
149                 evdev_dispose_client(client->ec_evdev, client);
150         EVDEV_UNLOCK(client->ec_evdev);
151
152         knlist_clear(&client->ec_selp.si_note, 0);
153         seldrain(&client->ec_selp);
154         knlist_destroy(&client->ec_selp.si_note);
155         funsetown(&client->ec_sigio);
156         mtx_destroy(&client->ec_buffer_mtx);
157         free(client, M_EVDEV);
158 }
159
160 static int
161 evdev_read(struct cdev *dev, struct uio *uio, int ioflag)
162 {
163         struct evdev_client *client;
164         struct input_event event;
165         int ret = 0;
166         int remaining;
167
168         ret = devfs_get_cdevpriv((void **)&client);
169         if (ret != 0)
170                 return (ret);
171
172         debugf(client, "read %zd bytes by thread %d", uio->uio_resid,
173             uio->uio_td->td_tid);
174
175         if (client->ec_revoked)
176                 return (ENODEV);
177
178         /* Zero-sized reads are allowed for error checking */
179         if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event))
180                 return (EINVAL);
181
182         remaining = uio->uio_resid / sizeof(struct input_event);
183
184         EVDEV_CLIENT_LOCKQ(client);
185
186         if (EVDEV_CLIENT_EMPTYQ(client)) {
187                 if (ioflag & O_NONBLOCK)
188                         ret = EWOULDBLOCK;
189                 else {
190                         if (remaining != 0) {
191                                 client->ec_blocked = true;
192                                 ret = mtx_sleep(client, &client->ec_buffer_mtx,
193                                     PCATCH, "evread", 0);
194                         }
195                 }
196         }
197
198         while (ret == 0 && !EVDEV_CLIENT_EMPTYQ(client) && remaining > 0) {
199                 memcpy(&event, &client->ec_buffer[client->ec_buffer_head],
200                     sizeof(struct input_event));
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 }