brintos

brintos / linux-shallow public Read only

0
0
Text · 6.6 KiB · 30fe80e Raw
246 lines · plain
1=============2uinput module3=============4 5Introduction6============7 8uinput is a kernel module that makes it possible to emulate input devices9from userspace. By writing to /dev/uinput (or /dev/input/uinput) device, a10process can create a virtual input device with specific capabilities. Once11this virtual device is created, the process can send events through it,12that will be delivered to userspace and in-kernel consumers.13 14Interface15=========16 17::18 19  linux/uinput.h20 21The uinput header defines ioctls to create, set up, and destroy virtual22devices.23 24libevdev25========26 27libevdev is a wrapper library for evdev devices that provides interfaces to28create uinput devices and send events. libevdev is less error-prone than29accessing 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 34Examples35========36 37Keyboard events38---------------39 40This first example shows how to create a new virtual device, and how to41send a key event. All default imports and error handlers were removed for42the sake of simplicity.43 44.. code-block:: c45 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 be71       * 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 this87       * device. We are inserting a pause here so that userspace has time88       * to detect, initialize the new device, and can start listening to89       * the event, otherwise it will not notice the event we are about90       * 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 the102       * 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 movements113---------------114 115This example shows how to create a virtual device that behaves like a physical116mouse.117 118.. code-block:: c119 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 this150       * device. We are inserting a pause here so that userspace has time151       * to detect, initialize the new device, and can start listening to152       * the event, otherwise it will not notice the event we are about153       * 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 the167       * 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 interface179--------------------180 181Before uinput version 5, there wasn't a dedicated ioctl to set up a virtual182device. Programs supporting older versions of uinput interface need to fill183a uinput_user_dev structure and write it to the uinput file descriptor to184configure the new uinput device. New code should not use the old interface185but interact with uinput via ioctl calls, or use libevdev.186 187.. code-block:: c188 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 be208       * 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 this221       * device. We are inserting a pause here so that userspace has time222       * to detect, initialize the new device, and can start listening to223       * the event, otherwise it will not notice the event we are about224       * 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 the236       * 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 246