public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Marcos Paulo de Souza <marcos.souza.org@gmail.com>
To: corbet@lwn.net, linux-doc@vger.kernel.org,
	dmitry.torokhov@gmail.com, linux-input@vger.kernel.org,
	benjamin.tissoires@redhat.com, peter.hutterer@who-t.net
Cc: Marcos Paulo de Souza <marcos.souza.org@gmail.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH v2] Documentation: Input: Add uinput documentation
Date: Fri, 24 Mar 2017 00:34:59 -0300	[thread overview]
Message-ID: <20170324033502.17398-2-marcos.souza.org@gmail.com> (raw)
In-Reply-To: <20170324033502.17398-1-marcos.souza.org@gmail.com>

Signed-off-by: Marcos Paulo de Souza <marcos.souza.org@gmail.com>
---
 Documentation/input/uinput.rst | 196 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 196 insertions(+)
 create mode 100644 Documentation/input/uinput.rst

diff --git a/Documentation/input/uinput.rst b/Documentation/input/uinput.rst
new file mode 100644
index 0000000..eb79b77
--- /dev/null
+++ b/Documentation/input/uinput.rst
@@ -0,0 +1,196 @@
+=============
+uinput module
+=============
+
+Introduction
+============
+
+uinput is a kernel module that makes possible to create and handle input devices
+from userspace. By writing to the module's /dev/uinput (or /dev/input/uinput), a
+process can create a virtual device with specific capabilities.
+Once created, the process can send events through that virtual device.
+
+Interface
+=========
+
+::
+
+  linux/uinput.h
+
+The uinput header defines ioctls to create, setup and destroy virtual devices.
+
+libevdev
+========
+
+libevdev is a wrapper library for evdev devices, making uinput setup easier
+by skipping a lot of ioctl calls. When dealing with uinput, libevdev is the best
+alternative over accessing uinput directly, and it is less error prone.
+
+For examples and more information about libevdev:
+https://cgit.freedesktop.org/libevdev
+
+Examples
+========
+
+1.0 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>
+
+   int fd;
+
+   void emit(int type, int code, int val)
+   {
+        struct input_event ie;
+
+        ie.type = type;
+        ie.code = code;
+        ie.value = val;
+        /* below timestamp values are ignored */
+        ie.time.tv_sec = 0;
+        ie.time.tv_usec = 0;
+
+        write(fd, &ie, sizeof(ie));
+   }
+
+   int main() {
+        struct uinput_setup usetup;
+
+        fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
+
+        /* the ioctls below enables the to be created device to 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 */
+        strcpy(usetup.name, "Example device");
+
+        ioctl(fd, UI_DEV_SETUP, &usetup);
+        ioctl(fd, UI_DEV_CREATE);
+
+        /* UI_DEV_CREATE causes the kernel to create the device nodes for this
+         * device. Insert a pause so that userspace has time to detect,
+         * initialize the new device, and can start to listen to events from
+         * this device
+         **/
+
+        /* key press, report the event, send key release, and report again */
+        emit(EV_KEY, KEY_SPACE, 1);
+        emit(EV_SYN, SYN_REPORT, 0);
+        emit(EV_KEY, KEY_SPACE, 0);
+        emit(EV_SYN, SYN_REPORT, 0);
+
+        ioctl(fd, UI_DEV_DESTROY);
+        close(fd);
+
+        return 0;
+   }
+
+2.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 */
+
+    struct uinput_setup usetup;
+    int i = 50;
+
+    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 */
+    strcpy(usetup.name, "Example device");
+
+    ioctl(fd, UI_DEV_SETUP, &usetup);
+    ioctl(fd, UI_DEV_CREATE);
+
+    /* UI_DEV_CREATE causes the kernel to create the device nodes for this
+     * device. Insert a pause so that userspace has time to detect,
+     * initialize the new device, and can start to listen to events from
+     * this device
+     **/
+
+    /* moves the mouse diagonally, 5 units per axis */
+    while (i--) {
+        emit(EV_REL, REL_X, 5);
+        emit(EV_REL, REL_Y, 5);
+        emit(EV_SYN, SYN_REPORT, 0);
+        usleep(15000);
+    }
+
+    ioctl(fd, UI_DEV_DESTROY);
+    close(fd);
+
+    return 0;
+
+3.0 uinput old interface
+------------------------
+
+Before kernel 4.5, uinput didn't have an ioctl to setup a virtual device. When
+running a version prior to 4.5, the user needs to fill a different struct and
+call write on the uinput file descriptor.
+
+.. code-block:: c
+
+    #include <linux/uinput.h>
+
+    /* emit function is identical to of the first example */
+
+    struct uinput_user_dev uud;
+
+    fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
+
+    /* the ioctls below enables the to be created device to 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);
+
+    /* UI_DEV_CREATE causes the kernel to create the device nodes for this
+     * device. Insert a pause so that userspace has time to detect,
+     * initialize the new device, and can start to listen to events from
+     * this device
+     **/
+
+    /* key press, report the event, send key release, and report again */
+    emit(EV_KEY, KEY_SPACE, 1);
+    emit(EV_SYN, SYN_REPORT, 0);
+    emit(EV_KEY, KEY_SPACE, 0);
+    emit(EV_SYN, SYN_REPORT, 0);
+
+    ioctl(fd, UI_DEV_DESTROY);
+    close(fd);
+
+    return 0;
+
-- 
2.9.3

       reply	other threads:[~2017-03-24  3:36 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20170324033502.17398-1-marcos.souza.org@gmail.com>
2017-03-24  3:34 ` Marcos Paulo de Souza [this message]
2017-03-24  4:39   ` [PATCH v2] Documentation: Input: Add uinput documentation Peter Hutterer
2017-03-26 16:21     ` Marcos Paulo de Souza
2017-03-26 22:52       ` Peter Hutterer
2017-03-27  2:23         ` Marcos Paulo de Souza

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170324033502.17398-2-marcos.souza.org@gmail.com \
    --to=marcos.souza.org@gmail.com \
    --cc=benjamin.tissoires@redhat.com \
    --cc=corbet@lwn.net \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peter.hutterer@who-t.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox