mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-24 15:50:08 +01:00
Merge branch 'led-handling'
This commit is contained in:
commit
bd35bd53f0
5 changed files with 740 additions and 8 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue