*/
int libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs);
+
+enum EvdevLEDValues {
+ LIBEVDEV_LED_ON = 3,
+ LIBEVDEV_LED_OFF = 4,
+};
+
+/**
+ * @ingroup kernel
+ *
+ * Turn an LED on or off. Convenience function, if you need to modify multiple
+ * LEDs simultaneously, use libevdev_kernel_set_led_values() instead.
+ *
+ * @note enabling an LED requires write permissions on the device's file descriptor.
+ *
+ * @param dev The evdev device, already initialized with libevdev_set_fd()
+ * @param code The EV_LED event code to modify, one of LED_NUML, LED_CAPSL, ...
+ * @param value Specifies whether to turn the LED on or off
+ * @return zero on success, or a negative errno on failure
+ */
+int libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum EvdevLEDValues value);
+
+/**
+ * @ingroup kernel
+ *
+ * Turn multiple LEDs on or off simultaneously. This function expects a pair
+ * of LED codes and values to set them to, terminated by a -1. For example, to
+ * switch the NumLock LED on but the CapsLock LED off, use:
+ *
+ * @code
+ * libevdev_kernel_set_led_values(dev, LED_NUML, LIBEVDEV_LED_ON,
+ * LED_CAPSL, LIBEVDEV_LED_OFF,
+ * -1);
+ * @endcode
+ *
+ * If any LED code or value is invalid, this function returns -EINVAL and no
+ * LEDs are modified.
+ *
+ * @note enabling an LED requires write permissions on the device's file descriptor.
+ *
+ * @param dev The evdev device, already initialized with libevdev_set_fd()
+ * @param ... A pair of LED_* event codes and enum EvdevLEDValues, followed by
+ * -1 to terminate the list.
+ * @return zero on success, or a negative errno on failure
+ */
+int libevdev_kernel_set_led_values(struct libevdev *dev, ...);
+
/**
* @ingroup misc
*
}
END_TEST
+START_TEST(test_led_valid)
+{
+ struct uinput_device* uidev;
+ struct libevdev *dev;
+ int rc;
+
+ rc = test_create_device(&uidev, &dev,
+ EV_LED, LED_NUML,
+ EV_LED, LED_CAPSL,
+ EV_LED, LED_COMPOSE,
+ -1);
+ ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
+
+ rc = libevdev_kernel_set_led_value(dev, LED_NUML, LIBEVDEV_LED_ON);
+ ck_assert_int_eq(rc, 0);
+ rc = libevdev_kernel_set_led_value(dev, LED_NUML, LIBEVDEV_LED_OFF);
+ ck_assert_int_eq(rc, 0);
+
+ rc = libevdev_kernel_set_led_values(dev,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_CAPSL, LIBEVDEV_LED_ON,
+ LED_COMPOSE, LIBEVDEV_LED_OFF,
+ -1);
+ ck_assert_int_eq(rc, 0);
+ ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_NUML));
+ ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_CAPSL));
+ ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_COMPOSE));
+
+ rc = libevdev_kernel_set_led_values(dev,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_CAPSL, LIBEVDEV_LED_OFF,
+ LED_COMPOSE, LIBEVDEV_LED_ON,
+ -1);
+ ck_assert_int_eq(rc, 0);
+ ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_NUML));
+ ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_CAPSL));
+ ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_COMPOSE));
+
+ /* make sure we ignore unset leds */
+ rc = libevdev_kernel_set_led_values(dev,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_CAPSL, LIBEVDEV_LED_OFF,
+ LED_SCROLLL, LIBEVDEV_LED_OFF,
+ LED_COMPOSE, LIBEVDEV_LED_ON,
+ -1);
+ ck_assert_int_eq(rc, 0);
+ ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_NUML));
+ ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_CAPSL));
+ ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_COMPOSE));
+
+ libevdev_free(dev);
+ uinput_device_free(uidev);
+}
+END_TEST
+
+START_TEST(test_led_invalid)
+{
+ struct uinput_device* uidev;
+ struct libevdev *dev;
+ int rc;
+
+ rc = test_create_device(&uidev, &dev,
+ EV_LED, LED_NUML,
+ EV_LED, LED_CAPSL,
+ EV_LED, LED_COMPOSE,
+ -1);
+ ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
+
+ rc = libevdev_kernel_set_led_value(dev, LED_MAX + 1, LIBEVDEV_LED_ON);
+ ck_assert_int_eq(rc, -EINVAL);
+
+ rc = libevdev_kernel_set_led_value(dev, LED_NUML, LIBEVDEV_LED_OFF + 1);
+ ck_assert_int_eq(rc, -EINVAL);
+
+ rc = libevdev_kernel_set_led_value(dev, LED_SCROLLL, LIBEVDEV_LED_ON);
+ ck_assert_int_eq(rc, 0);
+
+ rc = libevdev_kernel_set_led_values(dev,
+ LED_NUML, LIBEVDEV_LED_OFF + 1,
+ -1);
+ ck_assert_int_eq(rc, -EINVAL);
+
+ rc = libevdev_kernel_set_led_values(dev,
+ LED_MAX + 1, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF + 1,
+ -1);
+ ck_assert_int_eq(rc, -EINVAL);
+
+ rc = libevdev_kernel_set_led_values(dev,
+ LED_SCROLLL, LIBEVDEV_LED_OFF,
+ -1);
+ ck_assert_int_eq(rc, 0);
+
+ libevdev_free(dev);
+ uinput_device_free(uidev);
+}
+END_TEST
+
+START_TEST(test_led_same)
+{
+ struct uinput_device* uidev;
+ struct libevdev *dev;
+ int rc;
+
+ rc = test_create_device(&uidev, &dev,
+ EV_LED, LED_NUML,
+ EV_LED, LED_CAPSL,
+ EV_LED, LED_COMPOSE,
+ -1);
+ ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
+
+ rc = libevdev_kernel_set_led_values(dev,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ LED_NUML, LIBEVDEV_LED_OFF,
+ LED_NUML, LIBEVDEV_LED_ON,
+ /* more than LED_CNT */
+ -1);
+ ck_assert_int_eq(rc, 0);
+ ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_NUML));
+ ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_CAPSL));
+ ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_COMPOSE));
+
+ libevdev_free(dev);
+ uinput_device_free(uidev);
+}
+END_TEST
Suite *
libevdev_has_event_test(void)
{
tcase_add_test(tc, test_device_kernel_change_axis_invalid);
suite_add_tcase(s, tc);
+ tc = tcase_create("led manipulation");
+ tcase_add_test(tc, test_led_valid);
+ tcase_add_test(tc, test_led_invalid);
+ tcase_add_test(tc, test_led_same);
+ suite_add_tcase(s, tc);
+
return s;
}