# Examples

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

- Printing the capabilities of a device and its events

- Creating a uinput device and sending events

- Filtering and re-routing events from a device

- Updating the kernel device’s axis ranges

## 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)