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
const int QUEUE_SIZE = 256;
- dev->queue = calloc(QUEUE_SIZE, sizeof(struct input_event));
- if (!dev->queue)
- return -ENOSPC;
-
- dev->queue_size = QUEUE_SIZE;
- dev->queue_next = 0;
-
- return 0;
+ return queue_alloc(dev, QUEUE_SIZE);
}
static void
goto out;
for (i = 0; i < KEY_MAX; i++) {
- struct input_event *ev = &dev->queue[dev->queue_next++];
int old, new;
old = bit_is_set(dev->key_values, 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);
+ }
set_bit_state(dev->key_values, i, new);
}
goto out;
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);
dev->abs_info[i].value = abs_info.value;
int j;
struct input_event *ev;
- ev = &dev->queue[dev->queue_next++];
+ ev = queue_push(dev);
init_event(ev, EV_ABS, ABS_MT_SLOT, i);
for (j = ABS_MT_MIN; j < ABS_MT_MAX; j++) {
int jdx = j - ABS_MT_MIN;
if (dev->mt_slot_vals[i][jdx] == mt_state[jdx].val[i])
continue;
- ev = &dev->queue[dev->queue_next++];
+ ev = queue_push(dev);
init_event(ev, EV_ABS, j, mt_state[jdx].val[i]);
dev->mt_slot_vals[i][jdx] = mt_state[jdx].val[i];
}
if (rc == 0 && libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
rc = sync_mt_state(dev);
- ev = &dev->queue[dev->queue_next++];
+ ev = queue_push(dev);
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;
return rc;
{
int free_elem;
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)
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) {
return -errno;
} else if (len > 0 && len % sizeof(struct input_event) != 0)
return -EINVAL;
- else if (len > 0)
- dev->queue_next += len/sizeof(struct input_event);
+ else if (len > 0) {
+ int nev = len/sizeof(struct input_event);
+ queue_set_num_elements(dev, queue_num_elements(dev) + nev);
+ }
return 0;
}
int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event *ev)
{
int rc = 0;
- int i;
if (dev->fd < 0)
return -ENODEV;
if (rc < 0 && rc != -EAGAIN)
goto out;
- if (dev->queue_next == 0)
+ if (queue_shift(dev, ev) != 0)
return -EAGAIN;
- *ev = dev->queue[0];
-
update_state(dev, ev);
rc = 0;
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) {
dev->queue_nsync--;
rc = 1;