Examples

The examples included here available in the examples/ directory of the git source.

Printing the capabilities of a device and its events

#!/usr/bin/env python3

import sys
import libevdev


def print_capabilities(l):
    v = l.driver_version
    print("Input driver version is {}.{}.{}".format(v >> 16, (v >> 8) & 0xff, v & 0xff))
    id = l.id
    print("Input device ID: bus {:#x} vendor {:#x} product {:#x} version {:#x}".format(
        id["bustype"],
        id["vendor"],
        id["product"],
        id["version"],
    ))
    print("Input device name: {}".format(l.name))
    print("Supported events:")

    for t, cs in l.evbits.items():
        print("  Event type {} ({})".format(t.value, t.name))

        for c in cs:
            if t in [libevdev.EV_LED, libevdev.EV_SND, libevdev.EV_SW]:
                v = l.value[c]
                print("    Event code {} ({}) state {}".format(c.value, c.name, v))
            else:
                print("    Event code {} ({})".format(c.value, c.name))

            if t == libevdev.EV_ABS:
                a = l.absinfo[c]
                print("       {:10s} {:6d}".format('Value', a.value))
                print("       {:10s} {:6d}".format('Minimum', a.minimum))
                print("       {:10s} {:6d}".format('Maximum', a.maximum))
                print("       {:10s} {:6d}".format('Fuzz', a.fuzz))
                print("       {:10s} {:6d}".format('Flat', a.flat))
                print("       {:10s} {:6d}".format('Resolution', a.resolution))

    print("Properties:")
    for p in l.properties:
        print("  Property type {} ({})".format(p.value, p.name))


def print_event(e):
    print("Event: time {}.{:06d}, ".format(e.sec, e.usec), end='')
    if e.matches(libevdev.EV_SYN):
        if e.matches(libevdev.EV_SYN.SYN_MT_REPORT):
            print("++++++++++++++ {} ++++++++++++".format(e.code.name))
        elif e.matches(libevdev.EV_SYN.SYN_DROPPED):
            print(">>>>>>>>>>>>>> {} >>>>>>>>>>>>".format(e.code.name))
        else:
            print("-------------- {} ------------".format(e.code.name))
    else:
        print("type {:02x} {} code {:03x} {:20s} value {:4d}".format(e.type.value, e.type.name, e.code.value, e.code.name, e.value))


def main(args):
    path = args[1]
    try:
        with open(path, "rb") as fd:
            dev = libevdev.Device(fd)
            print_capabilities(dev)
            print("################################\n"
                  "#      Waiting for events      #\n"
                  "################################")

            while True:
                try:
                    for e in dev.events():
                        print_event(e)
                except libevdev.EventsDroppedException:
                    for e in dev.sync():
                        print_event(e)

    except KeyboardInterrupt:
        pass
    except IOError as e:
        import errno
        if e.errno == errno.EACCES:
            print("Insufficient permissions to access {}".format(path))
        elif e.errno == errno.ENOENT:
            print("Device {} does not exist".format(path))
        else:
            raise e


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: {} /dev/input/eventX".format(sys.argv[0]))
        sys.exit(1)
    main(sys.argv)

Creating a uinput device and sending events

#!/usr/bin/env python3

import sys
import libevdev
from libevdev import InputEvent
import time


def main(args):
    dev = libevdev.Device()
    dev.name = "test device"
    dev.enable(libevdev.EV_REL.REL_X)
    dev.enable(libevdev.EV_REL.REL_Y)
    dev.enable(libevdev.EV_KEY.BTN_LEFT)
    dev.enable(libevdev.EV_KEY.BTN_RIGHT)
    try:
        uinput = dev.create_uinput_device()
        print("New device at {} ({})".format(uinput.devnode, uinput.syspath))

        # Sleep for a bit so udev, libinput, Xorg, Wayland, ... all have had
        # a chance to see the device and initialize it. Otherwise the event
        # will be sent by the kernel but nothing is ready to listen to the
        # device yet.
        time.sleep(1)

        for _ in range(5):
            events = [InputEvent(libevdev.EV_REL.REL_X, -1),
                      InputEvent(libevdev.EV_REL.REL_Y, 1),
                      InputEvent(libevdev.EV_SYN.SYN_REPORT, 0)]
            time.sleep(0.012)
            uinput.send_events(events)
    except OSError as e:
        print(e)


if __name__ == "__main__":
    main(sys.argv)

Filtering and re-routing events from a device

#!/usr/bin/env python3
#
# This example shows how to 'filter' device events from a device node.
# While real filtering is not possible, we can duplicate the input device as
# a new virtual input device and replay all events of the input events on
# our virtual one.

import sys
import libevdev


def main(args):
    path = args[1]
    code_from = libevdev.evbit(args[2])
    code_to = libevdev.evbit(args[3])

    print('Remapping {} to {}'.format(code_from, code_to))

    fd = open(path, 'rb')
    d = libevdev.Device(fd)
    d.grab()

    # create a duplicate of our input device
    d.enable(code_to)  # make sure the code we map to is available
    uidev = d.create_uinput_device()
    print('Device is at {}'.format(uidev.devnode))

    while True:
        for e in d.events():
            # change any event with our event code to
            # the one we want to map to, but pass all other events
            # through
            if e.code == code_from:
                e = libevdev.InputEvent(code_to, e.value)
            uidev.send_events([e])


if __name__ == "__main__":
    if len(sys.argv) < 4:
        print("Usage: {} /dev/input/eventX <from> <to>".format(sys.argv[0]))
        print("   where <from> and <to> are event codes, e.g. REL_X")
        sys.exit(1)
    main(sys.argv)

Updating the kernel device’s axis ranges

#!/usr/bin/env python3
#
# This example shows how to update a kernel device's axis range
# This can be useful to e.g. change the resolution on a touchpad.
# Note that this is an example only, there are a lot of race conditions to
# be considered when using this as a proper solution.

import sys
import libevdev


def main(args):
    path = args[1]
    axis = args[2]
    field = args[3]
    value = int(args[4])

    assert field in ['minimum', 'maximum', 'resolution']
    axis = libevdev.evbit(axis)
    assert axis is not None

    fd = open(path, 'rb')
    d = libevdev.Device(fd)
    if not d.has(axis):
        print('Device does not have axis {}'.format(axis))
        sys.exit(1)

    a = d.absinfo[axis]
    setattr(a, field, value)
    d.absinfo[axis] = a
    d.sync_absinfo_to_kernel(axis)


if __name__ == "__main__":
    if len(sys.argv) < 5:
        print("Usage: {} /dev/input/eventX <axis> <field> <value>".format(sys.argv[0]))
        print("   <axis> ... an EV_ABS event code, e.g. ABS_X")
        print("   <field> .. one of 'minimum', 'maximum', 'resolution'")
        print("   <value> .. the numeric value to set the axis field to")
        sys.exit(1)
    main(sys.argv)