From b6649710da4f80b1e4a76f391dfc0174afeb1b7e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 6 Jan 2017 11:26:18 +0100 Subject: [PATCH] event: modify the API 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 --- core.c | 29 +++++++++++++++++++---------- gpiod.h | 29 +++++++++++++++++++++-------- gpiomon.c | 10 +++++++++- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/core.c b/core.c index a66c052..b8d28fa 100644 --- 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 ec191c7..94616b7 100644 --- 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; diff --git a/gpiomon.c b/gpiomon.c index 1550e25..35222ed 100644 --- 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" -- 2.30.2