Merge branch 'led-handling'

This commit is contained in:
Peter Hutterer 2013-08-26 09:53:10 +10:00
commit bd35bd53f0
5 changed files with 740 additions and 8 deletions

View file

@ -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 */

View file

@ -232,6 +232,14 @@ 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;
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++)
@ -317,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)
{
@ -437,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))
@ -471,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;
@ -491,13 +534,27 @@ 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;
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)
{
@ -513,6 +570,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;
@ -761,6 +821,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;
@ -769,6 +830,30 @@ 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;
case EV_LED: rc = update_led_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)
{
@ -795,6 +880,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)
{
@ -957,8 +1066,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;
@ -975,7 +1091,7 @@ libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const str
}
int
libevdev_grab(struct libevdev *dev, int grab)
libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab)
{
int rc = 0;
@ -1070,3 +1186,66 @@ 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 libevdev_led_value 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 + 1];
enum libevdev_led_value 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 libevdev_led_value);
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) {
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]);
}
rc = (rc != -1) ? 0 : -errno;
}
return rc;
}

View file

@ -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
@ -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.
@ -813,6 +817,34 @@ 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.
*
* 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.
* @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 +894,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
*
@ -1092,7 +1152,53 @@ 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);
enum libevdev_led_value {
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 libevdev_led_value 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 libevdev_led_value_t, 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
@ -1227,5 +1333,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 */

View file

@ -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;
@ -806,6 +852,240 @@ 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,
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_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);
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);
}
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
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)
{
@ -823,6 +1103,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");
@ -838,6 +1119,14 @@ 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);
tcase_add_test(tc, test_event_mt_value_setters_current_slot);
suite_add_tcase(s, tc);
return s;
}

View file

@ -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);
@ -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;
}