xref: /freebsd/sys/dev/evdev/uinput.c (revision a35f04fba2ebb8f86d4cbdc710c89a094572b08e)
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 		evdev_register(state->ucs_evdev);
505 		state->ucs_state = UINPUT_RUNNING;
506 		return (0);
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);
713