Examples — libevdev Python wrapper 0.13.1 documentation

# 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(dev):
        v = dev.driver_version
        print("Input driver version is {}.{}.{}".format(v >> 16, (v >> 8) & 0xFF, v & 0xFF))
        id = dev.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(dev.name))
        print("Supported events:")

        for t, cs in dev.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 = dev.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 = dev.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 dev.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.SYN_MT_REPORT):
                print("++++++++++++++ {} ++++++++++++".format(e.code.name))
            elif e.matches(libevdev.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.REL_X)
        dev.enable(libevdev.REL_Y)
        dev.enable(libevdev.BTN_LEFT)
        dev.enable(libevdev.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.REL_X, -1),
                    InputEvent(libevdev.REL_Y, 1),
                    InputEvent(libevdev.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)