]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/evdev/uinput.c
Merge bmake-20170510
[FreeBSD/FreeBSD.git] / sys / dev / evdev / uinput.c
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/systm.h>
34 #include <sys/param.h>
35 #include <sys/fcntl.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/conf.h>
39 #include <sys/uio.h>
40 #include <sys/proc.h>
41 #include <sys/poll.h>
42 #include <sys/selinfo.h>
43 #include <sys/malloc.h>
44 #include <sys/lock.h>
45 #include <sys/sx.h>
46
47 #include <dev/evdev/input.h>
48 #include <dev/evdev/uinput.h>
49 #include <dev/evdev/evdev.h>
50 #include <dev/evdev/evdev_private.h>
51
52 #ifdef UINPUT_DEBUG
53 #define debugf(state, fmt, args...)     printf("uinput: " fmt "\n", ##args)
54 #else
55 #define debugf(state, fmt, args...)
56 #endif
57
58 #define UINPUT_BUFFER_SIZE      16
59
60 #define UINPUT_LOCK(state)              sx_xlock(&(state)->ucs_lock)
61 #define UINPUT_UNLOCK(state)            sx_unlock(&(state)->ucs_lock)
62 #define UINPUT_LOCK_ASSERT(state)       sx_assert(&(state)->ucs_lock, SA_LOCKED)
63 #define UINPUT_EMPTYQ(state) \
64     ((state)->ucs_buffer_head == (state)->ucs_buffer_tail)
65
66 enum uinput_state
67 {
68         UINPUT_NEW = 0,
69         UINPUT_CONFIGURED,
70         UINPUT_RUNNING
71 };
72
73 static evdev_event_t    uinput_ev_event;
74
75 static d_open_t         uinput_open;
76 static d_read_t         uinput_read;
77 static d_write_t        uinput_write;
78 static d_ioctl_t        uinput_ioctl;
79 static d_poll_t         uinput_poll;
80 static d_kqfilter_t     uinput_kqfilter;
81 static void uinput_dtor(void *);
82
83 static int uinput_kqread(struct knote *kn, long hint);
84 static void uinput_kqdetach(struct knote *kn);
85
86 static struct cdevsw uinput_cdevsw = {
87         .d_version = D_VERSION,
88         .d_open = uinput_open,
89         .d_read = uinput_read,
90         .d_write = uinput_write,
91         .d_ioctl = uinput_ioctl,
92         .d_poll = uinput_poll,
93         .d_kqfilter = uinput_kqfilter,
94         .d_name = "uinput",
95 };
96
97 static struct cdev *uinput_cdev;
98
99 static struct evdev_methods uinput_ev_methods = {
100         .ev_open = NULL,
101         .ev_close = NULL,
102         .ev_event = uinput_ev_event,
103 };
104
105 static struct filterops uinput_filterops = {
106         .f_isfd = 1,
107         .f_attach = NULL,
108         .f_detach = uinput_kqdetach,
109         .f_event = uinput_kqread,
110 };
111
112 struct uinput_cdev_state
113 {
114         enum uinput_state       ucs_state;
115         struct evdev_dev *      ucs_evdev;
116         struct sx               ucs_lock;
117         size_t                  ucs_buffer_head;
118         size_t                  ucs_buffer_tail;
119         struct selinfo          ucs_selp;
120         bool                    ucs_blocked;
121         bool                    ucs_selected;
122         struct input_event      ucs_buffer[UINPUT_BUFFER_SIZE];
123 };
124
125 static void uinput_enqueue_event(struct uinput_cdev_state *, uint16_t,
126     uint16_t, int32_t);
127 static int uinput_setup_provider(struct uinput_cdev_state *,
128     struct uinput_user_dev *);
129 static int uinput_cdev_create(void);
130 static void uinput_notify(struct uinput_cdev_state *);
131
132 static void
133 uinput_knllock(void *arg)
134 {
135         struct sx *sx = arg;
136
137         sx_xlock(sx);
138 }
139
140 static void
141 uinput_knlunlock(void *arg)
142 {
143         struct sx *sx = arg;
144
145         sx_unlock(sx);
146 }
147
148 static void
149 uinput_knl_assert_locked(void *arg)
150 {
151
152         sx_assert((struct sx*)arg, SA_XLOCKED);
153 }
154
155 static void
156 uinput_knl_assert_unlocked(void *arg)
157 {
158
159         sx_assert((struct sx*)arg, SA_UNLOCKED);
160 }
161
162 static void
163 uinput_ev_event(struct evdev_dev *evdev, void *softc, uint16_t type,
164     uint16_t code, int32_t value)
165 {
166         struct uinput_cdev_state *state = softc;
167
168         if (type == EV_LED)
169                 evdev_push_event(evdev, type, code, value);
170
171         UINPUT_LOCK(state);
172         if (state->ucs_state == UINPUT_RUNNING) {
173                 uinput_enqueue_event(state, type, code, value);
174                 uinput_notify(state);
175         }
176         UINPUT_UNLOCK(state);
177 }
178
179 static void
180 uinput_enqueue_event(struct uinput_cdev_state *state, uint16_t type,
181     uint16_t code, int32_t value)
182 {
183         size_t head, tail;
184
185         UINPUT_LOCK_ASSERT(state);
186
187         head = state->ucs_buffer_head;
188         tail = (state->ucs_buffer_tail + 1) % UINPUT_BUFFER_SIZE;
189
190         microtime(&state->ucs_buffer[tail].time);
191         state->ucs_buffer[tail].type = type;
192         state->ucs_buffer[tail].code = code;
193         state->ucs_buffer[tail].value = value;
194         state->ucs_buffer_tail = tail;
195
196         /* If queue is full remove oldest event */
197         if (tail == head) {
198                 debugf(state, "state %p: buffer overflow", state);
199
200                 head = (head + 1) % UINPUT_BUFFER_SIZE;
201                 state->ucs_buffer_head = head;
202         }
203 }
204
205 static int
206 uinput_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
207 {
208         struct uinput_cdev_state *state;
209
210         state = malloc(sizeof(struct uinput_cdev_state), M_EVDEV,
211             M_WAITOK | M_ZERO);
212         state->ucs_evdev = evdev_alloc();
213
214         sx_init(&state->ucs_lock, "uinput");
215         knlist_init(&state->ucs_selp.si_note, &state->ucs_lock, uinput_knllock,
216             uinput_knlunlock, uinput_knl_assert_locked,
217             uinput_knl_assert_unlocked);
218
219         devfs_set_cdevpriv(state, uinput_dtor);
220         return (0);
221 }
222
223 static void
224 uinput_dtor(void *data)
225 {
226         struct uinput_cdev_state *state = (struct uinput_cdev_state *)data;
227
228         evdev_free(state->ucs_evdev);
229
230         knlist_clear(&state->ucs_selp.si_note, 0);
231         seldrain(&state->ucs_selp);
232         knlist_destroy(&state->ucs_selp.si_note);
233         sx_destroy(&state->ucs_lock);
234         free(data, M_EVDEV);
235 }
236
237 static int
238 uinput_read(struct cdev *dev, struct uio *uio, int ioflag)
239 {
240         struct uinput_cdev_state *state;
241         struct input_event *event;
242         int remaining, ret;
243
244         ret = devfs_get_cdevpriv((void **)&state);
245         if (ret != 0)
246                 return (ret);
247
248         debugf(state, "read %zd bytes by thread %d", uio->uio_resid,
249             uio->uio_td->td_tid);
250
251         /* Zero-sized reads are allowed for error checking */
252         if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event))
253                 return (EINVAL);
254
255         remaining = uio->uio_resid / sizeof(struct input_event);
256
257         UINPUT_LOCK(state);
258
259         if (state->ucs_state != UINPUT_RUNNING)
260                 ret = EINVAL;
261
262         if (ret == 0 && UINPUT_EMPTYQ(state)) {
263                 if (ioflag & O_NONBLOCK)
264                         ret = EWOULDBLOCK;
265                 else {
266                         if (remaining != 0) {
267                                 state->ucs_blocked = true;
268                                 ret = sx_sleep(state, &state->ucs_lock,
269                                     PCATCH, "uiread", 0);
270                         }
271                 }
272         }
273
274         while (ret == 0 && !UINPUT_EMPTYQ(state) && remaining > 0) {
275                 event = &state->ucs_buffer[state->ucs_buffer_head];
276                 state->ucs_buffer_head = (state->ucs_buffer_head + 1) %
277                     UINPUT_BUFFER_SIZE;
278                 remaining--;
279                 ret = uiomove(event, sizeof(struct input_event), uio);
280         }
281
282         UINPUT_UNLOCK(state);
283
284         return (ret);
285 }
286
287 static int
288 uinput_write(struct cdev *dev, struct uio *uio, int ioflag)
289 {
290         struct uinput_cdev_state *state;
291         struct uinput_user_dev userdev;
292         struct input_event event;
293         int ret = 0;
294
295         ret = devfs_get_cdevpriv((void **)&state);
296         if (ret != 0)
297                 return (ret);
298
299         debugf(state, "write %zd bytes by thread %d", uio->uio_resid,
300             uio->uio_td->td_tid);
301
302         UINPUT_LOCK(state);
303
304         if (state->ucs_state != UINPUT_RUNNING) {
305                 /* Process written struct uinput_user_dev */
306                 if (uio->uio_resid != sizeof(struct uinput_user_dev)) {
307                         debugf(state, "write size not multiple of "
308                             "struct uinput_user_dev size");
309                         ret = EINVAL;
310                 } else {
311                         ret = uiomove(&userdev, sizeof(struct uinput_user_dev),
312                             uio);
313                         if (ret == 0)
314                                 uinput_setup_provider(state, &userdev);
315                 }
316         } else {
317                 /* Process written event */
318                 if (uio->uio_resid % sizeof(struct input_event) != 0) {
319                         debugf(state, "write size not multiple of "
320                             "struct input_event size");
321                         ret = EINVAL;
322                 }
323
324                 while (ret == 0 && uio->uio_resid > 0) {
325                         uiomove(&event, sizeof(struct input_event), uio);
326                         ret = evdev_push_event(state->ucs_evdev, event.type,
327                             event.code, event.value);
328                 }
329         }
330
331         UINPUT_UNLOCK(state);
332
333         return (ret);
334 }
335
336 static int
337 uinput_setup_dev(struct uinput_cdev_state *state, struct input_id *id,
338     char *name, uint32_t ff_effects_max)
339 {
340
341         if (name[0] == 0)
342                 return (EINVAL);
343
344         evdev_set_name(state->ucs_evdev, name);
345         evdev_set_id(state->ucs_evdev, id->bustype, id->vendor, id->product,
346             id->version);
347         state->ucs_state = UINPUT_CONFIGURED;
348
349         return (0);
350 }
351
352 static int
353 uinput_setup_provider(struct uinput_cdev_state *state,
354     struct uinput_user_dev *udev)
355 {
356         struct input_absinfo absinfo;
357         int i, ret;
358
359         debugf(state, "setup_provider called, udev=%p", udev);
360
361         ret = uinput_setup_dev(state, &udev->id, udev->name,
362             udev->ff_effects_max);
363         if (ret)
364                 return (ret);
365
366         bzero(&absinfo, sizeof(struct input_absinfo));
367         for (i = 0; i < ABS_CNT; i++) {
368                 if (!bit_test(state->ucs_evdev->ev_abs_flags, i))
369                         continue;
370
371                 absinfo.minimum = udev->absmin[i];
372                 absinfo.maximum = udev->absmax[i];
373                 absinfo.fuzz = udev->absfuzz[i];
374                 absinfo.flat = udev->absflat[i];
375                 evdev_set_absinfo(state->ucs_evdev, i, &absinfo);
376         }
377
378         return (0);
379 }
380
381 static int
382 uinput_poll(struct cdev *dev, int events, struct thread *td)
383 {
384         struct uinput_cdev_state *state;
385         int revents = 0;
386
387         if (devfs_get_cdevpriv((void **)&state) != 0)
388                 return (POLLNVAL);
389
390         debugf(state, "poll by thread %d", td->td_tid);
391
392         /* Always allow write */
393         if (events & (POLLOUT | POLLWRNORM))
394                 revents |= (events & (POLLOUT | POLLWRNORM));
395
396         if (events & (POLLIN | POLLRDNORM)) {
397                 UINPUT_LOCK(state);
398                 if (!UINPUT_EMPTYQ(state))
399                         revents = events & (POLLIN | POLLRDNORM);
400                 else {
401                         state->ucs_selected = true;
402                         selrecord(td, &state->ucs_selp);
403                 }
404                 UINPUT_UNLOCK(state);
405         }
406
407         return (revents);
408 }
409
410 static int
411 uinput_kqfilter(struct cdev *dev, struct knote *kn)
412 {
413         struct uinput_cdev_state *state;
414         int ret;
415
416         ret = devfs_get_cdevpriv((void **)&state);
417         if (ret != 0)
418                 return (ret);
419
420         switch(kn->kn_filter) {
421         case EVFILT_READ:
422                 kn->kn_fop = &uinput_filterops;
423                 break;
424         default:
425                 return(EINVAL);
426         }
427         kn->kn_hook = (caddr_t)state;
428
429         knlist_add(&state->ucs_selp.si_note, kn, 0);
430         return (0);
431 }
432
433 static int
434 uinput_kqread(struct knote *kn, long hint)
435 {
436         struct uinput_cdev_state *state;
437         int ret;
438
439         state = (struct uinput_cdev_state *)kn->kn_hook;
440
441         UINPUT_LOCK_ASSERT(state);
442
443         ret = !UINPUT_EMPTYQ(state);
444         return (ret);
445 }
446
447 static void
448 uinput_kqdetach(struct knote *kn)
449 {
450         struct uinput_cdev_state *state;
451
452         state = (struct uinput_cdev_state *)kn->kn_hook;
453         knlist_remove(&state->ucs_selp.si_note, kn, 0);
454 }
455
456 static void
457 uinput_notify(struct uinput_cdev_state *state)
458 {
459
460         UINPUT_LOCK_ASSERT(state);
461
462         if (state->ucs_blocked) {
463                 state->ucs_blocked = false;
464                 wakeup(state);
465         }
466         if (state->ucs_selected) {
467                 state->ucs_selected = false;
468                 selwakeup(&state->ucs_selp);
469         }
470         KNOTE_LOCKED(&state->ucs_selp.si_note, 0);
471 }
472
473 static int
474 uinput_ioctl_sub(struct uinput_cdev_state *state, u_long cmd, caddr_t data)
475 {
476         struct uinput_setup *us;
477         struct uinput_abs_setup *uabs;
478         int ret, len, intdata;
479         char buf[NAMELEN];
480
481         UINPUT_LOCK_ASSERT(state);
482
483         len = IOCPARM_LEN(cmd);
484         if ((cmd & IOC_DIRMASK) == IOC_VOID && len == sizeof(int))
485                 intdata = *(int *)data;
486
487         switch (IOCBASECMD(cmd)) {
488         case UI_GET_SYSNAME(0):
489                 if (state->ucs_state != UINPUT_RUNNING)
490                         return (ENOENT);
491                 if (len == 0)
492                         return (EINVAL);
493                 snprintf(data, len, "event%d", state->ucs_evdev->ev_unit);
494                 return (0);
495         }
496
497         switch (cmd) {
498         case UI_DEV_CREATE:
499                 if (state->ucs_state != UINPUT_CONFIGURED)
500                         return (EINVAL);
501
502                 evdev_set_methods(state->ucs_evdev, state, &uinput_ev_methods);
503                 evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_SOFTREPEAT);
504                 ret = evdev_register(state->ucs_evdev);
505                 if (ret == 0)
506                         state->ucs_state = UINPUT_RUNNING;
507                 return (ret);
508
509         case UI_DEV_DESTROY:
510                 if (state->ucs_state != UINPUT_RUNNING)
511                         return (0);
512
513                 evdev_unregister(state->ucs_evdev);
514                 bzero(state->ucs_evdev, sizeof(struct evdev_dev));
515                 state->ucs_state = UINPUT_NEW;
516                 return (0);
517
518         case UI_DEV_SETUP:
519                 if (state->ucs_state == UINPUT_RUNNING)
520                         return (EINVAL);
521
522                 us = (struct uinput_setup *)data;
523                 return (uinput_setup_dev(state, &us->id, us->name,
524                     us->ff_effects_max));
525
526         case UI_ABS_SETUP:
527                 if (state->ucs_state == UINPUT_RUNNING)
528                         return (EINVAL);
529
530                 uabs = (struct uinput_abs_setup *)data;
531                 if (uabs->code > ABS_MAX)
532                         return (EINVAL);
533
534                 evdev_support_abs(state->ucs_evdev, uabs->code,
535                     uabs->absinfo.value, uabs->absinfo.minimum,
536                     uabs->absinfo.maximum, uabs->absinfo.fuzz,
537                     uabs->absinfo.flat, uabs->absinfo.resolution);
538                 return (0);
539
540         case UI_SET_EVBIT:
541                 if (state->ucs_state == UINPUT_RUNNING ||
542                     intdata > EV_MAX || intdata < 0)
543                         return (EINVAL);
544                 evdev_support_event(state->ucs_evdev, intdata);
545                 return (0);
546
547         case UI_SET_KEYBIT:
548                 if (state->ucs_state == UINPUT_RUNNING ||
549                     intdata > KEY_MAX || intdata < 0)
550                         return (EINVAL);
551                 evdev_support_key(state->ucs_evdev, intdata);
552                 return (0);
553
554         case UI_SET_RELBIT:
555                 if (state->ucs_state == UINPUT_RUNNING ||
556                     intdata > REL_MAX || intdata < 0)
557                         return (EINVAL);
558                 evdev_support_rel(state->ucs_evdev, intdata);
559                 return (0);
560
561         case UI_SET_ABSBIT:
562                 if (state->ucs_state == UINPUT_RUNNING ||
563                     intdata > ABS_MAX || intdata < 0)
564                         return (EINVAL);
565                 evdev_set_abs_bit(state->ucs_evdev, intdata);
566                 return (0);
567
568         case UI_SET_MSCBIT:
569                 if (state->ucs_state == UINPUT_RUNNING ||
570                     intdata > MSC_MAX || intdata < 0)
571                         return (EINVAL);
572                 evdev_support_msc(state->ucs_evdev, intdata);
573                 return (0);
574
575         case UI_SET_LEDBIT:
576                 if (state->ucs_state == UINPUT_RUNNING ||
577                     intdata > LED_MAX || intdata < 0)
578                         return (EINVAL);
579                 evdev_support_led(state->ucs_evdev, intdata);
580                 return (0);
581
582         case UI_SET_SNDBIT:
583                 if (state->ucs_state == UINPUT_RUNNING ||
584                     intdata > SND_MAX || intdata < 0)
585                         return (EINVAL);
586                 evdev_support_snd(state->ucs_evdev, intdata);
587                 return (0);
588
589         case UI_SET_FFBIT:
590                 if (state->ucs_state == UINPUT_RUNNING ||
591                     intdata > FF_MAX || intdata < 0)
592                         return (EINVAL);
593                 /* Fake unsupported ioctl */
594                 return (0);
595
596         case UI_SET_PHYS:
597                 if (state->ucs_state == UINPUT_RUNNING)
598                         return (EINVAL);
599                 ret = copyinstr(*(void **)data, buf, sizeof(buf), NULL);
600                 /* Linux returns EINVAL when string does not fit the buffer */
601                 if (ret == ENAMETOOLONG)
602                         ret = EINVAL;
603                 if (ret != 0)
604                         return (ret);
605                 evdev_set_phys(state->ucs_evdev, buf);
606                 return (0);
607
608         case UI_SET_SWBIT:
609                 if (state->ucs_state == UINPUT_RUNNING ||
610                     intdata > SW_MAX || intdata < 0)
611                         return (EINVAL);
612                 evdev_support_sw(state->ucs_evdev, intdata);
613                 return (0);
614
615         case UI_SET_PROPBIT:
616                 if (state->ucs_state == UINPUT_RUNNING ||
617                     intdata > INPUT_PROP_MAX || intdata < 0)
618                         return (EINVAL);
619                 evdev_support_prop(state->ucs_evdev, intdata);
620                 return (0);
621
622         case UI_BEGIN_FF_UPLOAD:
623         case UI_END_FF_UPLOAD:
624         case UI_BEGIN_FF_ERASE:
625         case UI_END_FF_ERASE:
626                 if (state->ucs_state == UINPUT_RUNNING)
627                         return (EINVAL);
628                 /* Fake unsupported ioctl */
629                 return (0);
630
631         case UI_GET_VERSION:
632                 *(unsigned int *)data = UINPUT_VERSION;
633                 return (0);
634         }
635
636         return (EINVAL);
637 }
638
639 static int
640 uinput_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
641     struct thread *td)
642 {
643         struct uinput_cdev_state *state;
644         int ret;
645
646         ret = devfs_get_cdevpriv((void **)&state);
647         if (ret != 0)
648                 return (ret);
649
650         debugf(state, "ioctl called: cmd=0x%08lx, data=%p", cmd, data);
651
652         UINPUT_LOCK(state);
653         ret = uinput_ioctl_sub(state, cmd, data);
654         UINPUT_UNLOCK(state);
655
656         return (ret);
657 }
658
659 static int
660 uinput_cdev_create(void)
661 {
662         struct make_dev_args mda;
663         int ret;
664
665         make_dev_args_init(&mda);
666         mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
667         mda.mda_devsw = &uinput_cdevsw;
668         mda.mda_uid = UID_ROOT;
669         mda.mda_gid = GID_WHEEL;
670         mda.mda_mode = 0600;
671
672         ret = make_dev_s(&mda, &uinput_cdev, "uinput");
673
674         return (ret);
675 }
676
677 static int
678 uinput_cdev_destroy(void)
679 {
680
681         destroy_dev(uinput_cdev);
682
683         return (0);
684 }
685
686 static int
687 uinput_modevent(module_t mod __unused, int cmd, void *data)
688 {
689         int ret = 0;
690
691         switch (cmd) {
692         case MOD_LOAD:
693                 ret = uinput_cdev_create();
694                 break;
695
696         case MOD_UNLOAD:
697                 ret = uinput_cdev_destroy();
698                 break;
699
700         case MOD_SHUTDOWN:
701                 break;
702
703         default:
704                 ret = EINVAL;
705                 break;
706         }
707
708         return (ret);
709 }
710
711 DEV_MODULE(uinput, uinput_modevent, NULL);
712 MODULE_VERSION(uinput, 1);
713 MODULE_DEPEND(uinput, evdev, 1, 1, 1);