The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/evdev/uinput.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 5938423cbfa2d75a03448763272603d2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.