From: Bartosz Golaszewski Date: Wed, 11 Jan 2017 11:57:39 +0000 (+0100) Subject: core: implement simple event monitoring X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=571b1b06a5a716e028054a53c3f5ea49719557e4;p=qemu-gpiodev%2Flibgpiod.git core: implement simple event monitoring Add a function and corresponding data structures for simple event monitoring. Signed-off-by: Bartosz Golaszewski --- diff --git a/core.c b/core.c index 7602531..e50a2e6 100644 --- 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 d8e9789..fca5e0b 100644 --- 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; + /** * @} *