* @param consumer Name of the consumer.
* @return 0 or 1 (GPIO value) if the operation succeeds, -1 on error.
*/
-int gpiod_simple_get_value(const char *device, unsigned int offset,
- bool active_low, const char *consumer) GPIOD_API;
+int gpiod_ctxless_get_value(const char *device, unsigned int offset,
+ bool active_low, const char *consumer) GPIOD_API;
/**
* @brief Read current values from a set of GPIO lines.
* @param consumer Name of the consumer.
* @return 0 if the operation succeeds, -1 on error.
*/
-int gpiod_simple_get_value_multiple(const char *device,
- const unsigned int *offsets, int *values,
- unsigned int num_lines, bool active_low,
- const char *consumer) GPIOD_API;
+int gpiod_ctxless_get_value_multiple(const char *device,
+ const unsigned int *offsets, int *values,
+ unsigned int num_lines, bool active_low,
+ const char *consumer) GPIOD_API;
/**
* @brief Simple set value callback signature.
*/
-typedef void (*gpiod_simple_set_value_cb)(void *);
+typedef void (*gpiod_ctxless_set_value_cb)(void *);
/**
* @brief Set value of a single GPIO line.
* @param data User data that will be passed to the callback function.
* @return 0 if the operation succeeds, -1 on error.
*/
-int gpiod_simple_set_value(const char *device, unsigned int offset, int value,
- bool active_low, const char *consumer,
- gpiod_simple_set_value_cb cb, void *data) GPIOD_API;
+int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value,
+ bool active_low, const char *consumer,
+ gpiod_ctxless_set_value_cb cb,
+ void *data) GPIOD_API;
/**
* @brief Set values of multiple GPIO lines.
* @param active_low The active state of the lines - true if low.
* @param consumer Name of the consumer.
* @param cb Callback function that will be called right after the values are
- * set. Works the same as in ::gpiod_simple_set_value.
+ * set. Works the same as in ::gpiod_ctxless_set_value.
* @param data User data that will be passed to the callback function.
* @return 0 if the operation succeeds, -1 on error.
*/
-int gpiod_simple_set_value_multiple(const char *device,
- const unsigned int *offsets,
- const int *values, unsigned int num_lines,
- bool active_low, const char *consumer,
- gpiod_simple_set_value_cb cb,
- void *data) GPIOD_API;
+int gpiod_ctxless_set_value_multiple(const char *device,
+ const unsigned int *offsets,
+ const int *values, unsigned int num_lines,
+ bool active_low, const char *consumer,
+ gpiod_ctxless_set_value_cb cb,
+ void *data) GPIOD_API;
/**
- * @brief Event types that can be passed to the simple event callback.
+ * @brief Event types that can be passed to the ctxless event callback.
*/
enum {
- GPIOD_SIMPLE_EVENT_CB_TIMEOUT,
+ GPIOD_CTXLESS_EVENT_CB_TIMEOUT,
/**< Waiting for events timed out. */
- GPIOD_SIMPLE_EVENT_CB_RISING_EDGE,
+ GPIOD_CTXLESS_EVENT_CB_RISING_EDGE,
/**< Rising edge event occured. */
- GPIOD_SIMPLE_EVENT_CB_FALLING_EDGE,
+ GPIOD_CTXLESS_EVENT_CB_FALLING_EDGE,
/**< Falling edge event occured. */
};
/**
- * @brief Return status values that the simple event callback can return.
+ * @brief Return status values that the ctxless event callback can return.
*/
enum {
- GPIOD_SIMPLE_EVENT_CB_RET_ERR = -1,
+ GPIOD_CTXLESS_EVENT_CB_RET_ERR = -1,
/**< Stop processing events and indicate an error. */
- GPIOD_SIMPLE_EVENT_CB_RET_OK = 0,
+ GPIOD_CTXLESS_EVENT_CB_RET_OK = 0,
/**< Continue processing events. */
- GPIOD_SIMPLE_EVENT_CB_RET_STOP = 1,
+ GPIOD_CTXLESS_EVENT_CB_RET_STOP = 1,
/**< Stop processing events. */
};
* GPIO line offset (unsigned int), event timestamp (const struct timespec *)
* and a pointer to user data (void *).
*
- * This callback is called by the simple event loop functions for each GPIO
- * event. If the callback returns ::GPIOD_SIMPLE_EVENT_CB_RET_ERR, it should
+ * This callback is called by the ctxless event loop functions for each GPIO
+ * event. If the callback returns ::GPIOD_CTXLESS_EVENT_CB_RET_ERR, it should
* also set errno.
*/
-typedef int (*gpiod_simple_event_handle_cb)(int, unsigned int,
- const struct timespec *, void *);
+typedef int (*gpiod_ctxless_event_handle_cb)(int, unsigned int,
+ const struct timespec *, void *);
/**
- * @brief Return status values that the simple event poll callback can return.
+ * @brief Return status values that the ctxless event poll callback can return.
*
* Positive value returned from the polling callback indicates the number of
* events that occurred on the set of monitored lines.
*/
enum {
- GPIOD_SIMPLE_EVENT_POLL_RET_STOP = -2,
+ GPIOD_CTXLESS_EVENT_POLL_RET_STOP = -2,
/**< The event loop should stop processing events. */
- GPIOD_SIMPLE_EVENT_POLL_RET_ERR = -1,
+ GPIOD_CTXLESS_EVENT_POLL_RET_ERR = -1,
/**< Polling error occurred (the polling function should set errno). */
- GPIOD_SIMPLE_EVENT_POLL_RET_TIMEOUT = 0,
+ GPIOD_CTXLESS_EVENT_POLL_RET_TIMEOUT = 0,
/**< Poll timed out. */
};
/**
- * @brief Helper structure for the simple event loop poll callback.
+ * @brief Helper structure for the ctxless event loop poll callback.
*/
-struct gpiod_simple_event_poll_fd {
+struct gpiod_ctxless_event_poll_fd {
int fd;
/**< File descriptor number. */
bool event;
*
* The poll callback function takes the following arguments: number of lines
* (unsigned int), an array of file descriptors on which input events should
- * be monitored (struct gpiod_simple_event_poll_fd *), poll timeout
+ * be monitored (struct gpiod_ctxless_event_poll_fd *), poll timeout
* (const struct timespec *) and a pointer to user data (void *).
*
* The callback should poll for input events on the set of descriptors and
* return an appropriate value that can be interpreted by the event loop
* routine.
*/
-typedef int (*gpiod_simple_event_poll_cb)(unsigned int,
- struct gpiod_simple_event_poll_fd *,
- const struct timespec *, void *);
+typedef int (*gpiod_ctxless_event_poll_cb)(unsigned int,
+ struct gpiod_ctxless_event_poll_fd *,
+ const struct timespec *, void *);
/**
* @brief Wait for events on a single GPIO line.
* @param event_cb Callback function to call for each line event.
* @param data User data passed to the callback.
* @return 0 if no errors were encountered, -1 if an error occurred.
- * @note The way the simple event loop works is described in detail in
- * ::gpiod_simple_event_loop_multiple - this is just a wrapper aound
+ * @note The way the ctxless event loop works is described in detail in
+ * ::gpiod_ctxless_event_loop_multiple - this is just a wrapper aound
* this routine which calls it for a single GPIO line.
*/
-int gpiod_simple_event_loop(const char *device, unsigned int offset,
- bool active_low, const char *consumer,
- const struct timespec *timeout,
- gpiod_simple_event_poll_cb poll_cb,
- gpiod_simple_event_handle_cb event_cb,
- void *data) GPIOD_API;
+int gpiod_ctxless_event_loop(const char *device, unsigned int offset,
+ bool active_low, const char *consumer,
+ const struct timespec *timeout,
+ gpiod_ctxless_event_poll_cb poll_cb,
+ gpiod_ctxless_event_handle_cb event_cb,
+ void *data) GPIOD_API;
/**
* @brief Wait for events on multiple GPIO lines.
* polling callback is to detect input events on a set of file descriptors and
* notify the caller about the fds ready for reading.
*
- * The simple event loop then reads each queued event from marked descriptors
+ * The ctxless event loop then reads each queued event from marked descriptors
* and calls the event callback. Both callbacks can stop the loop at any
* point.
*
* The poll_cb argument can be NULL in which case the function falls back to
* a default, ppoll() based callback.
*/
-int gpiod_simple_event_loop_multiple(const char *device,
- const unsigned int *offsets,
- unsigned int num_lines, bool active_low,
- const char *consumer,
- const struct timespec *timeout,
- gpiod_simple_event_poll_cb poll_cb,
- gpiod_simple_event_handle_cb event_cb,
- void *data) GPIOD_API;
+int gpiod_ctxless_event_loop_multiple(const char *device,
+ const unsigned int *offsets,
+ unsigned int num_lines, bool active_low,
+ const char *consumer,
+ const struct timespec *timeout,
+ gpiod_ctxless_event_poll_cb poll_cb,
+ gpiod_ctxless_event_handle_cb event_cb,
+ void *data) GPIOD_API;
/**
* @brief Determine the chip name and line offset of a line with given name.
* and offset remain unchanged.
* @note The chip name is truncated if the buffer can't hold its entire size.
*/
-int gpiod_simple_find_line(const char *name, char *chipname,
- size_t chipname_size,
- unsigned int *offset) GPIOD_API;
+int gpiod_ctxless_find_line(const char *name, char *chipname,
+ size_t chipname_size,
+ unsigned int *offset) GPIOD_API;
/**
* @}
#
lib_LTLIBRARIES = libgpiod.la
-libgpiod_la_SOURCES = core.c helpers.c iter.c misc.c simple.c
+libgpiod_la_SOURCES = core.c ctxless.c helpers.c iter.c misc.c
libgpiod_la_CFLAGS = -Wall -Wextra -g
libgpiod_la_CFLAGS += -fvisibility=hidden -I$(top_srcdir)/include/
libgpiod_la_CFLAGS += -include $(top_builddir)/config.h
--- /dev/null
+/*
+ * This file is part of libgpiod.
+ *
+ * Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+/* Implementation of the high-level API. */
+
+#include <gpiod.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <poll.h>
+
+int gpiod_ctxless_get_value(const char *device, unsigned int offset,
+ bool active_low, const char *consumer)
+{
+ int value, status;
+
+ status = gpiod_ctxless_get_value_multiple(device, &offset, &value,
+ 1, active_low, consumer);
+ if (status < 0)
+ return status;
+
+ return value;
+}
+
+int gpiod_ctxless_get_value_multiple(const char *device,
+ const unsigned int *offsets, int *values,
+ unsigned int num_lines, bool active_low,
+ const char *consumer)
+{
+ struct gpiod_line_bulk bulk;
+ struct gpiod_chip *chip;
+ struct gpiod_line *line;
+ int status, flags;
+ unsigned int i;
+
+ if (num_lines > GPIOD_LINE_BULK_MAX_LINES) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ chip = gpiod_chip_open_lookup(device);
+ if (!chip)
+ return -1;
+
+ gpiod_line_bulk_init(&bulk);
+
+ for (i = 0; i < num_lines; i++) {
+ line = gpiod_chip_get_line(chip, offsets[i]);
+ if (!line) {
+ gpiod_chip_close(chip);
+ return -1;
+ }
+
+ gpiod_line_bulk_add(&bulk, line);
+ }
+
+ flags = active_low ? GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW : 0;
+
+ status = gpiod_line_request_bulk_input_flags(&bulk, consumer, flags);
+ if (status < 0) {
+ gpiod_chip_close(chip);
+ return -1;
+ }
+
+ memset(values, 0, sizeof(*values) * num_lines);
+ status = gpiod_line_get_value_bulk(&bulk, values);
+
+ gpiod_chip_close(chip);
+
+ return status;
+}
+
+int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value,
+ bool active_low, const char *consumer,
+ gpiod_ctxless_set_value_cb cb, void *data)
+{
+ return gpiod_ctxless_set_value_multiple(device, &offset, &value, 1,
+ active_low, consumer, cb, data);
+}
+
+int gpiod_ctxless_set_value_multiple(const char *device,
+ const unsigned int *offsets,
+ const int *values, unsigned int num_lines,
+ bool active_low, const char *consumer,
+ gpiod_ctxless_set_value_cb cb, void *data)
+{
+ struct gpiod_line_bulk bulk;
+ struct gpiod_chip *chip;
+ struct gpiod_line *line;
+ int status, flags;
+ unsigned int i;
+
+ if (num_lines > GPIOD_LINE_BULK_MAX_LINES) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ chip = gpiod_chip_open_lookup(device);
+ if (!chip)
+ return -1;
+
+ gpiod_line_bulk_init(&bulk);
+
+ for (i = 0; i < num_lines; i++) {
+ line = gpiod_chip_get_line(chip, offsets[i]);
+ if (!line) {
+ gpiod_chip_close(chip);
+ return -1;
+ }
+
+ gpiod_line_bulk_add(&bulk, line);
+ }
+
+ flags = active_low ? GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW : 0;
+
+ status = gpiod_line_request_bulk_output_flags(&bulk, consumer,
+ flags, values);
+ if (status < 0) {
+ gpiod_chip_close(chip);
+ return -1;
+ }
+
+ if (cb)
+ cb(data);
+
+ gpiod_chip_close(chip);
+
+ return 0;
+}
+
+static int basic_event_poll(unsigned int num_lines,
+ struct gpiod_ctxless_event_poll_fd *fds,
+ const struct timespec *timeout,
+ void *data GPIOD_UNUSED)
+{
+ struct pollfd poll_fds[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int rv, ret;
+
+ if (num_lines > GPIOD_LINE_BULK_MAX_LINES)
+ return GPIOD_CTXLESS_EVENT_POLL_RET_ERR;
+
+ memset(poll_fds, 0, sizeof(poll_fds));
+
+ for (i = 0; i < num_lines; i++) {
+ poll_fds[i].fd = fds[i].fd;
+ poll_fds[i].events = POLLIN | POLLPRI;
+ }
+
+ rv = ppoll(poll_fds, num_lines, timeout, NULL);
+ if (rv < 0) {
+ if (errno == EINTR)
+ return GPIOD_CTXLESS_EVENT_POLL_RET_TIMEOUT;
+ else
+ return GPIOD_CTXLESS_EVENT_POLL_RET_ERR;
+ } else if (rv == 0) {
+ return GPIOD_CTXLESS_EVENT_POLL_RET_TIMEOUT;
+ }
+
+ ret = rv;
+ for (i = 0; i < num_lines; i++) {
+ if (poll_fds[i].revents) {
+ fds[i].event = true;
+ if (!--rv)
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int gpiod_ctxless_event_loop(const char *device, unsigned int offset,
+ bool active_low, const char *consumer,
+ const struct timespec *timeout,
+ gpiod_ctxless_event_poll_cb poll_cb,
+ gpiod_ctxless_event_handle_cb event_cb,
+ void *data)
+{
+ return gpiod_ctxless_event_loop_multiple(device, &offset, 1,
+ active_low, consumer, timeout,
+ poll_cb, event_cb, data);
+}
+
+int gpiod_ctxless_event_loop_multiple(const char *device,
+ const unsigned int *offsets,
+ unsigned int num_lines, bool active_low,
+ const char *consumer,
+ const struct timespec *timeout,
+ gpiod_ctxless_event_poll_cb poll_cb,
+ gpiod_ctxless_event_handle_cb event_cb,
+ void *data)
+{
+ struct gpiod_ctxless_event_poll_fd fds[GPIOD_LINE_BULK_MAX_LINES];
+ int rv, ret, flags, evtype, cnt;
+ struct gpiod_line_event event;
+ struct gpiod_line_bulk bulk;
+ struct gpiod_chip *chip;
+ struct gpiod_line *line;
+ unsigned int i;
+
+ if (num_lines > GPIOD_LINE_BULK_MAX_LINES) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!poll_cb)
+ poll_cb = basic_event_poll;
+
+ chip = gpiod_chip_open_lookup(device);
+ if (!chip)
+ return -1;
+
+ gpiod_line_bulk_init(&bulk);
+
+ for (i = 0; i < num_lines; i++) {
+ line = gpiod_chip_get_line(chip, offsets[i]);
+ if (!line) {
+ gpiod_chip_close(chip);
+ return -1;
+ }
+
+ gpiod_line_bulk_add(&bulk, line);
+ }
+
+ flags = active_low ? GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW : 0;
+
+ rv = gpiod_line_request_bulk_both_edges_events_flags(&bulk,
+ consumer, flags);
+ if (rv) {
+ ret = -1;
+ goto out;
+ }
+
+ memset(fds, 0, sizeof(fds));
+ for (i = 0; i < num_lines; i++) {
+ line = gpiod_line_bulk_get_line(&bulk, i);
+ fds[i].fd = gpiod_line_event_get_fd(line);
+ }
+
+ for (;;) {
+ for (i = 0; i < num_lines; i++)
+ fds[i].event = false;
+
+ cnt = poll_cb(num_lines, fds, timeout, data);
+ if (cnt == GPIOD_CTXLESS_EVENT_POLL_RET_ERR) {
+ ret = -1;
+ goto out;
+ } else if (cnt == GPIOD_CTXLESS_EVENT_POLL_RET_TIMEOUT) {
+ rv = event_cb(GPIOD_CTXLESS_EVENT_CB_TIMEOUT,
+ 0, &event.ts, data);
+ if (rv == GPIOD_CTXLESS_EVENT_CB_RET_ERR) {
+ ret = -1;
+ goto out;
+ } else if (rv == GPIOD_CTXLESS_EVENT_CB_RET_STOP) {
+ ret = 0;
+ goto out;
+ }
+ } else if (cnt == GPIOD_CTXLESS_EVENT_POLL_RET_STOP) {
+ ret = 0;
+ goto out;
+ }
+
+ for (i = 0; i < num_lines; i++) {
+ if (!fds[i].event)
+ continue;
+
+ line = gpiod_line_bulk_get_line(&bulk, i);
+ rv = gpiod_line_event_read(line, &event);
+ if (rv < 0) {
+ ret = rv;
+ goto out;
+ }
+
+ if (event.event_type == GPIOD_LINE_EVENT_RISING_EDGE)
+ evtype = GPIOD_CTXLESS_EVENT_CB_RISING_EDGE;
+ else
+ evtype = GPIOD_CTXLESS_EVENT_CB_FALLING_EDGE;
+
+ rv = event_cb(evtype, gpiod_line_offset(line),
+ &event.ts, data);
+ if (rv == GPIOD_CTXLESS_EVENT_CB_RET_ERR) {
+ ret = -1;
+ goto out;
+ } else if (rv == GPIOD_CTXLESS_EVENT_CB_RET_STOP) {
+ ret = 0;
+ goto out;
+ }
+
+ if (!--cnt)
+ break;
+ }
+ }
+
+out:
+ gpiod_chip_close(chip);
+
+ return ret;
+}
+
+int gpiod_ctxless_find_line(const char *name, char *chipname,
+ size_t chipname_size, unsigned int *offset)
+{
+ struct gpiod_chip *chip;
+ struct gpiod_line *line;
+
+ line = gpiod_line_find(name);
+ if (!line) {
+ if (errno == ENOENT)
+ return 0;
+ else
+ return -1;
+ }
+
+ chip = gpiod_line_get_chip(line);
+ snprintf(chipname, chipname_size, "%s", gpiod_chip_name(chip));
+ *offset = gpiod_line_offset(line);
+ gpiod_chip_close(chip);
+
+ return 1;
+}
+++ /dev/null
-/*
- * This file is part of libgpiod.
- *
- * Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-/* Implementation of the high-level API. */
-
-#include <gpiod.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <poll.h>
-
-int gpiod_simple_get_value(const char *device, unsigned int offset,
- bool active_low, const char *consumer)
-{
- int value, status;
-
- status = gpiod_simple_get_value_multiple(device, &offset, &value,
- 1, active_low, consumer);
- if (status < 0)
- return status;
-
- return value;
-}
-
-int gpiod_simple_get_value_multiple(const char *device,
- const unsigned int *offsets, int *values,
- unsigned int num_lines, bool active_low,
- const char *consumer)
-{
- struct gpiod_line_bulk bulk;
- struct gpiod_chip *chip;
- struct gpiod_line *line;
- int status, flags;
- unsigned int i;
-
- if (num_lines > GPIOD_LINE_BULK_MAX_LINES) {
- errno = EINVAL;
- return -1;
- }
-
- chip = gpiod_chip_open_lookup(device);
- if (!chip)
- return -1;
-
- gpiod_line_bulk_init(&bulk);
-
- for (i = 0; i < num_lines; i++) {
- line = gpiod_chip_get_line(chip, offsets[i]);
- if (!line) {
- gpiod_chip_close(chip);
- return -1;
- }
-
- gpiod_line_bulk_add(&bulk, line);
- }
-
- flags = active_low ? GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW : 0;
-
- status = gpiod_line_request_bulk_input_flags(&bulk, consumer, flags);
- if (status < 0) {
- gpiod_chip_close(chip);
- return -1;
- }
-
- memset(values, 0, sizeof(*values) * num_lines);
- status = gpiod_line_get_value_bulk(&bulk, values);
-
- gpiod_chip_close(chip);
-
- return status;
-}
-
-int gpiod_simple_set_value(const char *device, unsigned int offset, int value,
- bool active_low, const char *consumer,
- gpiod_simple_set_value_cb cb, void *data)
-{
- return gpiod_simple_set_value_multiple(device, &offset, &value, 1,
- active_low, consumer, cb, data);
-}
-
-int gpiod_simple_set_value_multiple(const char *device,
- const unsigned int *offsets,
- const int *values, unsigned int num_lines,
- bool active_low, const char *consumer,
- gpiod_simple_set_value_cb cb, void *data)
-{
- struct gpiod_line_bulk bulk;
- struct gpiod_chip *chip;
- struct gpiod_line *line;
- int status, flags;
- unsigned int i;
-
- if (num_lines > GPIOD_LINE_BULK_MAX_LINES) {
- errno = EINVAL;
- return -1;
- }
-
- chip = gpiod_chip_open_lookup(device);
- if (!chip)
- return -1;
-
- gpiod_line_bulk_init(&bulk);
-
- for (i = 0; i < num_lines; i++) {
- line = gpiod_chip_get_line(chip, offsets[i]);
- if (!line) {
- gpiod_chip_close(chip);
- return -1;
- }
-
- gpiod_line_bulk_add(&bulk, line);
- }
-
- flags = active_low ? GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW : 0;
-
- status = gpiod_line_request_bulk_output_flags(&bulk, consumer,
- flags, values);
- if (status < 0) {
- gpiod_chip_close(chip);
- return -1;
- }
-
- if (cb)
- cb(data);
-
- gpiod_chip_close(chip);
-
- return 0;
-}
-
-static int basic_event_poll(unsigned int num_lines,
- struct gpiod_simple_event_poll_fd *fds,
- const struct timespec *timeout,
- void *data GPIOD_UNUSED)
-{
- struct pollfd poll_fds[GPIOD_LINE_BULK_MAX_LINES];
- unsigned int i;
- int rv, ret;
-
- if (num_lines > GPIOD_LINE_BULK_MAX_LINES)
- return GPIOD_SIMPLE_EVENT_POLL_RET_ERR;
-
- memset(poll_fds, 0, sizeof(poll_fds));
-
- for (i = 0; i < num_lines; i++) {
- poll_fds[i].fd = fds[i].fd;
- poll_fds[i].events = POLLIN | POLLPRI;
- }
-
- rv = ppoll(poll_fds, num_lines, timeout, NULL);
- if (rv < 0) {
- if (errno == EINTR)
- return GPIOD_SIMPLE_EVENT_POLL_RET_TIMEOUT;
- else
- return GPIOD_SIMPLE_EVENT_POLL_RET_ERR;
- } else if (rv == 0) {
- return GPIOD_SIMPLE_EVENT_POLL_RET_TIMEOUT;
- }
-
- ret = rv;
- for (i = 0; i < num_lines; i++) {
- if (poll_fds[i].revents) {
- fds[i].event = true;
- if (!--rv)
- break;
- }
- }
-
- return ret;
-}
-
-int gpiod_simple_event_loop(const char *device, unsigned int offset,
- bool active_low, const char *consumer,
- const struct timespec *timeout,
- gpiod_simple_event_poll_cb poll_cb,
- gpiod_simple_event_handle_cb event_cb, void *data)
-{
- return gpiod_simple_event_loop_multiple(device, &offset, 1, active_low,
- consumer, timeout, poll_cb,
- event_cb, data);
-}
-
-int gpiod_simple_event_loop_multiple(const char *device,
- const unsigned int *offsets,
- unsigned int num_lines, bool active_low,
- const char *consumer,
- const struct timespec *timeout,
- gpiod_simple_event_poll_cb poll_cb,
- gpiod_simple_event_handle_cb event_cb,
- void *data)
-{
- struct gpiod_simple_event_poll_fd fds[GPIOD_LINE_BULK_MAX_LINES];
- int rv, ret, flags, evtype, cnt;
- struct gpiod_line_event event;
- struct gpiod_line_bulk bulk;
- struct gpiod_chip *chip;
- struct gpiod_line *line;
- unsigned int i;
-
- if (num_lines > GPIOD_LINE_BULK_MAX_LINES) {
- errno = EINVAL;
- return -1;
- }
-
- if (!poll_cb)
- poll_cb = basic_event_poll;
-
- chip = gpiod_chip_open_lookup(device);
- if (!chip)
- return -1;
-
- gpiod_line_bulk_init(&bulk);
-
- for (i = 0; i < num_lines; i++) {
- line = gpiod_chip_get_line(chip, offsets[i]);
- if (!line) {
- gpiod_chip_close(chip);
- return -1;
- }
-
- gpiod_line_bulk_add(&bulk, line);
- }
-
- flags = active_low ? GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW : 0;
-
- rv = gpiod_line_request_bulk_both_edges_events_flags(&bulk,
- consumer, flags);
- if (rv) {
- ret = -1;
- goto out;
- }
-
- memset(fds, 0, sizeof(fds));
- for (i = 0; i < num_lines; i++) {
- line = gpiod_line_bulk_get_line(&bulk, i);
- fds[i].fd = gpiod_line_event_get_fd(line);
- }
-
- for (;;) {
- for (i = 0; i < num_lines; i++)
- fds[i].event = false;
-
- cnt = poll_cb(num_lines, fds, timeout, data);
- if (cnt == GPIOD_SIMPLE_EVENT_POLL_RET_ERR) {
- ret = -1;
- goto out;
- } else if (cnt == GPIOD_SIMPLE_EVENT_POLL_RET_TIMEOUT) {
- rv = event_cb(GPIOD_SIMPLE_EVENT_CB_TIMEOUT,
- 0, &event.ts, data);
- if (rv == GPIOD_SIMPLE_EVENT_CB_RET_ERR) {
- ret = -1;
- goto out;
- } else if (rv == GPIOD_SIMPLE_EVENT_CB_RET_STOP) {
- ret = 0;
- goto out;
- }
- } else if (cnt == GPIOD_SIMPLE_EVENT_POLL_RET_STOP) {
- ret = 0;
- goto out;
- }
-
- for (i = 0; i < num_lines; i++) {
- if (!fds[i].event)
- continue;
-
- line = gpiod_line_bulk_get_line(&bulk, i);
- rv = gpiod_line_event_read(line, &event);
- if (rv < 0) {
- ret = rv;
- goto out;
- }
-
- if (event.event_type == GPIOD_LINE_EVENT_RISING_EDGE)
- evtype = GPIOD_SIMPLE_EVENT_CB_RISING_EDGE;
- else
- evtype = GPIOD_SIMPLE_EVENT_CB_FALLING_EDGE;
-
- rv = event_cb(evtype, gpiod_line_offset(line),
- &event.ts, data);
- if (rv == GPIOD_SIMPLE_EVENT_CB_RET_ERR) {
- ret = -1;
- goto out;
- } else if (rv == GPIOD_SIMPLE_EVENT_CB_RET_STOP) {
- ret = 0;
- goto out;
- }
-
- if (!--cnt)
- break;
- }
- }
-
-out:
- gpiod_chip_close(chip);
-
- return ret;
-}
-
-int gpiod_simple_find_line(const char *name, char *chipname,
- size_t chipname_size, unsigned int *offset)
-{
- struct gpiod_chip *chip;
- struct gpiod_line *line;
-
- line = gpiod_line_find(name);
- if (!line) {
- if (errno == ENOENT)
- return 0;
- else
- return -1;
- }
-
- chip = gpiod_line_get_chip(line);
- snprintf(chipname, chipname_size, "%s", gpiod_chip_name(chip));
- *offset = gpiod_line_offset(line);
- gpiod_chip_close(chip);
-
- return 1;
-}
if (argc != 1)
die("exactly one GPIO line name must be specified");
- rv = gpiod_simple_find_line(argv[0], chip, sizeof(chip), &offset);
+ rv = gpiod_ctxless_find_line(argv[0], chip, sizeof(chip), &offset);
if (rv < 0)
die_perror("error performing the line lookup");
else if (rv == 0)
die("invalid GPIO offset: %s", argv[i + 1]);
}
- status = gpiod_simple_get_value_multiple(device, offsets, values,
- num_lines, active_low,
- "gpioget");
+ status = gpiod_ctxless_get_value_multiple(device, offsets, values,
+ num_lines, active_low,
+ "gpioget");
if (status < 0)
die_perror("error reading GPIO values");
printf("%u", offset);
break;
case 'e':
- if (event_type == GPIOD_SIMPLE_EVENT_CB_RISING_EDGE)
+ if (event_type == GPIOD_CTXLESS_EVENT_CB_RISING_EDGE)
fputc('1', stdout);
else
fputc('0', stdout);
{
char *evname;
- if (event_type == GPIOD_SIMPLE_EVENT_CB_RISING_EDGE)
+ if (event_type == GPIOD_CTXLESS_EVENT_CB_RISING_EDGE)
evname = " RISING EDGE";
else
evname = "FALLING EDGE";
}
static int poll_callback(unsigned int num_lines,
- struct gpiod_simple_event_poll_fd *fds,
+ struct gpiod_ctxless_event_poll_fd *fds,
const struct timespec *timeout, void *data)
{
struct pollfd pfds[GPIOD_LINE_BULK_MAX_LINES + 1];
cnt = poll(pfds, num_lines + 1, ts);
if (cnt < 0)
- return GPIOD_SIMPLE_EVENT_POLL_RET_ERR;
+ return GPIOD_CTXLESS_EVENT_POLL_RET_ERR;
else if (cnt == 0)
- return GPIOD_SIMPLE_EVENT_POLL_RET_TIMEOUT;
+ return GPIOD_CTXLESS_EVENT_POLL_RET_TIMEOUT;
ret = cnt;
for (i = 0; i < num_lines; i++) {
*/
close(ctx->sigfd);
- return GPIOD_SIMPLE_EVENT_POLL_RET_STOP;
+ return GPIOD_CTXLESS_EVENT_POLL_RET_STOP;
}
static void handle_event(struct mon_ctx *ctx, int event_type,
struct mon_ctx *ctx = data;
switch (event_type) {
- case GPIOD_SIMPLE_EVENT_CB_RISING_EDGE:
+ case GPIOD_CTXLESS_EVENT_CB_RISING_EDGE:
if (ctx->watch_rising)
handle_event(ctx, event_type, line_offset, timestamp);
break;
- case GPIOD_SIMPLE_EVENT_CB_FALLING_EDGE:
+ case GPIOD_CTXLESS_EVENT_CB_FALLING_EDGE:
if (ctx->watch_falling)
handle_event(ctx, event_type, line_offset, timestamp);
break;
default:
- return GPIOD_SIMPLE_EVENT_CB_RET_OK;
+ return GPIOD_CTXLESS_EVENT_CB_RET_OK;
}
if (ctx->events_wanted && ctx->events_done >= ctx->events_wanted)
- return GPIOD_SIMPLE_EVENT_CB_RET_STOP;
+ return GPIOD_CTXLESS_EVENT_CB_RET_STOP;
- return GPIOD_SIMPLE_EVENT_CB_RET_OK;
+ return GPIOD_CTXLESS_EVENT_CB_RET_OK;
}
static int make_signalfd(void)
ctx.sigfd = make_signalfd();
- ret = gpiod_simple_event_loop_multiple(argv[0], offsets, num_lines,
- active_low, "gpiomon", &timeout,
- poll_callback,
- event_callback, &ctx);
+ ret = gpiod_ctxless_event_loop_multiple(argv[0], offsets, num_lines,
+ active_low, "gpiomon",
+ &timeout, poll_callback,
+ event_callback, &ctx);
if (ret)
die_perror("error waiting for events");
struct mode_mapping {
int id;
const char *name;
- gpiod_simple_set_value_cb callback;
+ gpiod_ctxless_set_value_cb callback;
};
static const struct mode_mapping modes[] = {
die("invalid offset: %s", argv[i + 1]);
}
- status = gpiod_simple_set_value_multiple(device, offsets, values,
- num_lines, active_low,
- "gpioset", mode->callback,
- &cbdata);
+ status = gpiod_ctxless_set_value_multiple(device, offsets, values,
+ num_lines, active_low,
+ "gpioset", mode->callback,
+ &cbdata);
if (status < 0)
die_perror("error setting the GPIO line values");
gpiod_test_SOURCES = gpiod-test.c \
gpiod-test.h \
tests-chip.c \
+ tests-ctxless.c \
tests-event.c \
tests-iter.c \
tests-line.c \
- tests-misc.c \
- tests-simple-api.c
+ tests-misc.c
if WITH_TOOLS
--- /dev/null
+/*
+ * This file is part of libgpiod.
+ *
+ * Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+/* Test cases for the high-level API. */
+
+#include "gpiod-test.h"
+
+#include <errno.h>
+
+static void ctxless_set_get_value(void)
+{
+ int ret;
+
+ ret = gpiod_ctxless_get_value(test_chip_name(0), 3,
+ false, TEST_CONSUMER);
+ TEST_ASSERT_EQ(ret, 0);
+
+ ret = gpiod_ctxless_set_value(test_chip_name(0), 3, 1,
+ false, TEST_CONSUMER, NULL, NULL);
+ TEST_ASSERT_RET_OK(ret);
+
+ ret = gpiod_ctxless_get_value(test_chip_name(0), 3,
+ false, TEST_CONSUMER);
+ TEST_ASSERT_EQ(ret, 1);
+}
+TEST_DEFINE(ctxless_set_get_value,
+ "ctxless set/get value - single line",
+ 0, { 8 });
+
+static void ctxless_set_get_value_multiple(void)
+{
+ unsigned int offsets[] = { 0, 1, 2, 3, 4, 5, 6, 12, 13, 15 };
+ int values[10], rv;
+
+ rv = gpiod_ctxless_get_value_multiple(test_chip_name(0), offsets,
+ values, 10, false, TEST_CONSUMER);
+ TEST_ASSERT_RET_OK(rv);
+
+ TEST_ASSERT_EQ(values[0], 0);
+ TEST_ASSERT_EQ(values[1], 0);
+ TEST_ASSERT_EQ(values[2], 0);
+ TEST_ASSERT_EQ(values[3], 0);
+ TEST_ASSERT_EQ(values[4], 0);
+ TEST_ASSERT_EQ(values[5], 0);
+ TEST_ASSERT_EQ(values[6], 0);
+ TEST_ASSERT_EQ(values[7], 0);
+ TEST_ASSERT_EQ(values[8], 0);
+ TEST_ASSERT_EQ(values[9], 0);
+
+ values[0] = 1;
+ values[1] = 1;
+ values[2] = 1;
+ values[3] = 0;
+ values[4] = 0;
+ values[5] = 1;
+ values[6] = 0;
+ values[7] = 1;
+ values[8] = 0;
+ values[9] = 0;
+
+ rv = gpiod_ctxless_set_value_multiple(test_chip_name(0), offsets,
+ values, 10, false, TEST_CONSUMER,
+ NULL, NULL);
+ TEST_ASSERT_RET_OK(rv);
+
+ rv = gpiod_ctxless_get_value_multiple(test_chip_name(0), offsets,
+ values, 10, false, TEST_CONSUMER);
+ TEST_ASSERT_RET_OK(rv);
+
+ TEST_ASSERT_EQ(values[0], 1);
+ TEST_ASSERT_EQ(values[1], 1);
+ TEST_ASSERT_EQ(values[2], 1);
+ TEST_ASSERT_EQ(values[3], 0);
+ TEST_ASSERT_EQ(values[4], 0);
+ TEST_ASSERT_EQ(values[5], 1);
+ TEST_ASSERT_EQ(values[6], 0);
+ TEST_ASSERT_EQ(values[7], 1);
+ TEST_ASSERT_EQ(values[8], 0);
+ TEST_ASSERT_EQ(values[9], 0);
+}
+TEST_DEFINE(ctxless_set_get_value_multiple,
+ "ctxless set/get value - multiple lines",
+ 0, { 16 });
+
+static void ctxless_get_value_multiple_max_lines(void)
+{
+ unsigned int offsets[GPIOD_LINE_BULK_MAX_LINES + 1];
+ int values[GPIOD_LINE_BULK_MAX_LINES + 1], ret;
+
+ ret = gpiod_ctxless_get_value_multiple(test_chip_name(0), offsets,
+ values,
+ GPIOD_LINE_BULK_MAX_LINES + 1,
+ false, TEST_CONSUMER);
+ TEST_ASSERT_NOTEQ(ret, 0);
+ TEST_ASSERT_ERRNO_IS(EINVAL);
+}
+TEST_DEFINE(ctxless_get_value_multiple_max_lines,
+ "gpiod_ctxless_get_value_multiple() exceed max lines",
+ 0, { 128 });
+
+static void ctxless_set_value_multiple_max_lines(void)
+{
+ unsigned int offsets[GPIOD_LINE_BULK_MAX_LINES + 1];
+ int values[GPIOD_LINE_BULK_MAX_LINES + 1], ret;
+
+ ret = gpiod_ctxless_set_value_multiple(test_chip_name(0), offsets,
+ values,
+ GPIOD_LINE_BULK_MAX_LINES + 1,
+ false, TEST_CONSUMER,
+ NULL, NULL);
+ TEST_ASSERT_NOTEQ(ret, 0);
+ TEST_ASSERT_ERRNO_IS(EINVAL);
+}
+TEST_DEFINE(ctxless_set_value_multiple_max_lines,
+ "gpiod_ctxless_set_value_multiple() exceed max lines",
+ 0, { 128 });
+
+struct ctxless_event_data {
+ bool got_rising_edge;
+ bool got_falling_edge;
+ unsigned int offset;
+ unsigned int count;
+};
+
+static int ctxless_event_cb(int evtype, unsigned int offset,
+ const struct timespec *ts TEST_UNUSED, void *data)
+{
+ struct ctxless_event_data *evdata = data;
+
+ if (evtype == GPIOD_CTXLESS_EVENT_CB_RISING_EDGE)
+ evdata->got_rising_edge = true;
+ else if (evtype == GPIOD_CTXLESS_EVENT_CB_FALLING_EDGE)
+ evdata->got_falling_edge = true;
+
+ evdata->offset = offset;
+
+ return ++evdata->count == 2 ? GPIOD_CTXLESS_EVENT_CB_RET_STOP
+ : GPIOD_CTXLESS_EVENT_CB_RET_OK;
+}
+
+static void ctxless_event_loop(void)
+{
+ struct ctxless_event_data evdata = { false, false, 0, 0 };
+ struct timespec ts = { 1, 0 };
+ int status;
+
+ test_set_event(0, 3, TEST_EVENT_ALTERNATING, 100);
+
+ status = gpiod_ctxless_event_loop(test_chip_name(0), 3, false,
+ TEST_CONSUMER, &ts, NULL,
+ ctxless_event_cb, &evdata);
+
+ TEST_ASSERT_RET_OK(status);
+ TEST_ASSERT(evdata.got_rising_edge);
+ TEST_ASSERT(evdata.got_falling_edge);
+ TEST_ASSERT_EQ(evdata.count, 2);
+ TEST_ASSERT_EQ(evdata.offset, 3);
+}
+TEST_DEFINE(ctxless_event_loop,
+ "gpiod_ctxless_event_loop() - single event",
+ 0, { 8 });
+
+static void ctxless_event_loop_multiple(void)
+{
+ struct ctxless_event_data evdata = { false, false, 0, 0 };
+ struct timespec ts = { 1, 0 };
+ unsigned int offsets[4];
+ int status;
+
+ offsets[0] = 2;
+ offsets[1] = 3;
+ offsets[2] = 5;
+ offsets[3] = 6;
+
+ test_set_event(0, 3, TEST_EVENT_ALTERNATING, 100);
+
+ status = gpiod_ctxless_event_loop_multiple(test_chip_name(0), offsets,
+ 4, false, TEST_CONSUMER,
+ &ts, NULL, ctxless_event_cb,
+ &evdata);
+
+ TEST_ASSERT_RET_OK(status);
+ TEST_ASSERT(evdata.got_rising_edge);
+ TEST_ASSERT(evdata.got_falling_edge);
+ TEST_ASSERT_EQ(evdata.count, 2);
+ TEST_ASSERT_EQ(evdata.offset, 3);
+}
+TEST_DEFINE(ctxless_event_loop_multiple,
+ "gpiod_ctxless_event_loop_multiple() - single event",
+ 0, { 8 });
+
+static int error_event_cb(int evtype TEST_UNUSED,
+ unsigned int offset TEST_UNUSED,
+ const struct timespec *ts TEST_UNUSED,
+ void *data TEST_UNUSED)
+{
+ errno = ENOTBLK;
+
+ return GPIOD_CTXLESS_EVENT_CB_RET_ERR;
+}
+
+static void ctxless_event_loop_indicate_error(void)
+{
+ struct timespec ts = { 1, 0 };
+ int rv;
+
+ test_set_event(0, 3, TEST_EVENT_ALTERNATING, 100);
+
+ rv = gpiod_ctxless_event_loop(test_chip_name(0), 3, false,
+ TEST_CONSUMER, &ts, NULL,
+ error_event_cb, NULL);
+
+ TEST_ASSERT_EQ(rv, -1);
+ TEST_ASSERT_ERRNO_IS(ENOTBLK);
+}
+TEST_DEFINE(ctxless_event_loop_indicate_error,
+ "gpiod_ctxless_event_loop() - error in callback",
+ 0, { 8 });
+
+static void ctxless_event_loop_indicate_error_timeout(void)
+{
+ struct timespec ts = { 0, 100000 };
+ int rv;
+
+ rv = gpiod_ctxless_event_loop(test_chip_name(0), 3, false,
+ TEST_CONSUMER, &ts, NULL,
+ error_event_cb, NULL);
+
+ TEST_ASSERT_EQ(rv, -1);
+ TEST_ASSERT_ERRNO_IS(ENOTBLK);
+}
+TEST_DEFINE(ctxless_event_loop_indicate_error_timeout,
+ "gpiod_ctxless_event_loop() - error in callback after timeout",
+ 0, { 8 });
+
+static void ctxless_find_line_good(void)
+{
+ unsigned int offset;
+ char chip[32];
+ int rv;
+
+ rv = gpiod_ctxless_find_line("gpio-mockup-C-14", chip,
+ sizeof(chip), &offset);
+ TEST_ASSERT_EQ(rv, 1);
+ TEST_ASSERT_EQ(offset, 14);
+ TEST_ASSERT_STR_EQ(chip, test_chip_name(2));
+}
+TEST_DEFINE(ctxless_find_line_good,
+ "gpiod_ctxless_find_line() - good",
+ TEST_FLAG_NAMED_LINES, { 8, 16, 16, 8 });
+
+static void ctxless_find_line_truncated(void)
+{
+ unsigned int offset;
+ char chip[6];
+ int rv;
+
+ rv = gpiod_ctxless_find_line("gpio-mockup-C-14", chip,
+ sizeof(chip), &offset);
+ TEST_ASSERT_EQ(rv, 1);
+ TEST_ASSERT_EQ(offset, 14);
+ TEST_ASSERT_STR_EQ(chip, "gpioc");
+}
+TEST_DEFINE(ctxless_find_line_truncated,
+ "gpiod_ctxless_find_line() - chip name truncated",
+ TEST_FLAG_NAMED_LINES, { 8, 16, 16, 8 });
+
+static void ctxless_find_line_not_found(void)
+{
+ unsigned int offset;
+ char chip[32];
+ int rv;
+
+ rv = gpiod_ctxless_find_line("nonexistent", chip,
+ sizeof(chip), &offset);
+ TEST_ASSERT_EQ(rv, 0);
+}
+TEST_DEFINE(ctxless_find_line_not_found,
+ "gpiod_ctxless_find_line() - not found",
+ TEST_FLAG_NAMED_LINES, { 8, 16, 16, 8 });
values[0] = values[1] = values[2] = values[3] = 1;
- rv = gpiod_simple_set_value_multiple(test_chip_name(1), offsets,
- values, 4, false, TEST_CONSUMER,
- NULL, NULL);
+ rv = gpiod_ctxless_set_value_multiple(test_chip_name(1), offsets,
+ values, 4, false, TEST_CONSUMER,
+ NULL, NULL);
TEST_ASSERT_RET_OK(rv);
test_tool_run("gpioget", test_chip_name(1),
values[0] = values[1] = values[2] = values[3] = 1;
- rv = gpiod_simple_set_value_multiple(test_chip_name(1), offsets,
- values, 4, false, TEST_CONSUMER,
- NULL, NULL);
+ rv = gpiod_ctxless_set_value_multiple(test_chip_name(1), offsets,
+ values, 4, false, TEST_CONSUMER,
+ NULL, NULL);
TEST_ASSERT_RET_OK(rv);
test_tool_run("gpioget", "--active-low", test_chip_name(1),
values[0] = values[1] = values[2] = 1;
- rv = gpiod_simple_set_value_multiple(test_chip_name(1), offsets,
- values, 3, false, TEST_CONSUMER,
- NULL, NULL);
+ rv = gpiod_ctxless_set_value_multiple(test_chip_name(1), offsets,
+ values, 3, false, TEST_CONSUMER,
+ NULL, NULL);
TEST_ASSERT_RET_OK(rv);
test_tool_run("gpioget", test_chip_name(1),
offsets[6] = 6;
offsets[7] = 7;
- rv = gpiod_simple_get_value_multiple(test_chip_name(2), offsets,
- values, 8, false, TEST_CONSUMER);
+ rv = gpiod_ctxless_get_value_multiple(test_chip_name(2), offsets,
+ values, 8, false, TEST_CONSUMER);
TEST_ASSERT_RET_OK(rv);
TEST_ASSERT_EQ(values[0], 0);
offsets[6] = 6;
offsets[7] = 7;
- rv = gpiod_simple_get_value_multiple(test_chip_name(2), offsets,
- values, 8, false, TEST_CONSUMER);
+ rv = gpiod_ctxless_get_value_multiple(test_chip_name(2), offsets,
+ values, 8, false, TEST_CONSUMER);
TEST_ASSERT_RET_OK(rv);
TEST_ASSERT_EQ(values[0], 1);
offsets[6] = 6;
offsets[7] = 7;
- rv = gpiod_simple_get_value_multiple(test_chip_name(2), offsets,
- values, 8, false, TEST_CONSUMER);
+ rv = gpiod_ctxless_get_value_multiple(test_chip_name(2), offsets,
+ values, 8, false, TEST_CONSUMER);
TEST_ASSERT_RET_OK(rv);
TEST_ASSERT_EQ(values[0], 0);
offsets[3] = 6;
offsets[4] = 7;
- rv = gpiod_simple_get_value_multiple(test_chip_name(2), offsets,
- values, 5, false, TEST_CONSUMER);
+ rv = gpiod_ctxless_get_value_multiple(test_chip_name(2), offsets,
+ values, 5, false, TEST_CONSUMER);
TEST_ASSERT_RET_OK(rv);
TEST_ASSERT_EQ(values[0], 0);
offsets[3] = 6;
offsets[4] = 7;
- rv = gpiod_simple_get_value_multiple(test_chip_name(2),
- offsets, values,
- 5, false, TEST_CONSUMER);
+ rv = gpiod_ctxless_get_value_multiple(test_chip_name(2),
+ offsets, values,
+ 5, false, TEST_CONSUMER);
TEST_ASSERT_RET_OK(rv);
TEST_ASSERT_EQ(values[0], 0);
offsets[1] = 2;
offsets[2] = 5;
- rv = gpiod_simple_get_value_multiple(test_chip_name(0), offsets,
- values, 3, false, TEST_CONSUMER);
+ rv = gpiod_ctxless_get_value_multiple(test_chip_name(0), offsets,
+ values, 3, false, TEST_CONSUMER);
TEST_ASSERT_RET_OK(rv);
TEST_ASSERT_EQ(values[0], 1);
+++ /dev/null
-/*
- * This file is part of libgpiod.
- *
- * Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-/* Test cases for the simple API. */
-
-#include "gpiod-test.h"
-
-#include <errno.h>
-
-static void simple_set_get_value(void)
-{
- int ret;
-
- ret = gpiod_simple_get_value(test_chip_name(0), 3,
- false, TEST_CONSUMER);
- TEST_ASSERT_EQ(ret, 0);
-
- ret = gpiod_simple_set_value(test_chip_name(0), 3, 1,
- false, TEST_CONSUMER, NULL, NULL);
- TEST_ASSERT_RET_OK(ret);
-
- ret = gpiod_simple_get_value(test_chip_name(0), 3,
- false, TEST_CONSUMER);
- TEST_ASSERT_EQ(ret, 1);
-}
-TEST_DEFINE(simple_set_get_value,
- "simple set/get value - single line",
- 0, { 8 });
-
-static void simple_set_get_value_multiple(void)
-{
- unsigned int offsets[] = { 0, 1, 2, 3, 4, 5, 6, 12, 13, 15 };
- int values[10], rv;
-
- rv = gpiod_simple_get_value_multiple(test_chip_name(0), offsets,
- values, 10, false, TEST_CONSUMER);
- TEST_ASSERT_RET_OK(rv);
-
- TEST_ASSERT_EQ(values[0], 0);
- TEST_ASSERT_EQ(values[1], 0);
- TEST_ASSERT_EQ(values[2], 0);
- TEST_ASSERT_EQ(values[3], 0);
- TEST_ASSERT_EQ(values[4], 0);
- TEST_ASSERT_EQ(values[5], 0);
- TEST_ASSERT_EQ(values[6], 0);
- TEST_ASSERT_EQ(values[7], 0);
- TEST_ASSERT_EQ(values[8], 0);
- TEST_ASSERT_EQ(values[9], 0);
-
- values[0] = 1;
- values[1] = 1;
- values[2] = 1;
- values[3] = 0;
- values[4] = 0;
- values[5] = 1;
- values[6] = 0;
- values[7] = 1;
- values[8] = 0;
- values[9] = 0;
-
- rv = gpiod_simple_set_value_multiple(test_chip_name(0), offsets,
- values, 10, false, TEST_CONSUMER,
- NULL, NULL);
- TEST_ASSERT_RET_OK(rv);
-
- rv = gpiod_simple_get_value_multiple(test_chip_name(0), offsets,
- values, 10, false, TEST_CONSUMER);
- TEST_ASSERT_RET_OK(rv);
-
- TEST_ASSERT_EQ(values[0], 1);
- TEST_ASSERT_EQ(values[1], 1);
- TEST_ASSERT_EQ(values[2], 1);
- TEST_ASSERT_EQ(values[3], 0);
- TEST_ASSERT_EQ(values[4], 0);
- TEST_ASSERT_EQ(values[5], 1);
- TEST_ASSERT_EQ(values[6], 0);
- TEST_ASSERT_EQ(values[7], 1);
- TEST_ASSERT_EQ(values[8], 0);
- TEST_ASSERT_EQ(values[9], 0);
-}
-TEST_DEFINE(simple_set_get_value_multiple,
- "simple set/get value - multiple lines",
- 0, { 16 });
-
-static void simple_get_value_multiple_max_lines(void)
-{
- unsigned int offsets[GPIOD_LINE_BULK_MAX_LINES + 1];
- int values[GPIOD_LINE_BULK_MAX_LINES + 1], ret;
-
- ret = gpiod_simple_get_value_multiple(test_chip_name(0), offsets,
- values,
- GPIOD_LINE_BULK_MAX_LINES + 1,
- false, TEST_CONSUMER);
- TEST_ASSERT_NOTEQ(ret, 0);
- TEST_ASSERT_ERRNO_IS(EINVAL);
-}
-TEST_DEFINE(simple_get_value_multiple_max_lines,
- "gpiod_simple_get_value_multiple() exceed max lines",
- 0, { 128 });
-
-static void simple_set_value_multiple_max_lines(void)
-{
- unsigned int offsets[GPIOD_LINE_BULK_MAX_LINES + 1];
- int values[GPIOD_LINE_BULK_MAX_LINES + 1], ret;
-
- ret = gpiod_simple_set_value_multiple(test_chip_name(0), offsets,
- values,
- GPIOD_LINE_BULK_MAX_LINES + 1,
- false, TEST_CONSUMER, NULL, NULL);
- TEST_ASSERT_NOTEQ(ret, 0);
- TEST_ASSERT_ERRNO_IS(EINVAL);
-}
-TEST_DEFINE(simple_set_value_multiple_max_lines,
- "gpiod_simple_set_value_multiple() exceed max lines",
- 0, { 128 });
-
-struct simple_event_data {
- bool got_rising_edge;
- bool got_falling_edge;
- unsigned int offset;
- unsigned int count;
-};
-
-static int simple_event_cb(int evtype, unsigned int offset,
- const struct timespec *ts TEST_UNUSED, void *data)
-{
- struct simple_event_data *evdata = data;
-
- if (evtype == GPIOD_SIMPLE_EVENT_CB_RISING_EDGE)
- evdata->got_rising_edge = true;
- else if (evtype == GPIOD_SIMPLE_EVENT_CB_FALLING_EDGE)
- evdata->got_falling_edge = true;
-
- evdata->offset = offset;
-
- return ++evdata->count == 2 ? GPIOD_SIMPLE_EVENT_CB_RET_STOP
- : GPIOD_SIMPLE_EVENT_CB_RET_OK;
-}
-
-static void simple_event_loop(void)
-{
- struct simple_event_data evdata = { false, false, 0, 0 };
- struct timespec ts = { 1, 0 };
- int status;
-
- test_set_event(0, 3, TEST_EVENT_ALTERNATING, 100);
-
- status = gpiod_simple_event_loop(test_chip_name(0), 3, false,
- TEST_CONSUMER, &ts, NULL,
- simple_event_cb, &evdata);
-
- TEST_ASSERT_RET_OK(status);
- TEST_ASSERT(evdata.got_rising_edge);
- TEST_ASSERT(evdata.got_falling_edge);
- TEST_ASSERT_EQ(evdata.count, 2);
- TEST_ASSERT_EQ(evdata.offset, 3);
-}
-TEST_DEFINE(simple_event_loop,
- "gpiod_simple_event_loop() - single event",
- 0, { 8 });
-
-static void simple_event_loop_multiple(void)
-{
- struct simple_event_data evdata = { false, false, 0, 0 };
- struct timespec ts = { 1, 0 };
- unsigned int offsets[4];
- int status;
-
- offsets[0] = 2;
- offsets[1] = 3;
- offsets[2] = 5;
- offsets[3] = 6;
-
- test_set_event(0, 3, TEST_EVENT_ALTERNATING, 100);
-
- status = gpiod_simple_event_loop_multiple(test_chip_name(0), offsets,
- 4, false, TEST_CONSUMER, &ts,
- NULL, simple_event_cb,
- &evdata);
-
- TEST_ASSERT_RET_OK(status);
- TEST_ASSERT(evdata.got_rising_edge);
- TEST_ASSERT(evdata.got_falling_edge);
- TEST_ASSERT_EQ(evdata.count, 2);
- TEST_ASSERT_EQ(evdata.offset, 3);
-}
-TEST_DEFINE(simple_event_loop_multiple,
- "gpiod_simple_event_loop_multiple() - single event",
- 0, { 8 });
-
-static int error_event_cb(int evtype TEST_UNUSED,
- unsigned int offset TEST_UNUSED,
- const struct timespec *ts TEST_UNUSED,
- void *data TEST_UNUSED)
-{
- errno = ENOTBLK;
-
- return GPIOD_SIMPLE_EVENT_CB_RET_ERR;
-}
-
-static void simple_event_loop_indicate_error(void)
-{
- struct timespec ts = { 1, 0 };
- int rv;
-
- test_set_event(0, 3, TEST_EVENT_ALTERNATING, 100);
-
- rv = gpiod_simple_event_loop(test_chip_name(0), 3, false,
- TEST_CONSUMER, &ts, NULL,
- error_event_cb, NULL);
-
- TEST_ASSERT_EQ(rv, -1);
- TEST_ASSERT_ERRNO_IS(ENOTBLK);
-}
-TEST_DEFINE(simple_event_loop_indicate_error,
- "gpiod_simple_event_loop() - error in callback",
- 0, { 8 });
-
-static void simple_event_loop_indicate_error_timeout(void)
-{
- struct timespec ts = { 0, 100000 };
- int rv;
-
- rv = gpiod_simple_event_loop(test_chip_name(0), 3, false,
- TEST_CONSUMER, &ts, NULL,
- error_event_cb, NULL);
-
- TEST_ASSERT_EQ(rv, -1);
- TEST_ASSERT_ERRNO_IS(ENOTBLK);
-}
-TEST_DEFINE(simple_event_loop_indicate_error_timeout,
- "gpiod_simple_event_loop() - error in callback after timeout",
- 0, { 8 });
-
-static void simple_find_line_good(void)
-{
- unsigned int offset;
- char chip[32];
- int rv;
-
- rv = gpiod_simple_find_line("gpio-mockup-C-14", chip,
- sizeof(chip), &offset);
- TEST_ASSERT_EQ(rv, 1);
- TEST_ASSERT_EQ(offset, 14);
- TEST_ASSERT_STR_EQ(chip, test_chip_name(2));
-}
-TEST_DEFINE(simple_find_line_good,
- "gpiod_simple_find_line() - good",
- TEST_FLAG_NAMED_LINES, { 8, 16, 16, 8 });
-
-static void simple_find_line_truncated(void)
-{
- unsigned int offset;
- char chip[6];
- int rv;
-
- rv = gpiod_simple_find_line("gpio-mockup-C-14", chip,
- sizeof(chip), &offset);
- TEST_ASSERT_EQ(rv, 1);
- TEST_ASSERT_EQ(offset, 14);
- TEST_ASSERT_STR_EQ(chip, "gpioc");
-}
-TEST_DEFINE(simple_find_line_truncated,
- "gpiod_simple_find_line() - chip name truncated",
- TEST_FLAG_NAMED_LINES, { 8, 16, 16, 8 });
-
-static void simple_find_line_not_found(void)
-{
- unsigned int offset;
- char chip[32];
- int rv;
-
- rv = gpiod_simple_find_line("nonexistent", chip,
- sizeof(chip), &offset);
- TEST_ASSERT_EQ(rv, 0);
-}
-TEST_DEFINE(simple_find_line_not_found,
- "gpiod_simple_find_line() - not found",
- TEST_FLAG_NAMED_LINES, { 8, 16, 16, 8 });