xref: /freebsd/sys/dev/evdev/uinput.c (revision b0d29bc47dba79f6f38e67eabadfb4b32ffd9390)
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, uint16_t type, uint16_t code,
163     int32_t value)
164 {
165 	struct uinput_cdev_state *state = evdev_get_softc(evdev);
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_BSDUNIQ:
608 		if (state->ucs_state == UINPUT_RUNNING)
609 			return (EINVAL);
610 		ret = copyinstr(*(void **)data, buf, sizeof(buf), NULL);
611 		if (ret != 0)
612 			return (ret);
613 		evdev_set_serial(state->ucs_evdev, buf);
614 		return (0);
615 
616 	case UI_SET_SWBIT:
617 		if (state->ucs_state == UINPUT_RUNNING ||
618 		    intdata > SW_MAX || intdata < 0)
619 			return (EINVAL);
620 		evdev_support_sw(state->ucs_evdev, intdata);
621 		return (0);
622 
623 	case UI_SET_PROPBIT:
624 		if (state->ucs_state == UINPUT_RUNNING ||
625 		    intdata > INPUT_PROP_MAX || intdata < 0)
626 			return (EINVAL);
627 		evdev_support_prop(state->ucs_evdev, intdata);
628 		return (0);
629 
630 	case UI_BEGIN_FF_UPLOAD:
631 	case UI_END_FF_UPLOAD:
632 	case UI_BEGIN_FF_ERASE:
633 	case UI_END_FF_ERASE:
634 		if (state->ucs_state == UINPUT_RUNNING)
635 			return (EINVAL);
636 		/* Fake unsupported ioctl */
637 		return (0);
638 
639 	case UI_GET_VERSION:
640 		*(unsigned int *)data = UINPUT_VERSION;
641 		return (0);
642 	}
643 
644 	return (EINVAL);
645 }
646 
647 static int
648 uinput_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
649     struct thread *td)
650 {
651 	struct uinput_cdev_state *state;
652 	int ret;
653 
654 	ret = devfs_get_cdevpriv((void **)&state);
655 	if (ret != 0)
656 		return (ret);
657 
658 	debugf(state, "ioctl called: cmd=0x%08lx, data=%p", cmd, data);
659 
660 	UINPUT_LOCK(state);
661 	ret = uinput_ioctl_sub(state, cmd, data);
662 	UINPUT_UNLOCK(state);
663 
664 	return (ret);
665 }
666 
667 static int
668 uinput_cdev_create(void)
669 {
670 	struct make_dev_args mda;
671 	int ret;
672 
673 	make_dev_args_init(&mda);
674 	mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
675 	mda.mda_devsw = &uinput_cdevsw;
676 	mda.mda_uid = UID_ROOT;
677 	mda.mda_gid = GID_WHEEL;
678 	mda.mda_mode = 0600;
679 
680 	ret = make_dev_s(&mda, &uinput_cdev, "uinput");
681 
682 	return (ret);
683 }
684 
685 static int
686 uinput_cdev_destroy(void)
687 {
688 
689 	destroy_dev(uinput_cdev);
690 
691 	return (0);
692 }
693 
694 static int
695 uinput_modevent(module_t mod __unused, int cmd, void *data)
696 {
697 	int ret = 0;
698 
699 	switch (cmd) {
700 	case MOD_LOAD:
701 		ret = uinput_cdev_create();
702 		break;
703 
704 	case MOD_UNLOAD:
705 		ret = uinput_cdev_destroy();
706 		break;
707 
708 	case MOD_SHUTDOWN:
709 		break;
710 
711 	default:
712 		ret = EINVAL;
713 		break;
714 	}
715 
716 	return (ret);
717 }
718 
719 DEV_MODULE(uinput, uinput_modevent, NULL);
720 MODULE_VERSION(uinput, 1);
721 MODULE_DEPEND(uinput, evdev, 1, 1, 1);
722