Abstract the event queue away
authorPeter Hutterer <peter.hutterer@who-t.net>
Thu, 30 May 2013 01:05:24 +0000 (11:05 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 30 May 2013 03:37:43 +0000 (13:37 +1000)
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>
libevdev/libevdev-int.h
libevdev/libevdev.c

index d287697..848c1a5 100644 (file)
@@ -61,5 +61,104 @@ struct libevdev {
        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
 
index 11b3492..561d0c5 100644 (file)
@@ -125,14 +125,7 @@ init_event_queue(struct libevdev *dev)
 
        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
@@ -293,12 +286,13 @@ sync_key_state(struct libevdev *dev)
                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);
        }
 
@@ -327,7 +321,7 @@ sync_abs_state(struct libevdev *dev)
                        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;
@@ -365,7 +359,7 @@ sync_mt_state(struct libevdev *dev)
                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;
@@ -373,7 +367,7 @@ sync_mt_state(struct libevdev *dev)
                        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];
                }
@@ -401,10 +395,10 @@ sync_state(struct libevdev *dev)
        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;
@@ -466,18 +460,22 @@ read_more_events(struct libevdev *dev)
 {
        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;
 }
@@ -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 rc = 0;
-       int i;
 
        if (dev->fd < 0)
                return -ENODEV;
@@ -509,11 +506,9 @@ int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_e
        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;
@@ -522,11 +517,6 @@ int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_e
                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;