All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] Adding uinput documentation
@ 2017-03-26 16:48 Marcos Paulo de Souza
  2017-03-26 16:48 ` [PATCH v3] Documentation: Input: Add " Marcos Paulo de Souza
  0 siblings, 1 reply; 4+ messages in thread
From: Marcos Paulo de Souza @ 2017-03-26 16:48 UTC (permalink / raw)
  To: corbet, linux-doc, dmitry.torokhov, linux-input, linux-kernel,
	peter.hutterer
  Cc: Marcos Paulo de Souza

Hi all,

this is the third version of the patchset, solved some typos and suggestions from
Peter and Jon Corbet.

Thanks for the suggestions. I hope this version is better than the last one.

Marcos Paulo de Souza (1):
  Documentation: Input: Add uinput documentation

 Documentation/input/uinput.rst | 207 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 207 insertions(+)
 create mode 100644 Documentation/input/uinput.rst

-- 
2.9.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v3] Documentation: Input: Add uinput documentation
  2017-03-26 16:48 [PATCH v3] Adding uinput documentation Marcos Paulo de Souza
@ 2017-03-26 16:48 ` Marcos Paulo de Souza
  2017-03-27  1:06   ` Peter Hutterer
  0 siblings, 1 reply; 4+ messages in thread
From: Marcos Paulo de Souza @ 2017-03-26 16:48 UTC (permalink / raw)
  To: corbet, linux-doc, dmitry.torokhov, linux-input, linux-kernel,
	peter.hutterer
  Cc: Marcos Paulo de Souza

Signed-off-by: Marcos Paulo de Souza <marcos.souza.org@gmail.com>
---
 v2 -> v3:
 Changes in libevdev's description (suggested by Peter)
 Added uinput version check when using the old interface (suggested by Peter)
 Removed section numbers from sections, sphinx creates these indexes
 	(suggestion by Jon)

 v1 -> v2:
 Changes all over the place, including better descriptions (suggested by Peter)
 Added comments about the need of a sleep call (suggested by Peter)
 

 Documentation/input/uinput.rst | 207 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 207 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..f606989
--- /dev/null
+++ b/Documentation/input/uinput.rst
@@ -0,0 +1,207 @@
+=============
+uinput module
+=============
+
+Introduction
+============
+
+uinput is a kernel module that makes it possible to emulate 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 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>
+
+   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 */
+        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 creates 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
+         */
+        sleep(1);
+
+        /* 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;
+   }
+
+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 */
+    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 creates 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
+     */
+    sleep(1);
+
+    /* 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;
+
+uinput old interface
+--------------------
+
+Before uinput version 5, there wasn't a proper ioctl to setup a virtual device.
+In this case, the user neesa to fill a different struct and call write o the
+uinput file descriptor to configure the new uinput device.
+
+.. code-block:: c
+
+    #include <linux/uinput.h>
+
+    /* emit function is identical to of the first example */
+
+    struct uinput_user_dev uud;
+    int version;
+
+    fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
+    ioctl(fd, UI_GET_VERSION, &version);
+
+    if (version < 5) {
+        /*
+         * 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);
+
+        /*
+         * On UI_DEV_CREATE the kernel creates 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
+         */
+        sleep(1);
+
+        /* 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

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v3] Documentation: Input: Add uinput documentation
  2017-03-26 16:48 ` [PATCH v3] Documentation: Input: Add " Marcos Paulo de Souza
@ 2017-03-27  1:06   ` Peter Hutterer
  2017-03-27  2:41     ` Marcos Paulo de Souza
  0 siblings, 1 reply; 4+ messages in thread
From: Peter Hutterer @ 2017-03-27  1:06 UTC (permalink / raw)
  To: Marcos Paulo de Souza
  Cc: corbet, linux-doc, dmitry.torokhov, linux-input, linux-kernel

On Sun, Mar 26, 2017 at 01:48:12PM -0300, Marcos Paulo de Souza wrote:
> Signed-off-by: Marcos Paulo de Souza <marcos.souza.org@gmail.com>
> ---
>  v2 -> v3:
>  Changes in libevdev's description (suggested by Peter)
>  Added uinput version check when using the old interface (suggested by Peter)
>  Removed section numbers from sections, sphinx creates these indexes
>  	(suggestion by Jon)
> 
>  v1 -> v2:
>  Changes all over the place, including better descriptions (suggested by Peter)
>  Added comments about the need of a sleep call (suggested by Peter)
>  


[...]

tested mouse/keyboard - works as expected, thanks. I found it slightly
confusing though that the mouse example wasn't wrapped in main() but still had a
return 0 at the bottom. This code will never change once it's in the doc, so
I'm not sure skipping things is really that useful here.

> +uinput old interface
> +--------------------
> +
> +Before uinput version 5, there wasn't a proper ioctl to setup a virtual device.
> +In this case, the user neesa to fill a different struct and call write o the
> +uinput file descriptor to configure the new uinput device.
> +
> +.. code-block:: c
> +
> +    #include <linux/uinput.h>
> +
> +    /* emit function is identical to of the first example */
> +
> +    struct uinput_user_dev uud;
> +    int version;
> +
> +    fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
> +    ioctl(fd, UI_GET_VERSION, &version);
> +
> +    if (version < 5) {

this won't work on all kernels. UI_GET_VERSION was added in version 4, on
kernels before you get rc == -1 and errno EINVAL. You can only check
for >= 4. Please make sure the example compiles and works on an older
kernel, otherwise there's no point shipping it.

Cheers,
   Peter

> +        /*
> +         * 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);
> +
> +        /*
> +         * On UI_DEV_CREATE the kernel creates 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
> +         */
> +        sleep(1);
> +
> +        /* 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
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v3] Documentation: Input: Add uinput documentation
  2017-03-27  1:06   ` Peter Hutterer
@ 2017-03-27  2:41     ` Marcos Paulo de Souza
  0 siblings, 0 replies; 4+ messages in thread
From: Marcos Paulo de Souza @ 2017-03-27  2:41 UTC (permalink / raw)
  To: Peter Hutterer
  Cc: corbet, linux-doc, dmitry.torokhov, linux-input, linux-kernel

On Mon, Mar 27, 2017 at 11:06:11AM +1000, Peter Hutterer wrote:
> On Sun, Mar 26, 2017 at 01:48:12PM -0300, Marcos Paulo de Souza wrote:
> > Signed-off-by: Marcos Paulo de Souza <marcos.souza.org@gmail.com>
> > ---
> >  v2 -> v3:
> >  Changes in libevdev's description (suggested by Peter)
> >  Added uinput version check when using the old interface (suggested by Peter)
> >  Removed section numbers from sections, sphinx creates these indexes
> >  	(suggestion by Jon)
> > 
> >  v1 -> v2:
> >  Changes all over the place, including better descriptions (suggested by Peter)
> >  Added comments about the need of a sleep call (suggested by Peter)
> >  
> 
> 
> [...]
> 
> tested mouse/keyboard - works as expected, thanks. I found it slightly
> confusing though that the mouse example wasn't wrapped in main() but still had a
> return 0 at the bottom. This code will never change once it's in the doc, so
> I'm not sure skipping things is really that useful here.

True, I'll "complete" the code in the next submission.

> 
> > +uinput old interface
> > +--------------------
> > +
> > +Before uinput version 5, there wasn't a proper ioctl to setup a virtual device.
> > +In this case, the user neesa to fill a different struct and call write o the
> > +uinput file descriptor to configure the new uinput device.
> > +
> > +.. code-block:: c
> > +
> > +    #include <linux/uinput.h>
> > +
> > +    /* emit function is identical to of the first example */
> > +
> > +    struct uinput_user_dev uud;
> > +    int version;
> > +
> > +    fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
> > +    ioctl(fd, UI_GET_VERSION, &version);
> > +
> > +    if (version < 5) {
> 
> this won't work on all kernels. UI_GET_VERSION was added in version 4, on
> kernels before you get rc == -1 and errno EINVAL. You can only check
> for >= 4. Please make sure the example compiles and works on an older
> kernel, otherwise there's no point shipping it.

OK, noting here.

> 
> Cheers,
>    Peter
> 
> > +        /*
> > +         * 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);
> > +
> > +        /*
> > +         * On UI_DEV_CREATE the kernel creates 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
> > +         */
> > +        sleep(1);
> > +
> > +        /* 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
> > 

-- 
Thanks,
	Marcos

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-03-27  2:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-26 16:48 [PATCH v3] Adding uinput documentation Marcos Paulo de Souza
2017-03-26 16:48 ` [PATCH v3] Documentation: Input: Add " Marcos Paulo de Souza
2017-03-27  1:06   ` Peter Hutterer
2017-03-27  2:41     ` Marcos Paulo de Souza

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.