event: modify the API
authorBartosz Golaszewski <bartekgola@gmail.com>
Fri, 6 Jan 2017 10:26:18 +0000 (11:26 +0100)
committerBartosz Golaszewski <bartekgola@gmail.com>
Fri, 6 Jan 2017 10:26:18 +0000 (11:26 +0100)
In order to make it possible for users to poll the event file
descriptor, we need to split the logic of waiting for events to occur
and reading them into separate routines.

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

diff --git a/core.c b/core.c
index a66c052348ac18c0a0f8c5e76e81fc35f12901c5..b8d28fa2ec9443e687ad7587e35ba133bf972915 100644 (file)
--- a/core.c
+++ b/core.c
@@ -502,30 +502,26 @@ bool gpiod_line_event_configured(struct gpiod_line *line)
 }
 
 int gpiod_line_event_wait(struct gpiod_line *line,
-                         const struct timespec *timeout,
-                         struct gpiod_line_event *event)
+                         const struct timespec *timeout)
 {
        struct gpiod_line_bulk bulk;
 
        gpiod_line_bulk_init(&bulk);
        gpiod_line_bulk_add(&bulk, line);
 
-       return gpiod_line_event_wait_bulk(&bulk, timeout, event);
+       return gpiod_line_event_wait_bulk(&bulk, timeout, NULL);
 }
 
 int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
                               const struct timespec *timeout,
-                              struct gpiod_line_event *event)
+                              unsigned int *index)
 {
        struct pollfd fds[GPIOD_REQUEST_MAX_LINES];
-       struct gpioevent_data evdata;
        struct gpiod_line *line;
        unsigned int i;
        int status;
-       ssize_t rd;
 
        memset(fds, 0, sizeof(fds));
-       memset(&evdata, 0, sizeof(evdata));
 
        /* TODO Check if all lines are requested. */
 
@@ -545,8 +541,21 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
        }
 
        for (i = 0; !fds[i].revents; i++);
+       if (index)
+               *index = i;
+
+       return 1;
+}
+
+int gpiod_line_event_read(struct gpiod_line *line,
+                         struct gpiod_line_event *event)
+{
+       struct gpioevent_data evdata;
+       ssize_t rd;
 
-       rd = read(fds[i].fd, &evdata, sizeof(evdata));
+       memset(&evdata, 0, sizeof(evdata));
+
+       rd = read(line->event.fd, &evdata, sizeof(evdata));
        if (rd < 0) {
                last_error_from_errno();
                return -1;
@@ -555,13 +564,13 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
                return -1;
        }
 
-       event->line = bulk->lines[i];
+       event->line = line;
        event->event_type = evdata.id == GPIOEVENT_EVENT_RISING_EDGE
                                                ? GPIOD_EVENT_RISING_EDGE
                                                : GPIOD_EVENT_FALLING_EDGE;
        nsec_to_timespec(evdata.timestamp, &event->ts);
 
-       return 1;
+       return 0;
 }
 
 int gpiod_line_event_get_fd(struct gpiod_line *line)
diff --git a/gpiod.h b/gpiod.h
index ec191c70a82b878b33aa2d82e4a2657c12d20df6..94616b76e58c5d2da40fe907d65293d6df35f1b2 100644 (file)
--- a/gpiod.h
+++ b/gpiod.h
@@ -484,29 +484,42 @@ bool gpiod_line_event_configured(struct gpiod_line *line) GPIOD_API;
  * @brief Wait for an event on a single line.
  * @param line GPIO line object.
  * @param timeout Wait time limit.
- * @param event Buffer to which the event data will be copied.
  * @return 0 if wait timed out, -1 if an error occurred, 1 if an event
  *         occurred.
  */
 int gpiod_line_event_wait(struct gpiod_line *line,
-                         const struct timespec *timeout,
-                         struct gpiod_line_event *event) GPIOD_API;
+                         const struct timespec *timeout) GPIOD_API;
 
 /**
  * @brief Wait for the first event on a set of lines.
  * @param bulk Set of GPIO lines to monitor.
  * @param timeout Wait time limit.
- * @param event Buffer to which the event data will be copied.
+ * @param index The position of the line on which an event occured is stored
+ *              in this variable. Can be NULL, in which case the index will
+ *              not be stored.
  * @return 0 if wait timed out, -1 if an error occurred, 1 if an event
  *         occurred.
  */
 int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
                               const struct timespec *timeout,
-                              struct gpiod_line_event *event) GPIOD_API;
+                              unsigned int *index) GPIOD_API;
 
-/*
- * FIXME for this to make sense we need a routine to read events from a file
- * descriptor too.
+/**
+ * @brief Read the last event from the GPIO line.
+ * @param line GPIO line object.
+ * @param event Buffer to which the event data will be copied.
+ * @return 0 if the event was read correctly, -1 on error.
+ */
+int gpiod_line_event_read(struct gpiod_line *line,
+                         struct gpiod_line_event *event) GPIOD_API;
+
+/**
+ * @brief Get the event file descriptor.
+ * @param line GPIO line object.
+ * @return Number of the event file descriptor or -1 on error.
+ *
+ * Users may want to poll the event file descriptor on their own. This routine
+ * allows to access it.
  */
 int gpiod_line_event_get_fd(struct gpiod_line *line) GPIOD_API;
 
index 1550e25c4a854d7a0426f4c6ebf5488ec5c6838f..35222ed99c2a13bd31f86ca673d3272bc3f3d0f2 100644 (file)
--- a/gpiomon.c
+++ b/gpiomon.c
@@ -76,7 +76,7 @@ int main(int argc, char **argv)
                timeout.tv_sec = 1;
                timeout.tv_nsec = 0;
 
-               status = gpiod_line_event_wait(line, &timeout, &event);
+               status = gpiod_line_event_wait(line, &timeout);
                if (status < 0) {
                        fprintf(stderr,
                                "%s: error waiting for line event: %s\n",
@@ -86,6 +86,14 @@ int main(int argc, char **argv)
                        continue;
                }
 
+               status = gpiod_line_event_read(line, &event);
+               if (status < 0) {
+                       fprintf(stderr,
+                               "%s: error reading the line event: %s\n",
+                               argv[0], gpiod_strerror(gpiod_errno()));
+                       return EXIT_FAILURE;
+               }
+
                printf("GPIO EVENT: %s [%ld.%ld]\n",
                       event.event_type == GPIOD_EVENT_FALLING_EDGE
                                                        ? "FALLING EDGE"