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