mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2026-05-08 22:58:12 +02:00
Abstract the event queue away
Provide a couple of handler functions to avoid erroneous queue updates. This will make it easier if we need to swap queue implementation later. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
f3d94ecfd7
commit
549f0f0bcd
2 changed files with 117 additions and 28 deletions
|
|
@ -61,5 +61,104 @@ struct libevdev {
|
||||||
size_t queue_nsync; /**< number of sync events */
|
size_t queue_nsync; /**< number of sync events */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a pointer to the next element in the queue, or NULL if the queue
|
||||||
|
* is full.
|
||||||
|
*/
|
||||||
|
static inline struct input_event*
|
||||||
|
queue_push(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
if (dev->queue_next >= dev->queue_size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &dev->queue[dev->queue_next++];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set ev to the last element in the queue, removing it from the queue.
|
||||||
|
*
|
||||||
|
* @return 0 on success, 1 if the queue is empty.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
queue_pop(struct libevdev *dev, struct input_event *ev)
|
||||||
|
{
|
||||||
|
if (dev->queue_next == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*ev = dev->queue[--dev->queue_next];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set ev to the first element in the queue, shifting everything else
|
||||||
|
* forward by one.
|
||||||
|
*
|
||||||
|
* @return 0 on success, 1 if the queue is empty.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
queue_shift(struct libevdev *dev, struct input_event *ev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (dev->queue_next == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*ev = dev->queue[0];
|
||||||
|
|
||||||
|
for (i = 0; i < dev->queue_next - 1; i++)
|
||||||
|
dev->queue[i] = dev->queue[i + 1];
|
||||||
|
|
||||||
|
dev->queue_next--;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
queue_alloc(struct libevdev *dev, int size)
|
||||||
|
{
|
||||||
|
dev->queue = calloc(size, sizeof(struct input_event));
|
||||||
|
if (!dev->queue)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
|
dev->queue_size = size;
|
||||||
|
dev->queue_next = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
queue_num_elements(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
return dev->queue_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
queue_size(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
return dev->queue_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
queue_num_free_elements(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
return dev->queue_size - dev->queue_next - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct input_event *
|
||||||
|
queue_next_element(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
return &dev->queue[dev->queue_next];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
queue_set_num_elements(struct libevdev *dev, int nelem)
|
||||||
|
{
|
||||||
|
if (nelem > dev->queue_size)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
dev->queue_next = nelem;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,14 +125,7 @@ init_event_queue(struct libevdev *dev)
|
||||||
|
|
||||||
const int QUEUE_SIZE = 256;
|
const int QUEUE_SIZE = 256;
|
||||||
|
|
||||||
dev->queue = calloc(QUEUE_SIZE, sizeof(struct input_event));
|
return queue_alloc(dev, QUEUE_SIZE);
|
||||||
if (!dev->queue)
|
|
||||||
return -ENOSPC;
|
|
||||||
|
|
||||||
dev->queue_size = QUEUE_SIZE;
|
|
||||||
dev->queue_next = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -293,12 +286,13 @@ sync_key_state(struct libevdev *dev)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (i = 0; i < KEY_MAX; i++) {
|
for (i = 0; i < KEY_MAX; i++) {
|
||||||
struct input_event *ev = &dev->queue[dev->queue_next++];
|
|
||||||
int old, new;
|
int old, new;
|
||||||
old = bit_is_set(dev->key_values, i);
|
old = bit_is_set(dev->key_values, i);
|
||||||
new = bit_is_set(keystate, i);
|
new = bit_is_set(keystate, i);
|
||||||
if (old ^ new)
|
if (old ^ new) {
|
||||||
|
struct input_event *ev = queue_push(dev);
|
||||||
init_event(ev, EV_KEY, i, new ? 1 : 0);
|
init_event(ev, EV_KEY, i, new ? 1 : 0);
|
||||||
|
}
|
||||||
set_bit_state(dev->key_values, i, new);
|
set_bit_state(dev->key_values, i, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -327,7 +321,7 @@ sync_abs_state(struct libevdev *dev)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (dev->abs_info[i].value != abs_info.value) {
|
if (dev->abs_info[i].value != abs_info.value) {
|
||||||
struct input_event *ev = &dev->queue[dev->queue_next++];
|
struct input_event *ev = queue_push(dev);
|
||||||
|
|
||||||
init_event(ev, EV_ABS, i, abs_info.value);
|
init_event(ev, EV_ABS, i, abs_info.value);
|
||||||
dev->abs_info[i].value = abs_info.value;
|
dev->abs_info[i].value = abs_info.value;
|
||||||
|
|
@ -365,7 +359,7 @@ sync_mt_state(struct libevdev *dev)
|
||||||
int j;
|
int j;
|
||||||
struct input_event *ev;
|
struct input_event *ev;
|
||||||
|
|
||||||
ev = &dev->queue[dev->queue_next++];
|
ev = queue_push(dev);
|
||||||
init_event(ev, EV_ABS, ABS_MT_SLOT, i);
|
init_event(ev, EV_ABS, ABS_MT_SLOT, i);
|
||||||
for (j = ABS_MT_MIN; j < ABS_MT_MAX; j++) {
|
for (j = ABS_MT_MIN; j < ABS_MT_MAX; j++) {
|
||||||
int jdx = j - ABS_MT_MIN;
|
int jdx = j - ABS_MT_MIN;
|
||||||
|
|
@ -373,7 +367,7 @@ sync_mt_state(struct libevdev *dev)
|
||||||
if (dev->mt_slot_vals[i][jdx] == mt_state[jdx].val[i])
|
if (dev->mt_slot_vals[i][jdx] == mt_state[jdx].val[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ev = &dev->queue[dev->queue_next++];
|
ev = queue_push(dev);
|
||||||
init_event(ev, EV_ABS, j, mt_state[jdx].val[i]);
|
init_event(ev, EV_ABS, j, mt_state[jdx].val[i]);
|
||||||
dev->mt_slot_vals[i][jdx] = mt_state[jdx].val[i];
|
dev->mt_slot_vals[i][jdx] = mt_state[jdx].val[i];
|
||||||
}
|
}
|
||||||
|
|
@ -401,10 +395,10 @@ sync_state(struct libevdev *dev)
|
||||||
if (rc == 0 && libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
|
if (rc == 0 && libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
|
||||||
rc = sync_mt_state(dev);
|
rc = sync_mt_state(dev);
|
||||||
|
|
||||||
ev = &dev->queue[dev->queue_next++];
|
ev = queue_push(dev);
|
||||||
init_event(ev, EV_SYN, SYN_REPORT, 0);
|
init_event(ev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
||||||
dev->queue_nsync = dev->queue_next;
|
dev->queue_nsync = queue_num_elements(dev);
|
||||||
dev->need_sync = 0;
|
dev->need_sync = 0;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
@ -466,18 +460,22 @@ read_more_events(struct libevdev *dev)
|
||||||
{
|
{
|
||||||
int free_elem;
|
int free_elem;
|
||||||
int len;
|
int len;
|
||||||
|
struct input_event *next;
|
||||||
|
|
||||||
free_elem = dev->queue_size - dev->queue_next - 1;
|
free_elem = queue_num_free_elements(dev);
|
||||||
if (free_elem <= 0)
|
if (free_elem <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
len = read(dev->fd, &dev->queue[dev->queue_next], free_elem * sizeof(struct input_event));
|
next = queue_next_element(dev);
|
||||||
|
len = read(dev->fd, next, free_elem * sizeof(struct input_event));
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
return -errno;
|
return -errno;
|
||||||
} else if (len > 0 && len % sizeof(struct input_event) != 0)
|
} else if (len > 0 && len % sizeof(struct input_event) != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
else if (len > 0)
|
else if (len > 0) {
|
||||||
dev->queue_next += len/sizeof(struct input_event);
|
int nev = len/sizeof(struct input_event);
|
||||||
|
queue_set_num_elements(dev, queue_num_elements(dev) + nev);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -485,7 +483,6 @@ read_more_events(struct libevdev *dev)
|
||||||
int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event *ev)
|
int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event *ev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (dev->fd < 0)
|
if (dev->fd < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
@ -509,11 +506,9 @@ int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_e
|
||||||
if (rc < 0 && rc != -EAGAIN)
|
if (rc < 0 && rc != -EAGAIN)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (dev->queue_next == 0)
|
if (queue_shift(dev, ev) != 0)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
*ev = dev->queue[0];
|
|
||||||
|
|
||||||
update_state(dev, ev);
|
update_state(dev, ev);
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
@ -522,11 +517,6 @@ int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_e
|
||||||
rc = 1;
|
rc = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; dev->queue_next > 1 && i < dev->queue_next - 1; i++)
|
|
||||||
dev->queue[i] = dev->queue[i + 1];
|
|
||||||
|
|
||||||
dev->queue_next--;
|
|
||||||
|
|
||||||
if (flags & ER_SYNC && dev->queue_nsync > 0) {
|
if (flags & ER_SYNC && dev->queue_nsync > 0) {
|
||||||
dev->queue_nsync--;
|
dev->queue_nsync--;
|
||||||
rc = 1;
|
rc = 1;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue