core: implement simple event monitoring
authorBartosz Golaszewski <bartekgola@gmail.com>
Wed, 11 Jan 2017 11:57:39 +0000 (12:57 +0100)
committerBartosz Golaszewski <bartekgola@gmail.com>
Wed, 11 Jan 2017 11:57:39 +0000 (12:57 +0100)
Add a function and corresponding data structures for simple event
monitoring.

Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com>
core.c
gpiod.h

diff --git a/core.c b/core.c
index 760253110a9a24eb8bad0576806af7235cc63cf2..e50a2e6518d95c0e57cc2a161357b86437086dd2 100644 (file)
--- a/core.c
+++ b/core.c
@@ -242,6 +242,66 @@ int gpiod_simple_set_value(const char *device, unsigned int offset, int value,
        return 0;
 }
 
+int gpiod_simple_event_loop(const char *device, unsigned int offset,
+                           bool active_low, struct timespec *timeout,
+                           gpiod_event_cb callback, void *cbdata)
+{
+       struct gpiod_line_evreq_config config;
+       struct gpiod_line_event event;
+       struct gpiod_chip *chip;
+       struct gpiod_line *line;
+       int status, evtype;
+
+       memset(&config, 0, sizeof(config));
+       config.consumer = libgpiod_consumer;
+       config.event_type = GPIOD_EVENT_BOTH_EDGES;
+       config.active_state = active_low ? GPIOD_ACTIVE_STATE_LOW
+                                        : GPIOD_ACTIVE_STATE_HIGH;
+
+       chip = gpiod_chip_open_lookup(device);
+       if (!chip)
+               return -1;
+
+       line = gpiod_chip_get_line(chip, offset);
+       if (!line) {
+               gpiod_chip_close(chip);
+               return -1;
+       }
+
+       status = gpiod_line_event_request(line, &config);
+       if (status < 0) {
+               gpiod_chip_close(chip);
+               return -1;
+       }
+
+       for (;;) {
+               status = gpiod_line_event_wait(line, timeout);
+               if (status < 0) {
+                       goto out;
+               } else if (status == 0) {
+                       evtype = GPIOD_EVENT_CB_TIMEOUT;
+               } else {
+                       status = gpiod_line_event_read(line, &event);
+                       if (status < 0)
+                               goto out;
+
+                       evtype = event.event_type == GPIOD_EVENT_RISING_EDGE
+                                               ? GPIOD_EVENT_CB_RISING_EDGE
+                                               : GPIOD_EVENT_CB_FALLING_EDGE;
+               }
+
+               status = callback(evtype, &event.ts, cbdata);
+               if (status == GPIOD_EVENT_CB_STOP)
+                       goto out;
+       }
+
+out:
+       gpiod_line_event_release(line);
+       gpiod_chip_close(chip);
+
+       return status;
+}
+
 static void line_set_offset(struct gpiod_line *line, unsigned int offset)
 {
        line->info.line_offset = offset;
diff --git a/gpiod.h b/gpiod.h
index d8e9789f963c5832cc1832e35925286adffd6a58..fca5e0b98c3687dd21a9f87d50860b83ae90bd06 100644 (file)
--- a/gpiod.h
+++ b/gpiod.h
@@ -145,6 +145,48 @@ int gpiod_simple_set_value(const char *device, unsigned int offset,
                           int value, bool active_low, void (*cb)(void *),
                           void *data) GPIOD_API;
 
+/**
+ * @brief Event types that can be passed to the simple event callback.
+ */
+enum {
+       GPIOD_EVENT_CB_TIMEOUT,
+       /**< Waiting for events timed out. */
+       GPIOD_EVENT_CB_RISING_EDGE,
+       /**< Rising edge event occured. */
+       GPIOD_EVENT_CB_FALLING_EDGE,
+       /**< Falling edge event occured. */
+};
+
+/**
+ * @brief Return status values that the simple event callback can return.
+ */
+enum {
+       GPIOD_EVENT_CB_OK = 0,
+       /**< Continue processing events. */
+       GPIOD_EVENT_CB_STOP,
+       /**< Stop processing events. */
+};
+
+/**
+ * @brief Simple event callack signature.
+ */
+typedef int (*gpiod_event_cb)(int, const struct timespec *, void *);
+
+/**
+ * @brief Wait for events on a single GPIO line.
+ * @param device Name, path or number of the gpiochip.
+ * @param offset GPIO line offset on the chip.
+ * @param active_low The active state of this line - true if low.
+ * @param timeout Maximum wait time for each iteration.
+ * @param callback Callback function to call on event occurence.
+ * @param cbdata User data passed to the callback.
+ * @return 0 no errors were encountered, -1 if an error occured.
+ *
+ */
+int gpiod_simple_event_loop(const char *device, unsigned int offset,
+                           bool active_low, struct timespec *timeout,
+                           gpiod_event_cb callback, void *cbdata) GPIOD_API;
+
 /**
  * @}
  *