Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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