Question

I would like to write an application to generate keyboard input (i.e. to the system it would look just like a button on the keyboard had been pressed) for a Linux system. I would like to use C and xdotools are not an option. Libevdev looks promising, but so far I haven't been able to get it to work.

First, can libevdev do what I want? Most of the documentation is focused on reading the incoming input and outputting it, but the API does feature a function to "Post an event through the uinput device."

There is also an example for creating a device. I modified the example as follows:

#include <stdio.h>
#include <libevdev.h>
#include <libevdev-uinput.h>

int main(int argc, char **argv)
{
    int err;
    struct libevdev *dev;
    struct libevdev_uinput *uidev;

    dev = libevdev_new();
    libevdev_set_name(dev, "fake keyboard device");

    libevdev_enable_event_type(dev, EV_KEY);
    libevdev_enable_event_code(dev, EV_KEY, KEY_A, NULL);

    err = libevdev_uinput_create_from_device(dev,
        LIBEVDEV_UINPUT_OPEN_MANAGED,
        &uidev);

    if (err != 0)
        return err;

    libevdev_uinput_write_event(uidev, EV_KEY, KEY_A, 1);
    libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
    libevdev_uinput_write_event(uidev, EV_KEY, KEY_A, 0);
    libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);

    libevdev_uinput_destroy(uidev);
    printf("Complete\n");
}

When I run this application, I don't see any errors (the error handling was removed from the above code for brevity), but I also don't see the "A" key get pressed. Am I doing something wrong or do I have the wrong expectations for this library?

Was it helpful?

Solution

There's nothing wrong with your code per se, it looks like a timing issue. If you're running this from within X for example, by the time the X server got the udev event, told the evdev driver to open the device, etc. the device is gone again. You should see a message to that effect in the Xorg.log.

If you check the source for libevdev, you'll see that it's really just a small wrapper around writing to /dev/uinput. All it provides is better type-safety and slightly easier code.

The delay is the easiest solution, a more complex one would be to either check that X initialized the device correctly or at least check with udev that the device appeared.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top