summaryrefslogtreecommitdiffstats
path: root/Documentation/input/uinput.rst
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.org>2026-09-26 19:20:30 -0300
committerPaulo Alcantara <pc@manguebit.org>2026-09-30 14:24:12 -0300
commitdd05add7b2b6004c5fa3a1f276f56d8668f86b65 (patch)
tree23efdcaa0b8031f6ac6f57b6734d18d6c1adc6f2 /Documentation/input/uinput.rst
downloadlinux-stable-dd05add7b2b6004c5fa3a1f276f56d8668f86b65.tar.gz
linux-stable-dd05add7b2b6004c5fa3a1f276f56d8668f86b65.zip
netfs: zero the tail of a short DIO/unbuffered readgrafted
The buffered read collector zero-fills the tail of a short read that stops below the inode's i_size (netfs_clear_unread()), so a read that races an extending write still returns the expected number of bytes. The non-buffered collector path does no such thing: it just records how much was transferred. Add the same zero-fill for the non-buffered case, gated on NETFS_SREQ_CLEAR_TAIL: a subreq's source sets that flag when a short result from it is known to be safe to treat as a hole, as opposed to NETFS_SREQ_HIT_EOF, which means the read genuinely ran off the end of the file and should be reported short as-is. Only CLEAR_TAIL should zero-fill here; a real EOF must stay a real short read. No source currently sets CLEAR_TAIL on an unbuffered/DIO subrequest, so this is inert on its own -- a following change teaches cifs to set it in the one case that needs it. Fixes: e2d46f2ec332 ("netfs: Change the read result collector to only use one work item") Reviewed-by: David Howells <dhowells@redhat.com> Reviewed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Paulo Alcantara <pc@manguebit.org> Cc: Christian Brauner <brauner@kernel.org> Cc: Matthew Wilcox <willy@infradead.org> Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com> Cc: Shyam Prasad N <sprasad@microsoft.com> Cc: Tom Talpey <tom@talpey.com> Cc: Bharath SM <bharathsm@microsoft.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'Documentation/input/uinput.rst')
-rw-r--r--Documentation/input/uinput.rst245
1 files changed, 245 insertions, 0 deletions
diff --git a/Documentation/input/uinput.rst b/Documentation/input/uinput.rst
new file mode 100644
index 000000000..30fe80e32
--- /dev/null
+++ b/Documentation/input/uinput.rst
@@ -0,0 +1,245 @@
+=============
+uinput module
+=============
+
+Introduction
+============
+
+uinput is a kernel module that makes it possible to emulate input devices
+from userspace. By writing to /dev/uinput (or /dev/input/uinput) device, a
+process can create a virtual input device with specific capabilities. Once
+this virtual device is created, the process can send events through it,
+that will be delivered to userspace and in-kernel consumers.
+
+Interface
+=========
+
+::
+
+ linux/uinput.h
+
+The uinput header defines ioctls to create, set up, and destroy virtual
+devices.
+
+libevdev
+========
+
+libevdev is a wrapper library for evdev devices that provides interfaces to
+create uinput devices and send events. libevdev is less error-prone than
+accessing uinput directly, and should be considered for new software.
+
+For examples and more information about libevdev:
+https://www.freedesktop.org/software/libevdev/doc/latest/
+
+Examples
+========
+
+Keyboard events
+---------------
+
+This first example shows how to create a new virtual device, and how to
+send a key event. All default imports and error handlers were removed for
+the sake of simplicity.
+
+.. code-block:: c
+
+ #include <linux/uinput.h>
+
+ void emit(int fd, int type, int code, int val)
+ {
+ struct input_event ie;
+
+ ie.type = type;
+ ie.code = code;
+ ie.value = val;
+ /* timestamp values below are ignored */
+ ie.time.tv_sec = 0;
+ ie.time.tv_usec = 0;
+
+ write(fd, &ie, sizeof(ie));
+ }
+
+ int main(void)
+ {
+ struct uinput_setup usetup;
+
+ int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
+
+
+ /*
+ * The ioctls below will enable the device that is about to be
+ * created, to pass key events, in this case the space key.
+ */
+ ioctl(fd, UI_SET_EVBIT, EV_KEY);
+ ioctl(fd, UI_SET_KEYBIT, KEY_SPACE);
+
+ memset(&usetup, 0, sizeof(usetup));
+ usetup.id.bustype = BUS_USB;
+ usetup.id.vendor = 0x1234; /* sample vendor */
+ usetup.id.product = 0x5678; /* sample product */
+ strcpy(usetup.name, "Example device");
+
+ ioctl(fd, UI_DEV_SETUP, &usetup);
+ ioctl(fd, UI_DEV_CREATE);
+
+ /*
+ * On UI_DEV_CREATE the kernel will create the device node for this
+ * device. We are inserting a pause here so that userspace has time
+ * to detect, initialize the new device, and can start listening to
+ * the event, otherwise it will not notice the event we are about
+ * to send. This pause is only needed in our example code!
+ */
+ sleep(1);
+
+ /* Key press, report the event, send key release, and report again */
+ emit(fd, EV_KEY, KEY_SPACE, 1);
+ emit(fd, EV_SYN, SYN_REPORT, 0);
+ emit(fd, EV_KEY, KEY_SPACE, 0);
+ emit(fd, EV_SYN, SYN_REPORT, 0);
+
+ /*
+ * Give userspace some time to read the events before we destroy the
+ * device with UI_DEV_DESTROY.
+ */
+ sleep(1);
+
+ ioctl(fd, UI_DEV_DESTROY);
+ close(fd);
+
+ return 0;
+ }
+
+Mouse movements
+---------------
+
+This example shows how to create a virtual device that behaves like a physical
+mouse.
+
+.. code-block:: c
+
+ #include <linux/uinput.h>
+
+ /* emit function is identical to of the first example */
+
+ int main(void)
+ {
+ struct uinput_setup usetup;
+ int i = 50;
+
+ int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
+
+ /* enable mouse button left and relative events */
+ ioctl(fd, UI_SET_EVBIT, EV_KEY);
+ ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
+
+ ioctl(fd, UI_SET_EVBIT, EV_REL);
+ ioctl(fd, UI_SET_RELBIT, REL_X);
+ ioctl(fd, UI_SET_RELBIT, REL_Y);
+
+ memset(&usetup, 0, sizeof(usetup));
+ usetup.id.bustype = BUS_USB;
+ usetup.id.vendor = 0x1234; /* sample vendor */
+ usetup.id.product = 0x5678; /* sample product */
+ strcpy(usetup.name, "Example device");
+
+ ioctl(fd, UI_DEV_SETUP, &usetup);
+ ioctl(fd, UI_DEV_CREATE);
+
+ /*
+ * On UI_DEV_CREATE the kernel will create the device node for this
+ * device. We are inserting a pause here so that userspace has time
+ * to detect, initialize the new device, and can start listening to
+ * the event, otherwise it will not notice the event we are about
+ * to send. This pause is only needed in our example code!
+ */
+ sleep(1);
+
+ /* Move the mouse diagonally, 5 units per axis */
+ while (i--) {
+ emit(fd, EV_REL, REL_X, 5);
+ emit(fd, EV_REL, REL_Y, 5);
+ emit(fd, EV_SYN, SYN_REPORT, 0);
+ usleep(15000);
+ }
+
+ /*
+ * Give userspace some time to read the events before we destroy the
+ * device with UI_DEV_DESTROY.
+ */
+ sleep(1);
+
+ ioctl(fd, UI_DEV_DESTROY);
+ close(fd);
+
+ return 0;
+ }
+
+
+uinput old interface
+--------------------
+
+Before uinput version 5, there wasn't a dedicated ioctl to set up a virtual
+device. Programs supporting older versions of uinput interface need to fill
+a uinput_user_dev structure and write it to the uinput file descriptor to
+configure the new uinput device. New code should not use the old interface
+but interact with uinput via ioctl calls, or use libevdev.
+
+.. code-block:: c
+
+ #include <linux/uinput.h>
+
+ /* emit function is identical to of the first example */
+
+ int main(void)
+ {
+ struct uinput_user_dev uud;
+ int version, rc, fd;
+
+ fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
+ rc = ioctl(fd, UI_GET_VERSION, &version);
+
+ if (rc == 0 && version >= 5) {
+ /* use UI_DEV_SETUP */
+ return 0;
+ }
+
+ /*
+ * The ioctls below will enable the device that is about to be
+ * created, to pass key events, in this case the space key.
+ */
+ ioctl(fd, UI_SET_EVBIT, EV_KEY);
+ ioctl(fd, UI_SET_KEYBIT, KEY_SPACE);
+
+ memset(&uud, 0, sizeof(uud));
+ snprintf(uud.name, UINPUT_MAX_NAME_SIZE, "uinput old interface");
+ write(fd, &uud, sizeof(uud));
+
+ ioctl(fd, UI_DEV_CREATE);
+
+ /*
+ * On UI_DEV_CREATE the kernel will create the device node for this
+ * device. We are inserting a pause here so that userspace has time
+ * to detect, initialize the new device, and can start listening to
+ * the event, otherwise it will not notice the event we are about
+ * to send. This pause is only needed in our example code!
+ */
+ sleep(1);
+
+ /* Key press, report the event, send key release, and report again */
+ emit(fd, EV_KEY, KEY_SPACE, 1);
+ emit(fd, EV_SYN, SYN_REPORT, 0);
+ emit(fd, EV_KEY, KEY_SPACE, 0);
+ emit(fd, EV_SYN, SYN_REPORT, 0);
+
+ /*
+ * Give userspace some time to read the events before we destroy the
+ * device with UI_DEV_DESTROY.
+ */
+ sleep(1);
+
+ ioctl(fd, UI_DEV_DESTROY);
+
+ close(fd);
+ return 0;
+ }
+