All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Hutterer <peter.hutterer@who-t.net>
To: Marcos Paulo de Souza <marcos.souza.org@gmail.com>
Cc: corbet@lwn.net, linux-doc@vger.kernel.org,
	dmitry.torokhov@gmail.com, linux-input@vger.kernel.org,
	benjamin.tissoires@redhat.com, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] Documentation: Input: Add uinput documentation
Date: Mon, 27 Mar 2017 08:52:58 +1000	[thread overview]
Message-ID: <20170326225258.GA14405@jelly> (raw)
In-Reply-To: <20170326162112.GA2267@xfiles.domain.name>

On Sun, Mar 26, 2017 at 01:21:14PM -0300, Marcos Paulo de Souza wrote:
> On Fri, Mar 24, 2017 at 02:39:13PM +1000, Peter Hutterer wrote:
> > as usual, reading through these things multiple times means one spots a
> > couple of different things. sorry about that.
> > 
> > On Fri, Mar 24, 2017 at 12:34:59AM -0300, Marcos Paulo de Souza wrote:
> > > 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
> > 
> > typo: makes *it* possible.
> > 
> > replace "to create and handle" with "to emulate", the rest is in the next
> > sentence anyway
> 
> Fixed.
> 
> > 
> > > +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.
> > 
> > "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".
> 
> Much better. Fixed.
> 
> > 
> > > +
> > > +For examples and more information about libevdev:
> > > +https://cgit.freedesktop.org/libevdev
> > > +
> > 
> > Please use https://www.freedesktop.org/software/libevdev/doc/latest/
> > (which needs a link to the git repo, I'll fix that in a minute)
> 
> Fixed.
> 
> > 
> > > +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
> > > +         **/
> > 
> > the comment terminator doesn't look right
> 
> Fixed.
> 
> > 
> > > +        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 */
> > 
> > add a sample product id too please
> Added.
> 
> > 
> > > +        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
> > 
> > "On UI_DEV_CREATE the kernel creates the device nodes..."
> Fixed.
> 
> > 
> > > +         * 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
> > > +         **/
> > 
> > the comment terminator doesn't look right
> > 
> > note: the actual pause is missing now :)
> 
> I thought you wanted just the warning, but ok, I added back the sleep
> call :)

better to have something that can be copy-pasted and works than expecting
people to add misc bits.

> > > +
> > > +        /* 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);
> > 
> > come to think of it, you probably need a pause here too, iirc a caller may
> > get ENODEV before reading the key events otherwise.
> 
> We need a sleep call after each emitted event?

no, I think we need a sleep between the final emit and the
UI_DEV_DESTROY, otherwise those events may not get delivered (not 100%
sure).

Cheers,
   Peter

> 
> > 
> > > +
> > > +        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.
> > 
> > I think this should really include the version check.
> 
> Uhg, I forgot this one again. Fixed here.
> 
> Sending a new version soon.
> 
> > 
> > Cheers,
> >    Peter
> > 
> > > +
> > > +.. 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
> > > 
> 
> -- 
> Thanks,
> 	Marcos

  reply	other threads:[~2017-03-26 22:53 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-24  3:34 [PATCH v2] Docs: Input: initial uinput documentation Marcos Paulo de Souza
2017-03-24  3:34 ` [PATCH v2] Documentation: Input: Add " Marcos Paulo de Souza
2017-03-24  4:39   ` Peter Hutterer
2017-03-26 16:21     ` Marcos Paulo de Souza
2017-03-26 22:52       ` Peter Hutterer [this message]
2017-03-27  2:23         ` Marcos Paulo de Souza
2017-03-24 21:17 ` [PATCH v2] Docs: Input: initial " Jonathan Corbet
2017-03-26 16:41   ` Marcos Paulo de Souza
2017-03-26 23:08     ` Peter Hutterer

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=20170326225258.GA14405@jelly \
    --to=peter.hutterer@who-t.net \
    --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=marcos.souza.org@gmail.com \
    /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 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.