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