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