From a36dcecd9e11804ed8e6a01d651ae4cc79b9cb32 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 14 Aug 2013 09:44:21 +1000 Subject: [PATCH 1/8] Sync the key state on startup Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 0d315ec..0641b97 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -232,6 +232,10 @@ libevdev_set_fd(struct libevdev* dev, int fd) if (rc < 0) goto out; + rc = ioctl(fd, EVIOCGKEY(sizeof(dev->key_values)), dev->key_values); + if (rc < 0) + goto out; + /* rep is a special case, always set it to 1 for both values if EV_REP is set */ if (bit_is_set(dev->bits, EV_REP)) { for (i = 0; i < REP_CNT; i++) From 62db838128fc76454466e28149c94362195322a4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 9 Aug 2013 13:47:00 +1000 Subject: [PATCH 2/8] Rename libevdev_kernel_set_abs_value to libevdev_kernel_set_abs_info Keep it in line with the non-kernel setter Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev.c | 7 +++++++ libevdev/libevdev.h | 6 +++++- test/test-libevdev-has-event.c | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 0641b97..4603651 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -961,8 +961,15 @@ libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigned in return 0; } +/* DEPRECATED */ int libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs) +{ + return libevdev_kernel_set_abs_info(dev, code, abs); +} + +int +libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs) { int rc; diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index bd65175..ccb2cc7 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -1092,7 +1092,7 @@ int libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigne * * @see libevdev_enable_event_code */ -int libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs); +int libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs); /** * @ingroup misc @@ -1227,5 +1227,9 @@ int libevdev_get_vendor_id(const struct libevdev *dev) LIBEVDEV_DEPRECATED; int libevdev_get_bustype(const struct libevdev *dev) LIBEVDEV_DEPRECATED; int libevdev_get_version(const struct libevdev *dev) LIBEVDEV_DEPRECATED; +/* replacement: libevdev_kernel_set_abs_info */ +int libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs) LIBEVDEV_DEPRECATED; + + /**************************************/ #endif /* LIBEVDEV_H */ diff --git a/test/test-libevdev-has-event.c b/test/test-libevdev-has-event.c index 7ce616f..307ea58 100644 --- a/test/test-libevdev-has-event.c +++ b/test/test-libevdev-has-event.c @@ -866,7 +866,7 @@ START_TEST(test_device_kernel_change_axis) abs.fuzz = 10; abs.flat = 20; abs.resolution = 30; - rc = libevdev_kernel_set_abs_value(dev, ABS_X, &abs); + rc = libevdev_kernel_set_abs_info(dev, ABS_X, &abs); ck_assert_int_eq(rc, 0); ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_X), 500); @@ -915,7 +915,7 @@ START_TEST(test_device_kernel_change_axis_invalid) rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev); ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));; - rc = libevdev_kernel_set_abs_value(dev, ABS_MAX + 1, &abs); + rc = libevdev_kernel_set_abs_info(dev, ABS_MAX + 1, &abs); ck_assert_int_eq(rc, -EINVAL); libevdev_free(dev); From 74d9b4c72d2bf0e11784605579123d78cccc9092 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 9 Aug 2013 14:46:24 +1000 Subject: [PATCH 3/8] Add setters for an event or slot value Signed-off-by: Peter Hutterer --- libevdev/libevdev.c | 47 ++++++++++ libevdev/libevdev.h | 52 +++++++++++ test/test-libevdev-events.c | 180 ++++++++++++++++++++++++++++++++++++ 3 files changed, 279 insertions(+) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 4603651..cade991 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -773,6 +773,29 @@ libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned return value; } +int libevdev_set_event_value(struct libevdev *dev, unsigned int type, unsigned int code, int value) +{ + int rc = 0; + struct input_event e; + + if (!libevdev_has_event_type(dev, type) || !libevdev_has_event_code(dev, type, code)) + return -1; + + e.type = type; + e.code = code; + e.value = value; + + switch(type) { + case EV_ABS: rc = update_abs_state(dev, &e); break; + case EV_KEY: rc = update_key_state(dev, &e); break; + default: + rc = -1; + break; + } + + return rc; +} + int libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, unsigned int code, int *value) { @@ -799,6 +822,30 @@ libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned return dev->mt_slot_vals[slot][code - ABS_MT_MIN]; } +int +libevdev_set_slot_value(struct libevdev *dev, unsigned int slot, unsigned int code, int value) +{ + if (!libevdev_has_event_type(dev, EV_ABS) || !libevdev_has_event_code(dev, EV_ABS, code)) + return -1; + + if (slot >= dev->num_slots || slot >= MAX_SLOTS) + return -1; + + if (code > ABS_MT_MAX || code < ABS_MT_MIN) + return -1; + + if (code == ABS_MT_SLOT) { + if (value < 0 || value >= libevdev_get_num_slots(dev)) + return -1; + dev->current_slot = value; + } + + dev->mt_slot_vals[slot][code - ABS_MT_MIN] = value; + + + return 0; +} + int libevdev_fetch_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code, int *value) { diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index ccb2cc7..4c01847 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -813,6 +813,30 @@ const struct input_absinfo* libevdev_get_abs_info(const struct libevdev *dev, un */ int libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned int code); +/** + * @ingroup kernel + * + * Set the value for a given event type and code. This only makes sense for + * some event types, e.g. setting the value for EV_REL is pointless. + * + * This is a local modification only affecting only this representation of + * this device. A future call to libevdev_get_event_value() will return this + * value, unless the value was overwritten by an event. + * + * @param dev The evdev device, already initialized with libevdev_set_fd() + * @param type The event type for the code to query (EV_SYN, EV_REL, etc.) + * @param code The event code to set the value for, one of ABS_X, LED_NUML, etc. + * @param value The new value to set + * + * @return 0 on success, or -1 on failure. + * @retval -1 the device does not have the event type or code enabled, or the code is outside the + * allowed limits for the given type, or the type cannot be set. + * + * @see libevdev_set_slot_value + * @see libevdev_get_event_value + */ +int libevdev_set_event_value(struct libevdev *dev, unsigned int type, unsigned int code, int value); + /** * @ingroup bits * @@ -862,6 +886,34 @@ int libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, un */ int libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code); +/** + * @ingroup kernel + * + * Set the value for a given code for the given slot. + * + * This is a local modification only affecting only this representation of + * this device. A future call to libevdev_get_slot_value() will return this + * value, unless the value was overwritten by an event. + * + * This function does not set event values for axes outside the ABS_MT range, + * use libevdev_set_event_value() instead. + * + * @param dev The evdev device, already initialized with libevdev_set_fd() + * @param slot The numerical slot number, must be smaller than the total number + * of slots on this device + * @param code The event code to set the value for, one of ABS_MT_POSITION_X, etc. + * @param value The new value to set + * + * @return 0 on success, or -1 on failure. + * @retval -1 the device does not have the event code enabled, or the code is + * outside the allowed limits for multitouch events, or the slot number is outside + * the limits for this device, or the device does not support multitouch events. + * + * @see libevdev_set_event_value + * @see libevdev_get_slot_value + */ +int libevdev_set_slot_value(struct libevdev *dev, unsigned int slot, unsigned int code, int value); + /** * @ingroup mt * diff --git a/test/test-libevdev-events.c b/test/test-libevdev-events.c index 40f94dd..95105d1 100644 --- a/test/test-libevdev-events.c +++ b/test/test-libevdev-events.c @@ -806,6 +806,179 @@ START_TEST(test_mt_event_values_invalid) } END_TEST +START_TEST(test_event_value_setters) +{ + struct uinput_device* uidev; + struct libevdev *dev; + int rc; + struct input_absinfo abs[2]; + + memset(abs, 0, sizeof(abs)); + abs[0].value = ABS_X; + abs[0].maximum = 1000; + + abs[1].value = ABS_Y; + abs[1].maximum = 1000; + + rc = test_create_abs_device(&uidev, &dev, + 2, abs, + EV_SYN, SYN_REPORT, + EV_REL, REL_X, + EV_REL, REL_Y, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_MIDDLE, + EV_KEY, BTN_RIGHT, + -1); + ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); + + ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_LEFT), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_REL, REL_X), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_REL, REL_Y), 0); + + ck_assert_int_eq(libevdev_set_event_value(dev, EV_KEY, BTN_LEFT, 1), 0); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_KEY, BTN_RIGHT, 1), 0); + + ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_LEFT), 1); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_RIGHT), 1); + + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_X, 10), 0); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_Y, 20), 0); + + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 10); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 20); + + uinput_device_free(uidev); + libevdev_free(dev); + +} +END_TEST + +START_TEST(test_event_value_setters_invalid) +{ + struct uinput_device* uidev; + struct libevdev *dev; + int rc; + struct input_absinfo abs[2]; + + memset(abs, 0, sizeof(abs)); + abs[0].value = ABS_X; + abs[0].maximum = 1000; + + abs[1].value = ABS_Y; + abs[1].maximum = 1000; + + rc = test_create_abs_device(&uidev, &dev, + 2, abs, + EV_SYN, SYN_REPORT, + EV_REL, REL_X, + EV_REL, REL_Y, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_MIDDLE, + EV_KEY, BTN_RIGHT, + -1); + ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); + + ck_assert_int_eq(libevdev_set_event_value(dev, EV_REL, REL_X, 1), -1); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_SW, SW_DOCK, 1), -1); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_Z, 1), -1); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_MAX + 1, 0, 1), -1); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_SYN, SYN_REPORT, 0), -1); + + uinput_device_free(uidev); + libevdev_free(dev); + +} +END_TEST + +START_TEST(test_event_mt_value_setters) +{ + struct uinput_device* uidev; + struct libevdev *dev; + int rc; + struct input_absinfo abs[5]; + + memset(abs, 0, sizeof(abs)); + abs[0].value = ABS_X; + abs[0].maximum = 1000; + abs[1].value = ABS_MT_POSITION_X; + abs[1].maximum = 1000; + + abs[2].value = ABS_Y; + abs[2].maximum = 1000; + abs[3].value = ABS_MT_POSITION_Y; + abs[3].maximum = 1000; + + abs[4].value = ABS_MT_SLOT; + abs[4].maximum = 2; + + rc = test_create_abs_device(&uidev, &dev, + 5, abs, + EV_SYN, SYN_REPORT, + -1); + ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); + + ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_MT_POSITION_X, 1), 0); + ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_MT_POSITION_Y, 2), 0); + ck_assert_int_eq(libevdev_set_slot_value(dev, 0, ABS_MT_POSITION_X, 3), 0); + ck_assert_int_eq(libevdev_set_slot_value(dev, 0, ABS_MT_POSITION_Y, 4), 0); + + ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_X), 1); + ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_Y), 2); + ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_X), 3); + ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_Y), 4); + + ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_MT_SLOT, 1), 0); + ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_SLOT), 1); + ck_assert_int_eq(libevdev_get_current_slot(dev), 1); + + uinput_device_free(uidev); + libevdev_free(dev); +} +END_TEST + +START_TEST(test_event_mt_value_setters_invalid) +{ + struct uinput_device* uidev; + struct libevdev *dev; + int rc; + struct input_absinfo abs[5]; + + memset(abs, 0, sizeof(abs)); + abs[0].value = ABS_X; + abs[0].maximum = 1000; + abs[1].value = ABS_MT_POSITION_X; + abs[1].maximum = 1000; + + abs[2].value = ABS_Y; + abs[2].maximum = 1000; + abs[3].value = ABS_MT_POSITION_Y; + abs[3].maximum = 1000; + + abs[4].value = ABS_MT_SLOT; + abs[4].maximum = 2; + + rc = test_create_abs_device(&uidev, &dev, + 5, abs, + EV_SYN, SYN_REPORT, + -1); + ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); + + /* invalid axis */ + ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_Z, 1), -1); + /* valid, but non-mt axis */ + ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_X, 1), -1); + /* invalid mt axis */ + ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_MT_PRESSURE, 1), -1); + /* invalid slot no */ + ck_assert_int_eq(libevdev_set_slot_value(dev, 4, ABS_X, 1), -1); + + uinput_device_free(uidev); + libevdev_free(dev); +} +END_TEST + Suite * libevdev_events(void) { @@ -838,6 +1011,13 @@ libevdev_events(void) tcase_add_test(tc, test_mt_event_values_invalid); suite_add_tcase(s, tc); + tc = tcase_create("event value setters"); + tcase_add_test(tc, test_event_value_setters); + tcase_add_test(tc, test_event_value_setters_invalid); + tcase_add_test(tc, test_event_mt_value_setters); + tcase_add_test(tc, test_event_mt_value_setters_invalid); + suite_add_tcase(s, tc); + return s; } From bfb6c1c6c59bf1bb3a9bbab0ff26b962a4efc922 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 14 Aug 2013 09:29:41 +1000 Subject: [PATCH 4/8] Keep the LED state and sync it after SYN_DROPPED This enables libevdev_get_event_value(dev, EV_LED, LED_NUML); to check if a LED is on or off. Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev-int.h | 1 + libevdev/libevdev.c | 51 ++++++++++++++++++++++++++++++++++ test/test-libevdev-events.c | 55 +++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/libevdev/libevdev-int.h b/libevdev/libevdev-int.h index a36be62..28933ef 100644 --- a/libevdev/libevdev-int.h +++ b/libevdev/libevdev-int.h @@ -89,6 +89,7 @@ struct libevdev { unsigned long ff_bits[NLONGS(FF_CNT)]; unsigned long snd_bits[NLONGS(SND_CNT)]; unsigned long key_values[NLONGS(KEY_CNT)]; + unsigned long led_values[NLONGS(LED_CNT)]; struct input_absinfo abs_info[ABS_CNT]; unsigned int mt_slot_vals[MAX_SLOTS][ABS_MT_CNT]; int num_slots; /**< valid slots in mt_slot_vals */ diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index cade991..bd0c58c 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -236,6 +236,10 @@ libevdev_set_fd(struct libevdev* dev, int fd) if (rc < 0) goto out; + rc = ioctl(fd, EVIOCGLED(sizeof(dev->led_values)), dev->led_values); + if (rc < 0) + goto out; + /* rep is a special case, always set it to 1 for both values if EV_REP is set */ if (bit_is_set(dev->bits, EV_REP)) { for (i = 0; i < REP_CNT; i++) @@ -321,6 +325,32 @@ out: return rc ? -errno : 0; } +static int +sync_led_state(struct libevdev *dev) +{ + int rc; + int i; + unsigned long ledstate[NLONGS(LED_MAX)]; + + rc = ioctl(dev->fd, EVIOCGLED(sizeof(ledstate)), ledstate); + if (rc < 0) + goto out; + + for (i = 0; i < LED_MAX; i++) { + int old, new; + old = bit_is_set(dev->led_values, i); + new = bit_is_set(ledstate, i); + if (old ^ new) { + struct input_event *ev = queue_push(dev); + init_event(dev, ev, EV_LED, i, new ? 1 : 0); + } + set_bit_state(dev->led_values, i, new); + } + + rc = 0; +out: + return rc ? -errno : 0; +} static int sync_abs_state(struct libevdev *dev) { @@ -441,6 +471,8 @@ sync_state(struct libevdev *dev) if (libevdev_has_event_type(dev, EV_KEY)) rc = sync_key_state(dev); + if (libevdev_has_event_type(dev, EV_LED)) + rc = sync_led_state(dev); if (rc == 0 && libevdev_has_event_type(dev, EV_ABS)) rc = sync_abs_state(dev); if (rc == 0 && libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT)) @@ -502,6 +534,20 @@ update_abs_state(struct libevdev *dev, const struct input_event *e) return 0; } +static int +update_led_state(struct libevdev *dev, const struct input_event *e) +{ + if (!libevdev_has_event_type(dev, EV_LED)) + return 1; + + if (e->code > LED_MAX) + return 1; + + set_bit_state(dev->led_values, e->code, e->value != 0); + + return 0; +} + static int update_state(struct libevdev *dev, const struct input_event *e) { @@ -517,6 +563,9 @@ update_state(struct libevdev *dev, const struct input_event *e) case EV_ABS: rc = update_abs_state(dev, e); break; + case EV_LED: + rc = update_led_state(dev, e); + break; } dev->last_event_time = e->time; @@ -765,6 +814,7 @@ libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned switch (type) { case EV_ABS: value = dev->abs_info[code].value; break; case EV_KEY: value = bit_is_set(dev->key_values, code); break; + case EV_LED: value = bit_is_set(dev->led_values, code); break; default: value = 0; break; @@ -788,6 +838,7 @@ int libevdev_set_event_value(struct libevdev *dev, unsigned int type, unsigned i switch(type) { case EV_ABS: rc = update_abs_state(dev, &e); break; case EV_KEY: rc = update_key_state(dev, &e); break; + case EV_LED: rc = update_led_state(dev, &e); break; default: rc = -1; break; diff --git a/test/test-libevdev-events.c b/test/test-libevdev-events.c index 95105d1..afa426d 100644 --- a/test/test-libevdev-events.c +++ b/test/test-libevdev-events.c @@ -453,6 +453,52 @@ START_TEST(test_syn_delta_mt) } END_TEST +START_TEST(test_syn_delta_led) +{ + struct uinput_device* uidev; + struct libevdev *dev; + int rc; + struct input_event ev; + + rc = test_create_device(&uidev, &dev, + EV_SYN, SYN_REPORT, + EV_SYN, SYN_DROPPED, + EV_LED, LED_NUML, + EV_LED, LED_CAPSL, + -1); + ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); + + uinput_device_event(uidev, EV_LED, LED_NUML, 1); + uinput_device_event(uidev, EV_LED, LED_CAPSL, 1); + uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); + rc = libevdev_next_event(dev, LIBEVDEV_FORCE_SYNC, &ev); + ck_assert_int_eq(rc, 1); + + rc = libevdev_next_event(dev, LIBEVDEV_READ_SYNC, &ev); + ck_assert_int_eq(rc, 1); + ck_assert_int_eq(ev.type, EV_LED); + ck_assert_int_eq(ev.code, LED_NUML); + ck_assert_int_eq(ev.value, 1); + rc = libevdev_next_event(dev, LIBEVDEV_READ_SYNC, &ev); + ck_assert_int_eq(rc, 1); + ck_assert_int_eq(ev.type, EV_LED); + ck_assert_int_eq(ev.code, LED_CAPSL); + ck_assert_int_eq(ev.value, 1); + rc = libevdev_next_event(dev, LIBEVDEV_READ_SYNC, &ev); + ck_assert_int_eq(rc, 1); + ck_assert_int_eq(ev.type, EV_SYN); + ck_assert_int_eq(ev.code, SYN_REPORT); + rc = libevdev_next_event(dev, LIBEVDEV_READ_SYNC, &ev); + ck_assert_int_eq(rc, -EAGAIN); + + ck_assert_int_eq(libevdev_get_event_value(dev, EV_LED, LED_NUML), 1); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_LED, LED_CAPSL), 1); + + uinput_device_free(uidev); + libevdev_free(dev); +} +END_TEST + START_TEST(test_skipped_sync) { struct uinput_device* uidev; @@ -828,6 +874,8 @@ START_TEST(test_event_value_setters) EV_KEY, BTN_LEFT, EV_KEY, BTN_MIDDLE, EV_KEY, BTN_RIGHT, + EV_LED, LED_NUML, + EV_LED, LED_CAPSL, -1); ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); @@ -849,6 +897,12 @@ START_TEST(test_event_value_setters) ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 10); ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 20); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_LED, LED_NUML, 1), 0); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_LED, LED_CAPSL, 1), 0); + + ck_assert_int_eq(libevdev_get_event_value(dev, EV_LED, LED_NUML), 1); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_LED, LED_CAPSL), 1); + uinput_device_free(uidev); libevdev_free(dev); @@ -996,6 +1050,7 @@ libevdev_events(void) tcase_add_test(tc, test_syn_delta_button); tcase_add_test(tc, test_syn_delta_abs); tcase_add_test(tc, test_syn_delta_mt); + tcase_add_test(tc, test_syn_delta_led); suite_add_tcase(s, tc); tc = tcase_create("skipped syncs"); From 4d4293a65b604e0bf8d02dc729803f142fc665aa Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 9 Aug 2013 13:21:28 +1000 Subject: [PATCH 5/8] Add functions to toggle LEDs on the device Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev.c | 59 +++++++++++++ libevdev/libevdev.h | 46 ++++++++++ test/test-libevdev-has-event.c | 153 +++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index bd0c58c..25d33e7 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -1179,3 +1179,62 @@ libevdev_get_repeat(struct libevdev *dev, int *delay, int *period) return 0; } + +int +libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum EvdevLEDValues value) +{ + return libevdev_kernel_set_led_values(dev, code, value, -1); +} + +int +libevdev_kernel_set_led_values(struct libevdev *dev, ...) +{ + struct input_event ev[LED_MAX]; + enum EvdevLEDValues val; + va_list args; + int code; + int rc = 0; + size_t nleds = 0; + + memset(ev, 0, sizeof(ev)); + + va_start(args, dev); + code = va_arg(args, unsigned int); + while (code != -1) { + if (code > LED_MAX) { + rc = -EINVAL; + break; + } + val = va_arg(args, enum EvdevLEDValues); + if (val != LIBEVDEV_LED_ON && val != LIBEVDEV_LED_OFF) { + rc = -EINVAL; + break; + } + + if (libevdev_has_event_code(dev, EV_LED, code)) { + struct input_event *e = ev; + + while (e->type > 0 && e->code != code) + e++; + + if (e->type == 0) + nleds++; + e->type = EV_LED; + e->code = code; + e->value = (val == LIBEVDEV_LED_ON); + } + code = va_arg(args, unsigned int); + } + va_end(args); + + if (rc == 0 && nleds > 0) { + rc = write(libevdev_get_fd(dev), ev, nleds * sizeof(ev[0])); + if (rc > 0) { + while (nleds--) + update_led_state(dev, &ev[nleds]); + } + rc = (rc != -1) ? 0 : -errno; + } + + return rc; +} diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index 4c01847..db6a2ec 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -1146,6 +1146,52 @@ int libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigne */ 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 * diff --git a/test/test-libevdev-has-event.c b/test/test-libevdev-has-event.c index 307ea58..31a46ab 100644 --- a/test/test-libevdev-has-event.c +++ b/test/test-libevdev-has-event.c @@ -923,6 +923,153 @@ START_TEST(test_device_kernel_change_axis_invalid) } 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) { @@ -971,6 +1118,12 @@ 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; } From f29e4118fcbc58ad79561e64f7ede15f59224240 Mon Sep 17 00:00:00 2001 From: polyphemus Date: Fri, 9 Aug 2013 17:38:51 +0200 Subject: [PATCH 6/8] write EV_SYN input_event along with led events to device Other clients of an evdev device need to have the events they receive be separated, in moment in time, from other events by an EV_SYN/ SYN_REPORT. This is the responsibility of the client who writes events into the stream. Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 25d33e7..ba5b17f 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -1189,7 +1189,7 @@ libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum Evde int libevdev_kernel_set_led_values(struct libevdev *dev, ...) { - struct input_event ev[LED_MAX]; + struct input_event ev[LED_MAX + 1]; enum EvdevLEDValues val; va_list args; int code; @@ -1228,8 +1228,12 @@ libevdev_kernel_set_led_values(struct libevdev *dev, ...) va_end(args); if (rc == 0 && nleds > 0) { + ev[nleds].type = EV_SYN; + ev[nleds++].code = SYN_REPORT; + rc = write(libevdev_get_fd(dev), ev, nleds * sizeof(ev[0])); if (rc > 0) { + nleds--; /* last is EV_SYN */ while (nleds--) update_led_state(dev, &ev[nleds]); } From edc31cf12ef9f99e22aacdc93f12dc1511cd6ad0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 15 Aug 2013 11:10:17 +1000 Subject: [PATCH 7/8] Store the abs value after handling mt events This way any ABS_MT_ event value that comes in will also be stored in abs_info. That always corresponds to "current slot", so if a user calls libevdev_set_event_value() or libevdev_get_event_value() they're actually modifying the current slot value. When the current slot changes, sync the state back into the absinfo values. Signed-off-by: Peter Hutterer --- libevdev/libevdev.c | 9 ++++++- libevdev/libevdev.h | 8 ++++++ test/test-libevdev-events.c | 54 +++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index ba5b17f..e59d795 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -507,7 +507,14 @@ static int update_mt_state(struct libevdev *dev, const struct input_event *e) { if (e->code == ABS_MT_SLOT) { + int i; dev->current_slot = e->value; + /* sync abs_info with the current slot values */ + for (i = ABS_MT_SLOT + 1; i <= ABS_MT_MAX; i++) { + if (libevdev_has_event_code(dev, EV_ABS, i)) + dev->abs_info[i].value = dev->mt_slot_vals[dev->current_slot][i - ABS_MT_MIN]; + } + return 0; } else if (dev->current_slot == -1) return 1; @@ -527,7 +534,7 @@ update_abs_state(struct libevdev *dev, const struct input_event *e) return 1; if (e->code >= ABS_MT_MIN && e->code <= ABS_MT_MAX) - return update_mt_state(dev, e); + update_mt_state(dev, e); dev->abs_info[e->code].value = e->value; diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index db6a2ec..61553cc 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -799,6 +799,10 @@ const struct input_absinfo* libevdev_get_abs_info(const struct libevdev *dev, un * Behaviour of this function is undefined if the device does not provide * the event. * + * If the device supports ABS_MT_SLOT, the value returned for any ABS_MT_* + * event code is the value of the currently active slot. You should use + * libevdev_get_slot_value() instead. + * * @param dev The evdev device, already initialized with libevdev_set_fd() * @param type The event type for the code to query (EV_SYN, EV_REL, etc.) * @param code The event code to query for, one of ABS_X, REL_X, etc. @@ -823,6 +827,10 @@ int libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsi * this device. A future call to libevdev_get_event_value() will return this * value, unless the value was overwritten by an event. * + * If the device supports ABS_MT_SLOT, the value set for any ABS_MT_* + * event code is the value of the currently active slot. You should use + * libevdev_set_slot_value() instead. + * * @param dev The evdev device, already initialized with libevdev_set_fd() * @param type The event type for the code to query (EV_SYN, EV_REL, etc.) * @param code The event code to set the value for, one of ABS_X, LED_NUML, etc. diff --git a/test/test-libevdev-events.c b/test/test-libevdev-events.c index afa426d..669de12 100644 --- a/test/test-libevdev-events.c +++ b/test/test-libevdev-events.c @@ -1033,6 +1033,59 @@ START_TEST(test_event_mt_value_setters_invalid) } END_TEST +START_TEST(test_event_mt_value_setters_current_slot) +{ + struct uinput_device* uidev; + struct libevdev *dev; + int rc; + struct input_absinfo abs[5]; + + memset(abs, 0, sizeof(abs)); + abs[0].value = ABS_X; + abs[0].maximum = 1000; + abs[1].value = ABS_MT_POSITION_X; + abs[1].maximum = 1000; + + abs[2].value = ABS_Y; + abs[2].maximum = 1000; + abs[3].value = ABS_MT_POSITION_Y; + abs[3].maximum = 1000; + + abs[4].value = ABS_MT_SLOT; + abs[4].maximum = 2; + + rc = test_create_abs_device(&uidev, &dev, + 5, abs, + EV_SYN, SYN_REPORT, + -1); + ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); + + /* set_event_value/get_event_value works on the current slot */ + + ck_assert_int_eq(libevdev_get_current_slot(dev), 0); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_POSITION_X, 1), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_POSITION_X), 1); + ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_X), 1); + + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_SLOT, 1), 0); + ck_assert_int_eq(libevdev_get_current_slot(dev), 1); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_POSITION_X, 2), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_POSITION_X), 2); + ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_X), 2); + + /* set slot 0, but current is still slot 1 */ + ck_assert_int_eq(libevdev_set_slot_value(dev, 0, ABS_MT_POSITION_X, 3), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_POSITION_X), 2); + + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_SLOT, 0), 0); + ck_assert_int_eq(libevdev_get_current_slot(dev), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_POSITION_X), 3); + + uinput_device_free(uidev); + libevdev_free(dev); +} +END_TEST + Suite * libevdev_events(void) { @@ -1071,6 +1124,7 @@ libevdev_events(void) tcase_add_test(tc, test_event_value_setters_invalid); tcase_add_test(tc, test_event_mt_value_setters); tcase_add_test(tc, test_event_mt_value_setters_invalid); + tcase_add_test(tc, test_event_mt_value_setters_current_slot); suite_add_tcase(s, tc); return s; From f9fef9fd04df0a14b5f936acacd83ead2f07ea9d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 14 Aug 2013 10:17:59 +1000 Subject: [PATCH 8/8] Rename enums to match lower_case format This is technically an API, but not an ABI change. Signed-off-by: Peter Hutterer Reviewed-by: David Herrmann --- libevdev/libevdev.c | 8 ++++---- libevdev/libevdev.h | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index e59d795..8151026 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -1091,7 +1091,7 @@ libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const stru } int -libevdev_grab(struct libevdev *dev, int grab) +libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab) { int rc = 0; @@ -1188,7 +1188,7 @@ libevdev_get_repeat(struct libevdev *dev, int *delay, int *period) } int -libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum EvdevLEDValues value) +libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum libevdev_led_value value) { return libevdev_kernel_set_led_values(dev, code, value, -1); } @@ -1197,7 +1197,7 @@ int libevdev_kernel_set_led_values(struct libevdev *dev, ...) { struct input_event ev[LED_MAX + 1]; - enum EvdevLEDValues val; + enum libevdev_led_value val; va_list args; int code; int rc = 0; @@ -1212,7 +1212,7 @@ libevdev_kernel_set_led_values(struct libevdev *dev, ...) rc = -EINVAL; break; } - val = va_arg(args, enum EvdevLEDValues); + val = va_arg(args, enum libevdev_led_value); if (val != LIBEVDEV_LED_ON && val != LIBEVDEV_LED_OFF) { rc = -EINVAL; break; diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index 61553cc..6113f41 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -284,7 +284,7 @@ */ struct libevdev; -enum EvdevReadFlags { +enum libevdev_read_flag { LIBEVDEV_READ_SYNC = 1, /**< Process data in sync mode */ LIBEVDEV_READ_NORMAL = 2, /**< Process data in normal mode */ LIBEVDEV_FORCE_SYNC = 4, /**< Pretend the next event is a SYN_DROPPED. There is @@ -369,7 +369,7 @@ typedef void (*libevdev_log_func_t)(const char *format, va_list args); void libevdev_set_log_handler(struct libevdev *dev, libevdev_log_func_t logfunc); -enum EvdevGrabModes { +enum libevdev_grab_mode { LIBEVDEV_GRAB = 3, LIBEVDEV_UNGRAB = 4, }; @@ -390,7 +390,7 @@ enum EvdevGrabModes { * @return 0 if the device was successfull grabbed or ungrabbed, or a * negative errno in case of failure. */ -int libevdev_grab(struct libevdev *dev, int grab); +int libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab); /** * @ingroup init @@ -1155,7 +1155,7 @@ int libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigne int libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs); -enum EvdevLEDValues { +enum libevdev_led_value { LIBEVDEV_LED_ON = 3, LIBEVDEV_LED_OFF = 4, }; @@ -1173,7 +1173,7 @@ enum EvdevLEDValues { * @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); +int libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum libevdev_led_value value); /** * @ingroup kernel @@ -1194,7 +1194,7 @@ int libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum * @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 + * @param ... A pair of LED_* event codes and libevdev_led_value_t, followed by * -1 to terminate the list. * @return zero on success, or a negative errno on failure */