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++)
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)
{
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))
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)
{
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;
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;
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;
}
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;
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));
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);
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");