cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

uinput.rst (6803B)


      1=============
      2uinput module
      3=============
      4
      5Introduction
      6============
      7
      8uinput is a kernel module that makes it possible to emulate input devices
      9from userspace. By writing to /dev/uinput (or /dev/input/uinput) device, a
     10process can create a virtual input device with specific capabilities. Once
     11this virtual device is created, the process can send events through it,
     12that will be delivered to userspace and in-kernel consumers.
     13
     14Interface
     15=========
     16
     17::
     18
     19  linux/uinput.h
     20
     21The uinput header defines ioctls to create, set up, and destroy virtual
     22devices.
     23
     24libevdev
     25========
     26
     27libevdev is a wrapper library for evdev devices that provides interfaces to
     28create uinput devices and send events. libevdev is less error-prone than
     29accessing uinput directly, and should be considered for new software.
     30
     31For examples and more information about libevdev:
     32https://www.freedesktop.org/software/libevdev/doc/latest/
     33
     34Examples
     35========
     36
     37Keyboard events
     38---------------
     39
     40This first example shows how to create a new virtual device, and how to
     41send a key event. All default imports and error handlers were removed for
     42the sake of simplicity.
     43
     44.. code-block:: c
     45
     46   #include <linux/uinput.h>
     47
     48   void emit(int fd, int type, int code, int val)
     49   {
     50      struct input_event ie;
     51
     52      ie.type = type;
     53      ie.code = code;
     54      ie.value = val;
     55      /* timestamp values below are ignored */
     56      ie.time.tv_sec = 0;
     57      ie.time.tv_usec = 0;
     58
     59      write(fd, &ie, sizeof(ie));
     60   }
     61
     62   int main(void)
     63   {
     64      struct uinput_setup usetup;
     65
     66      int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
     67
     68
     69      /*
     70       * The ioctls below will enable the device that is about to be
     71       * created, to pass key events, in this case the space key.
     72       */
     73      ioctl(fd, UI_SET_EVBIT, EV_KEY);
     74      ioctl(fd, UI_SET_KEYBIT, KEY_SPACE);
     75
     76      memset(&usetup, 0, sizeof(usetup));
     77      usetup.id.bustype = BUS_USB;
     78      usetup.id.vendor = 0x1234; /* sample vendor */
     79      usetup.id.product = 0x5678; /* sample product */
     80      strcpy(usetup.name, "Example device");
     81
     82      ioctl(fd, UI_DEV_SETUP, &usetup);
     83      ioctl(fd, UI_DEV_CREATE);
     84
     85      /*
     86       * On UI_DEV_CREATE the kernel will create the device node for this
     87       * device. We are inserting a pause here so that userspace has time
     88       * to detect, initialize the new device, and can start listening to
     89       * the event, otherwise it will not notice the event we are about
     90       * to send. This pause is only needed in our example code!
     91       */
     92      sleep(1);
     93
     94      /* Key press, report the event, send key release, and report again */
     95      emit(fd, EV_KEY, KEY_SPACE, 1);
     96      emit(fd, EV_SYN, SYN_REPORT, 0);
     97      emit(fd, EV_KEY, KEY_SPACE, 0);
     98      emit(fd, EV_SYN, SYN_REPORT, 0);
     99
    100      /*
    101       * Give userspace some time to read the events before we destroy the
    102       * device with UI_DEV_DESTROY.
    103       */
    104      sleep(1);
    105
    106      ioctl(fd, UI_DEV_DESTROY);
    107      close(fd);
    108
    109      return 0;
    110   }
    111
    112Mouse movements
    113---------------
    114
    115This example shows how to create a virtual device that behaves like a physical
    116mouse.
    117
    118.. code-block:: c
    119
    120   #include <linux/uinput.h>
    121
    122   /* emit function is identical to of the first example */
    123
    124   int main(void)
    125   {
    126      struct uinput_setup usetup;
    127      int i = 50;
    128
    129      int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    130
    131      /* enable mouse button left and relative events */
    132      ioctl(fd, UI_SET_EVBIT, EV_KEY);
    133      ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
    134
    135      ioctl(fd, UI_SET_EVBIT, EV_REL);
    136      ioctl(fd, UI_SET_RELBIT, REL_X);
    137      ioctl(fd, UI_SET_RELBIT, REL_Y);
    138
    139      memset(&usetup, 0, sizeof(usetup));
    140      usetup.id.bustype = BUS_USB;
    141      usetup.id.vendor = 0x1234; /* sample vendor */
    142      usetup.id.product = 0x5678; /* sample product */
    143      strcpy(usetup.name, "Example device");
    144
    145      ioctl(fd, UI_DEV_SETUP, &usetup);
    146      ioctl(fd, UI_DEV_CREATE);
    147
    148      /*
    149       * On UI_DEV_CREATE the kernel will create the device node for this
    150       * device. We are inserting a pause here so that userspace has time
    151       * to detect, initialize the new device, and can start listening to
    152       * the event, otherwise it will not notice the event we are about
    153       * to send. This pause is only needed in our example code!
    154       */
    155      sleep(1);
    156
    157      /* Move the mouse diagonally, 5 units per axis */
    158      while (i--) {
    159         emit(fd, EV_REL, REL_X, 5);
    160         emit(fd, EV_REL, REL_Y, 5);
    161         emit(fd, EV_SYN, SYN_REPORT, 0);
    162         usleep(15000);
    163      }
    164
    165      /*
    166       * Give userspace some time to read the events before we destroy the
    167       * device with UI_DEV_DESTROY.
    168       */
    169      sleep(1);
    170
    171      ioctl(fd, UI_DEV_DESTROY);
    172      close(fd);
    173
    174      return 0;
    175   }
    176
    177
    178uinput old interface
    179--------------------
    180
    181Before uinput version 5, there wasn't a dedicated ioctl to set up a virtual
    182device. Programs supporting older versions of uinput interface need to fill
    183a uinput_user_dev structure and write it to the uinput file descriptor to
    184configure the new uinput device. New code should not use the old interface
    185but interact with uinput via ioctl calls, or use libevdev.
    186
    187.. code-block:: c
    188
    189   #include <linux/uinput.h>
    190
    191   /* emit function is identical to of the first example */
    192
    193   int main(void)
    194   {
    195      struct uinput_user_dev uud;
    196      int version, rc, fd;
    197
    198      fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    199      rc = ioctl(fd, UI_GET_VERSION, &version);
    200
    201      if (rc == 0 && version >= 5) {
    202         /* use UI_DEV_SETUP */
    203         return 0;
    204      }
    205
    206      /*
    207       * The ioctls below will enable the device that is about to be
    208       * created, to pass key events, in this case the space key.
    209       */
    210      ioctl(fd, UI_SET_EVBIT, EV_KEY);
    211      ioctl(fd, UI_SET_KEYBIT, KEY_SPACE);
    212
    213      memset(&uud, 0, sizeof(uud));
    214      snprintf(uud.name, UINPUT_MAX_NAME_SIZE, "uinput old interface");
    215      write(fd, &uud, sizeof(uud));
    216
    217      ioctl(fd, UI_DEV_CREATE);
    218
    219      /*
    220       * On UI_DEV_CREATE the kernel will create the device node for this
    221       * device. We are inserting a pause here so that userspace has time
    222       * to detect, initialize the new device, and can start listening to
    223       * the event, otherwise it will not notice the event we are about
    224       * to send. This pause is only needed in our example code!
    225       */
    226      sleep(1);
    227
    228      /* Key press, report the event, send key release, and report again */
    229      emit(fd, EV_KEY, KEY_SPACE, 1);
    230      emit(fd, EV_SYN, SYN_REPORT, 0);
    231      emit(fd, EV_KEY, KEY_SPACE, 0);
    232      emit(fd, EV_SYN, SYN_REPORT, 0);
    233
    234      /*
    235       * Give userspace some time to read the events before we destroy the
    236       * device with UI_DEV_DESTROY.
    237       */
    238      sleep(1);
    239
    240      ioctl(fd, UI_DEV_DESTROY);
    241
    242      close(fd);
    243      return 0;
    244   }
    245