diff --git a/examples/led-toggle.py b/examples/led-toggle.py new file mode 100755 index 0000000000000000000000000000000000000000..da81f0f20cad27c8cb6bd79d0b34c80d0a97dcf8 --- /dev/null +++ b/examples/led-toggle.py @@ -0,0 +1,65 @@ +#!/usr/bin/python3 + +import libevdev +import sys + + +def toggle(path, ledstr): + ledmap = { + 'numlock': (libevdev.EV_LED.LED_NUML, libevdev.EV_KEY.KEY_NUMLOCK), + 'capslock': (libevdev.EV_LED.LED_CAPSL, libevdev.EV_KEY.KEY_CAPSLOCK), + 'scrolllock': (libevdev.EV_LED.LED_SCROLLL, libevdev.EV_KEY.KEY_SCROLLLOCK), + } + + if ledstr not in ledmap: + print('Unknown LED: "{}". Use one of "{}".'.format(ledstr, '", "'.join(ledmap.keys()))) + sys.exit(1) + + led, key = ledmap[ledstr] + + with open(path, 'r+b', buffering=0) as fd: + d = libevdev.Device(fd) + if not d.has(led): + print('Device does not have a {} LED'.format(ledstr)) + sys.exit(0) + + if not d.has(key): + print('Device does not have a {} key'.format(ledstr)) + sys.exit(0) + + state = d.value[key] + print('{} {}'.format(ledstr, 'on' if state else 'off')) + + while True: + for e in d.events(): + if not e.matches(key): + continue + + if not e.value: + continue + + state = not state + d.set_leds([(led, state)]) + print('{} {}'.format(ledstr, 'on' if state else 'off')) + + +if __name__ == "__main__": + if len(sys.argv) < 3: + print("Usage: {} /dev/input/eventX {{numlock|capslock|scrolllock}}".format(sys.argv[0])) + sys.exit(1) + + path = sys.argv[1] + ledstr = sys.argv[2] + + try: + toggle(path, ledstr) + 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 diff --git a/libevdev/_clib.py b/libevdev/_clib.py index 11daccf15ffa4dae675ea627ed56ff6e0360095f..824f1fe7a638cddadd4a39336299ce4152d42492 100644 --- a/libevdev/_clib.py +++ b/libevdev/_clib.py @@ -287,6 +287,11 @@ class Libevdev(_LibraryWrapper): "argtypes": (c_void_p, c_int, ctypes.POINTER(_InputAbsinfo)), "restype": (c_int) }, + # int libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int, enum libevdev_led_value); + "libevdev_kernel_set_led_value": { + "argtypes": (c_void_p, c_int, c_int), + "restype": (c_int) + }, ########################## # Various has_ functions # ########################## @@ -836,7 +841,7 @@ class Libevdev(_LibraryWrapper): """ t, c = self._code("EV_LED", led) which = 3 if on else 4 - self._set_led_value(self._ctx, c, which) + self._kernel_set_led_value(self._ctx, c, which) def next_event(self, flags=READ_FLAG_NORMAL): """ diff --git a/libevdev/device.py b/libevdev/device.py index 2ff63ce833c02ee48ef42cbb7efd8aa9fbd94234..0347cfbb5930b1dbe48c0c83289e3c1d64f3777e 100644 --- a/libevdev/device.py +++ b/libevdev/device.py @@ -822,3 +822,21 @@ class Device(object): """ self._libevdev.grab(False) self._is_grabbed = False + + def set_leds(self, leds): + """ + Write the LEDs to the device:: + + >>> fd = open(path, 'r+b', buffering=0) + >>> d = libevdev.Device(fd) + >>> d.set_leds([(libevdev.EV_LED.LED_NUML, 0), + (libevdev.EV_LED.LED_SCROLLL, 1)]) + + Updating LED states require the fd to be in write-mode. + """ + for led in leds: + if led[0].type is not libevdev.EV_LED: + raise InvalidArgumentException('Event code must be one of EV_LED.*') + + for led in leds: + self._libevdev.set_led(led[0].value, led[1])