@@ -6,7 +6,7 @@
#include <stdbool.h>
#include <stdlib.h>
-#include <time.h>
+#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@@ -37,6 +37,8 @@ struct gpiod_chip;
struct gpiod_line;
struct gpiod_line_info;
struct gpiod_line_bulk;
+struct gpiod_line_event;
+struct gpiod_line_event_buffer;
/**
* @defgroup common Common helper macros
@@ -928,17 +930,35 @@ enum {
/**< Falling edge event. */
};
-/**
- * @brief Structure holding event info.
- */
-struct gpiod_line_event {
- struct timespec ts;
- /**< Best estimate of time of event occurrence. */
- int event_type;
- /**< Type of the event that occurred. */
- int offset;
- /**< Offset of line on which the event occurred. */
-};
+struct gpiod_line_event *gpiod_line_event_ref(struct gpiod_line_event *event);
+
+void gpiod_line_event_unref(struct gpiod_line_event *event);
+
+int gpiod_line_event_get_event_type(struct gpiod_line_event *event);
+
+uint64_t gpiod_line_event_get_timestamp(struct gpiod_line_event *event);
+
+unsigned int gpiod_line_event_get_line_offset(struct gpiod_line_event *event);
+
+unsigned int gpiod_line_event_get_global_seqno(struct gpiod_line_event *event);
+
+unsigned int gpiod_line_event_get_line_seqno(struct gpiod_line_event *event);
+
+struct gpiod_line_event_buffer *
+gpiod_line_event_buffer_new(unsigned int capacity);
+
+struct gpiod_line_event_buffer *
+gpiod_line_event_buffer_ref(struct gpiod_line_event_buffer *buf);
+
+void gpiod_line_event_buffer_unref(struct gpiod_line_event_buffer *buf);
+
+struct gpiod_line_event *
+gpiod_line_event_buffer_get_event(struct gpiod_line_event_buffer *buf,
+ unsigned long index);
+
+struct gpiod_line_event *
+gpiod_line_event_buffer_copy_event(struct gpiod_line_event_buffer *buf,
+ unsigned long index);
/**
* @brief Wait for an event on a single line.
@@ -947,8 +967,7 @@ struct gpiod_line_event {
* @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);
+int gpiod_line_event_wait(struct gpiod_line *line, uint64_t timeout);
/**
* @brief Wait for events on a set of lines.
@@ -959,8 +978,7 @@ int gpiod_line_event_wait(struct gpiod_line *line,
* @return 0 if wait timed out, -1 if an error occurred, 1 if at least one
* event occurred.
*/
-int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
- const struct timespec *timeout,
+int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk, uint64_t timeout,
struct gpiod_line_bulk *event_bulk);
/**
@@ -971,7 +989,7 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
* @note This function will block if no event was queued for this line.
*/
int gpiod_line_event_read(struct gpiod_line *line,
- struct gpiod_line_event *event);
+ struct gpiod_line_event_buffer *buf);
/**
* @brief Read up to a certain number of events from the GPIO line.
@@ -983,7 +1001,7 @@ int gpiod_line_event_read(struct gpiod_line *line,
* failure -1 is returned.
*/
int gpiod_line_event_read_multiple(struct gpiod_line *line,
- struct gpiod_line_event *events,
+ struct gpiod_line_event_buffer *buf,
unsigned int num_events);
/**
@@ -1008,19 +1026,20 @@ int gpiod_line_event_get_fd(struct gpiod_line *line);
* directly read the event data from it using this routine. This function
* translates the kernel representation of the event to the libgpiod format.
*/
-int gpiod_line_event_read_fd(int fd, struct gpiod_line_event *event);
+int gpiod_line_event_read_fd(int fd, struct gpiod_line_event_buffer *buf);
/**
* @brief Read up to a certain number of events directly from a file descriptor.
* @param fd File descriptor.
* @param events Buffer to which the event data will be copied. Must hold at
* least the amount of events specified in num_events.
- * @param num_events Specifies how many events can be stored in the buffer.
+ * @param max_events Specifies the maximum number of events to read.
* @return On success returns the number of events stored in the buffer, on
* failure -1 is returned.
*/
-int gpiod_line_event_read_fd_multiple(int fd, struct gpiod_line_event *events,
- unsigned int num_events);
+int gpiod_line_event_read_fd_multiple(int fd,
+ struct gpiod_line_event_buffer *buf,
+ unsigned int max_events);
/**
* @}
@@ -1033,6 +1052,8 @@ int gpiod_line_event_read_fd_multiple(int fd, struct gpiod_line_event *events,
* Various libgpiod-related functions.
*/
+uint64_t gpiod_sec_to_nsec(uint64_t sec);
+
/**
* @brief Get the API version of the library as a human-readable string.
* @return Human-readable string containing the library version.
@@ -2,7 +2,14 @@
# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
lib_LTLIBRARIES = libgpiod.la
-libgpiod_la_SOURCES = core.c helpers.c internal.c internal.h info.c misc.c uapi/gpio.h
+libgpiod_la_SOURCES = core.c \
+ event.c \
+ helpers.c \
+ internal.h \
+ internal.c \
+ info.c \
+ misc.c \
+ uapi/gpio.h
libgpiod_la_CFLAGS = -Wall -Wextra -g -std=gnu89
libgpiod_la_CFLAGS += -fvisibility=hidden -I$(top_srcdir)/include/
libgpiod_la_CFLAGS += -include $(top_builddir)/config.h
@@ -15,6 +15,7 @@
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
+#include <time.h>
#include <unistd.h>
#include "internal.h"
@@ -1060,8 +1061,7 @@ GPIOD_API int gpiod_line_set_direction_output_bulk(struct gpiod_line_bulk *bulk,
line->req_flags, values);
}
-GPIOD_API int gpiod_line_event_wait(struct gpiod_line *line,
- const struct timespec *timeout)
+GPIOD_API int gpiod_line_event_wait(struct gpiod_line *line, uint64_t timeout)
{
struct gpiod_line_bulk bulk = BULK_SINGLE_LINE_INIT(line);
@@ -1069,12 +1069,13 @@ GPIOD_API int gpiod_line_event_wait(struct gpiod_line *line,
}
GPIOD_API int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
- const struct timespec *timeout,
+ uint64_t timeout,
struct gpiod_line_bulk *event_bulk)
{
struct pollfd fds[LINE_REQUEST_MAX_LINES];
unsigned int off, num_lines;
struct gpiod_line *line;
+ struct timespec ts;
int rv;
if (!line_bulk_all_requested(bulk))
@@ -1088,7 +1089,10 @@ GPIOD_API int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
fds[off].events = POLLIN | POLLPRI;
}
- rv = ppoll(fds, num_lines, timeout, NULL);
+ ts.tv_sec = timeout / 1000000000ULL;
+ ts.tv_nsec = timeout % 1000000000ULL;
+
+ rv = ppoll(fds, num_lines, &ts, NULL);
if (rv < 0)
return -1;
else if (rv == 0)
@@ -1116,31 +1120,6 @@ GPIOD_API int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
return 1;
}
-GPIOD_API int gpiod_line_event_read(struct gpiod_line *line,
- struct gpiod_line_event *event)
-{
- int ret;
-
- ret = gpiod_line_event_read_multiple(line, event, 1);
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-GPIOD_API int gpiod_line_event_read_multiple(struct gpiod_line *line,
- struct gpiod_line_event *events,
- unsigned int num_events)
-{
- int fd;
-
- fd = gpiod_line_event_get_fd(line);
- if (fd < 0)
- return -1;
-
- return gpiod_line_event_read_fd_multiple(fd, events, num_events);
-}
-
GPIOD_API int gpiod_line_event_get_fd(struct gpiod_line *line)
{
if (line->state != LINE_REQUESTED_EVENTS) {
@@ -1150,64 +1129,3 @@ GPIOD_API int gpiod_line_event_get_fd(struct gpiod_line *line)
return line_get_fd(line);
}
-
-GPIOD_API int gpiod_line_event_read_fd(int fd, struct gpiod_line_event *event)
-{
- int ret;
-
- ret = gpiod_line_event_read_fd_multiple(fd, event, 1);
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-GPIOD_API int gpiod_line_event_read_fd_multiple(int fd,
- struct gpiod_line_event *events,
- unsigned int num_events)
-{
- /*
- * 16 is the maximum number of events the kernel can store in the FIFO
- * so we can allocate the buffer on the stack.
- *
- * NOTE: This is no longer strictly true for uAPI v2. While 16 is
- * the default for single line, a request with multiple lines will
- * have a larger buffer. So need to rethink the allocation here,
- * or at least the comment above...
- */
- struct gpio_v2_line_event evdata[16], *curr;
- struct gpiod_line_event *event;
- unsigned int events_read, i;
- ssize_t rd;
-
- memset(evdata, 0, sizeof(evdata));
-
- if (num_events > 16)
- num_events = 16;
-
- rd = read(fd, evdata, num_events * sizeof(*evdata));
- if (rd < 0) {
- return -1;
- } else if ((unsigned int)rd < sizeof(*evdata)) {
- errno = EIO;
- return -1;
- }
-
- events_read = rd / sizeof(*evdata);
- if (events_read < num_events)
- num_events = events_read;
-
- for (i = 0; i < num_events; i++) {
- curr = &evdata[i];
- event = &events[i];
-
- event->offset = curr->offset;
- event->event_type = curr->id == GPIO_V2_LINE_EVENT_RISING_EDGE
- ? GPIOD_LINE_EVENT_RISING_EDGE
- : GPIOD_LINE_EVENT_FALLING_EDGE;
- event->ts.tv_sec = curr->timestamp_ns / 1000000000ULL;
- event->ts.tv_nsec = curr->timestamp_ns % 1000000000ULL;
- }
-
- return i;
-}
new file mode 100644
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2021 Bartosz Golaszewski <brgl@bgdev.pl>
+
+#include <errno.h>
+#include <gpiod.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "internal.h"
+#include "uapi/gpio.h"
+
+/* As defined in the kernel. */
+#define EVENT_BUFFER_MAX_CAPACITY (GPIO_V2_LINES_MAX * 16)
+
+struct gpiod_line_event {
+ struct gpiod_refcount refcount;
+ int event_type;
+ uint64_t timestamp;
+ unsigned int line_offset;
+ unsigned int global_seqno;
+ unsigned int line_seqno;
+};
+
+struct gpiod_line_event_buffer {
+ struct gpiod_refcount refcount;
+ unsigned int capacity;
+ unsigned int num_events;
+ struct gpiod_line_event *events;
+ struct gpio_v2_line_event *event_data;
+};
+
+static void line_event_release(struct gpiod_refcount *refcount)
+{
+ struct gpiod_line_event *event;
+
+ event = gpiod_container_of(refcount, struct gpiod_line_event, refcount);
+
+ free(event);
+}
+
+GPIOD_API struct gpiod_line_event *
+gpiod_line_event_ref(struct gpiod_line_event *event)
+{
+ gpiod_refcount_ref(&event->refcount);
+ return event;
+}
+
+GPIOD_API void gpiod_line_event_unref(struct gpiod_line_event *event)
+{
+ gpiod_refcount_unref(&event->refcount);
+}
+
+GPIOD_API int gpiod_line_event_get_event_type(struct gpiod_line_event *event)
+{
+ return event->event_type;
+}
+
+GPIOD_API uint64_t
+gpiod_line_event_get_timestamp(struct gpiod_line_event *event)
+{
+ return event->timestamp;
+}
+
+GPIOD_API unsigned int
+gpiod_line_event_get_line_offset(struct gpiod_line_event *event)
+{
+ return event->line_offset;
+}
+
+GPIOD_API unsigned int
+gpiod_line_event_get_global_seqno(struct gpiod_line_event *event)
+{
+ return event->global_seqno;
+}
+
+GPIOD_API unsigned int
+gpiod_line_event_get_line_seqno(struct gpiod_line_event *event)
+{
+ return event->line_seqno;
+}
+
+static void line_event_buffer_release(struct gpiod_refcount *refcount)
+{
+ struct gpiod_line_event_buffer *buf;
+
+ buf = gpiod_container_of(refcount,
+ struct gpiod_line_event_buffer, refcount);
+
+ free(buf);
+}
+
+GPIOD_API struct gpiod_line_event_buffer *
+gpiod_line_event_buffer_new(unsigned int capacity)
+{
+ struct gpiod_line_event_buffer *buf;
+
+ if (capacity == 0 || capacity > EVENT_BUFFER_MAX_CAPACITY) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ buf = malloc(sizeof(*buf));
+ if (!buf)
+ return NULL;
+
+ memset(buf, 0, sizeof(*buf));
+ gpiod_refcount_init(&buf->refcount, line_event_buffer_release);
+ buf->capacity = capacity;
+
+ buf->events = calloc(capacity, sizeof(*buf->events));
+ if (!buf->events) {
+ free(buf);
+ return NULL;
+ }
+
+ buf->event_data = calloc(capacity, sizeof(*buf->event_data));
+ if (!buf->event_data) {
+ free(buf->events);
+ free(buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
+GPIOD_API struct gpiod_line_event_buffer *
+gpiod_line_event_buffer_ref(struct gpiod_line_event_buffer *buf)
+{
+ gpiod_refcount_ref(&buf->refcount);
+ return buf;
+}
+
+GPIOD_API void
+gpiod_line_event_buffer_unref(struct gpiod_line_event_buffer *buf)
+{
+ gpiod_refcount_unref(&buf->refcount);
+}
+
+GPIOD_API struct gpiod_line_event *
+gpiod_line_event_buffer_get_event(struct gpiod_line_event_buffer *buf,
+ unsigned long index)
+{
+ if (index >= buf->num_events) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ return &buf->events[index];
+}
+
+GPIOD_API struct gpiod_line_event *
+gpiod_line_event_buffer_copy_event(struct gpiod_line_event_buffer *buf,
+ unsigned long index)
+{
+ struct gpiod_line_event *event;
+
+ if (index >= buf->num_events) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ event = malloc(sizeof(*event));
+ if (!event)
+ return NULL;
+
+ memcpy(event, &buf->events[index], sizeof(*event));
+ gpiod_refcount_init(&event->refcount, line_event_release);
+
+ return event;
+}
+
+GPIOD_API int gpiod_line_event_read(struct gpiod_line *line,
+ struct gpiod_line_event_buffer *buf)
+{
+ int ret;
+
+ ret = gpiod_line_event_read_multiple(line, buf, 1);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+GPIOD_API int
+gpiod_line_event_read_multiple(struct gpiod_line *line,
+ struct gpiod_line_event_buffer *buf,
+ unsigned int num_events)
+{
+ int fd;
+
+ fd = gpiod_line_event_get_fd(line);
+ if (fd < 0)
+ return -1;
+
+ return gpiod_line_event_read_fd_multiple(fd, buf, num_events);
+}
+
+GPIOD_API int gpiod_line_event_read_fd(int fd,
+ struct gpiod_line_event_buffer *buf)
+{
+ int ret;
+
+ ret = gpiod_line_event_read_fd_multiple(fd, buf, 1);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+GPIOD_API int
+gpiod_line_event_read_fd_multiple(int fd,
+ struct gpiod_line_event_buffer *buf,
+ unsigned int max_events)
+{
+ struct gpio_v2_line_event *curr;
+ struct gpiod_line_event *event;
+ unsigned int i;
+ ssize_t rd;
+
+ memset(buf->event_data, 0, sizeof(*buf->event_data) * buf->capacity);
+ memset(buf->events, 0, sizeof(*buf->events) * buf->capacity);
+
+ if (max_events > buf->capacity)
+ max_events = buf->capacity;
+
+ rd = read(fd, buf->event_data, max_events * sizeof(*buf->event_data));
+ if (rd < 0) {
+ return -1;
+ } else if ((unsigned int)rd < sizeof(*buf->event_data)) {
+ errno = EIO;
+ return -1;
+ }
+
+ buf->num_events = rd / sizeof(*buf->event_data);
+
+ for (i = 0; i < buf->num_events; i++) {
+ curr = &buf->event_data[i];
+ event = &buf->events[i];
+
+ event->line_offset = curr->offset;
+ event->event_type = curr->id == GPIO_V2_LINE_EVENT_RISING_EDGE
+ ? GPIOD_LINE_EVENT_RISING_EDGE
+ : GPIOD_LINE_EVENT_FALLING_EDGE;
+ event->timestamp = curr->timestamp_ns;
+ event->global_seqno = curr->seqno;
+ event->line_seqno = curr->line_seqno;
+ }
+
+ return i;
+}
@@ -7,6 +7,11 @@
#include "internal.h"
+GPIOD_API uint64_t gpiod_sec_to_nsec(uint64_t sec)
+{
+ return sec * 1000000000ULL;
+}
+
GPIOD_API const char *gpiod_version_string(void)
{
return GPIOD_VERSION_STR;
@@ -22,10 +22,13 @@
typedef struct gpiod_chip gpiod_chip_struct;
typedef struct gpiod_line_bulk gpiod_line_bulk_struct;
typedef struct gpiod_line_info gpiod_line_info_struct;
+typedef struct gpiod_line_event_buffer gpiod_line_event_buffer_struct;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_struct, gpiod_chip_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_bulk_struct, gpiod_line_bulk_free);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_info_struct, gpiod_line_info_unref);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_event_buffer_struct,
+ gpiod_line_event_buffer_unref);
/* These are private definitions and should not be used directly. */
typedef void (*_gpiod_test_func)(void);
@@ -10,10 +10,11 @@
GPIOD_TEST_CASE(rising_edge_good, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -21,6 +22,10 @@ GPIOD_TEST_CASE(rising_edge_good, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -31,21 +36,27 @@ GPIOD_TEST_CASE(rising_edge_good, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
}
GPIOD_TEST_CASE(falling_edge_good, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -53,6 +64,10 @@ GPIOD_TEST_CASE(falling_edge_good, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -64,21 +79,29 @@ GPIOD_TEST_CASE(falling_edge_good, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
}
GPIOD_TEST_CASE(rising_edge_ignore_falling, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf0 = NULL;
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf1 = NULL;
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf2 = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev[3];
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *events[3];
struct gpiod_line *line;
gint ret;
@@ -86,6 +109,14 @@ GPIOD_TEST_CASE(rising_edge_ignore_falling, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf0 = gpiod_line_event_buffer_new(1);
+ event_buf1 = gpiod_line_event_buffer_new(1);
+ event_buf2 = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf0);
+ g_assert_nonnull(event_buf1);
+ g_assert_nonnull(event_buf2);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -96,32 +127,44 @@ GPIOD_TEST_CASE(rising_edge_ignore_falling, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev[0]);
+ ret = gpiod_line_event_read(line, event_buf0);
g_assert_cmpint(ret, ==, 0);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev[1]);
+ ret = gpiod_line_event_read(line, event_buf1);
g_assert_cmpint(ret, ==, 0);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev[2]);
+ ret = gpiod_line_event_read(line, event_buf2);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev[0].event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
- g_assert_cmpint(ev[1].event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
- g_assert_cmpint(ev[2].event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
+ events[0] = gpiod_line_event_buffer_get_event(event_buf0, 0);
+ events[1] = gpiod_line_event_buffer_get_event(event_buf1, 0);
+ events[2] = gpiod_line_event_buffer_get_event(event_buf2, 0);
+ g_assert_nonnull(events[0]);
+ g_assert_nonnull(events[1]);
+ g_assert_nonnull(events[2]);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[0]), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[1]), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[2]), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
}
GPIOD_TEST_CASE(both_edges, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -129,6 +172,10 @@ GPIOD_TEST_CASE(both_edges, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -139,29 +186,40 @@ GPIOD_TEST_CASE(both_edges, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
}
GPIOD_TEST_CASE(both_edges_active_low, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -169,6 +227,10 @@ GPIOD_TEST_CASE(both_edges_active_low, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -180,29 +242,40 @@ GPIOD_TEST_CASE(both_edges_active_low, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
}
GPIOD_TEST_CASE(both_edges_bias_disable, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -210,6 +283,10 @@ GPIOD_TEST_CASE(both_edges_bias_disable, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -221,29 +298,40 @@ GPIOD_TEST_CASE(both_edges_bias_disable, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
}
GPIOD_TEST_CASE(both_edges_bias_pull_down, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -251,6 +339,10 @@ GPIOD_TEST_CASE(both_edges_bias_pull_down, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -262,29 +354,40 @@ GPIOD_TEST_CASE(both_edges_bias_pull_down, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
}
GPIOD_TEST_CASE(both_edges_bias_pull_up, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -292,6 +395,10 @@ GPIOD_TEST_CASE(both_edges_bias_pull_up, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -303,29 +410,40 @@ GPIOD_TEST_CASE(both_edges_bias_pull_up, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
}
GPIOD_TEST_CASE(falling_edge_active_low, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -333,6 +451,10 @@ GPIOD_TEST_CASE(falling_edge_active_low, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -344,21 +466,27 @@ GPIOD_TEST_CASE(falling_edge_active_low, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
}
GPIOD_TEST_CASE(get_value, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -366,6 +494,10 @@ GPIOD_TEST_CASE(get_value, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -381,21 +513,27 @@ GPIOD_TEST_CASE(get_value, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
}
GPIOD_TEST_CASE(get_value_active_low, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
@@ -403,6 +541,10 @@ GPIOD_TEST_CASE(get_value_active_low, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -419,13 +561,18 @@ GPIOD_TEST_CASE(get_value_active_low, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 7, 100);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
}
GPIOD_TEST_CASE(get_values, 0, { 8 })
@@ -548,12 +695,13 @@ GPIOD_TEST_CASE(get_values_active_low, 0, { 8 })
GPIOD_TEST_CASE(wait_multiple, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(GpiodTestEventThread) ev_thread = NULL;
g_autoptr(gpiod_line_bulk_struct) ev_bulk = NULL;
g_autoptr(gpiod_line_bulk_struct) bulk = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret, i;
@@ -561,6 +709,10 @@ GPIOD_TEST_CASE(wait_multiple, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
bulk = gpiod_line_bulk_new(8);
ev_bulk = gpiod_line_bulk_new(8);
g_assert_nonnull(bulk);
@@ -582,17 +734,23 @@ GPIOD_TEST_CASE(wait_multiple, 0, { 8 })
ev_thread = gpiod_test_start_event_thread(0, 4, 100);
- ret = gpiod_line_event_wait_bulk(bulk, &ts, ev_bulk);
+ ret = gpiod_line_event_wait_bulk(bulk, timeout, ev_bulk);
g_assert_cmpint(ret, ==, 1);
g_assert_cmpuint(gpiod_line_bulk_num_lines(ev_bulk), ==, 1);
line = gpiod_line_bulk_get_line(ev_bulk, 0);
g_assert_cmpuint(gpiod_line_offset(line), ==, 4);
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
- g_assert_cmpint(ev.offset, ==, 4);
+
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
+ g_assert_cmpint(gpiod_line_event_get_line_offset(event), ==, 4);
}
GPIOD_TEST_CASE(get_fd_when_values_requested, 0, { 8 })
@@ -659,7 +817,7 @@ GPIOD_TEST_CASE(invalid_fd, 0, { 8 })
g_autoptr(gpiod_line_bulk_struct) ev_bulk = NULL;
g_autoptr(gpiod_line_bulk_struct) bulk = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
+ uint64_t timeout = gpiod_sec_to_nsec(1);
struct gpiod_line *line;
gint ret, fd;
@@ -678,7 +836,7 @@ GPIOD_TEST_CASE(invalid_fd, 0, { 8 })
fd = gpiod_line_event_get_fd(line);
close(fd);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, -1);
g_assert_cmpint(errno, ==, EINVAL);
@@ -693,16 +851,17 @@ GPIOD_TEST_CASE(invalid_fd, 0, { 8 })
* as well.
*/
gpiod_line_bulk_add_line(bulk, line);
- ret = gpiod_line_event_wait_bulk(bulk, &ts, ev_bulk);
+ ret = gpiod_line_event_wait_bulk(bulk, timeout, ev_bulk);
g_assert_cmpint(ret, ==, -1);
g_assert_cmpint(errno, ==, EINVAL);
}
GPIOD_TEST_CASE(read_events_individually, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct timespec ts = { 1, 0 };
- struct gpiod_line_event ev;
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *event;
struct gpiod_line *line;
gint ret;
guint i;
@@ -711,6 +870,10 @@ GPIOD_TEST_CASE(read_events_individually, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(1);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 7);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -727,45 +890,61 @@ GPIOD_TEST_CASE(read_events_individually, 0, { 8 })
}
/* read them individually... */
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
if (!ret)
return;
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
if (!ret)
return;
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_RISING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
if (!ret)
return;
- ret = gpiod_line_event_read(line, &ev);
+ ret = gpiod_line_event_read(line, event_buf);
g_assert_cmpint(ret, ==, 0);
- g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE);
+ event = gpiod_line_event_buffer_get_event(event_buf, 0);
+ g_assert_nonnull(event);
+ gpiod_test_return_if_failed();
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(event), ==,
+ GPIOD_LINE_EVENT_FALLING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 0);
}
GPIOD_TEST_CASE(read_multiple_events, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct gpiod_line_event events[5];
- struct timespec ts = { 1, 0 };
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *events[4];
struct gpiod_line *line;
gint ret;
guint i;
@@ -774,6 +953,10 @@ GPIOD_TEST_CASE(read_multiple_events, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(5);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 4);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -795,23 +978,30 @@ GPIOD_TEST_CASE(read_multiple_events, 0, { 8 })
usleep(10000);
}
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
if (!ret)
return;
/* read a chunk */
- ret = gpiod_line_event_read_multiple(line, events, 3);
+ ret = gpiod_line_event_read_multiple(line, event_buf, 3);
g_assert_cmpint(ret, ==, 3);
- g_assert_cmpint(events[0].event_type, ==,
+ events[0] = gpiod_line_event_buffer_get_event(event_buf, 0);
+ events[1] = gpiod_line_event_buffer_get_event(event_buf, 1);
+ events[2] = gpiod_line_event_buffer_get_event(event_buf, 2);
+ g_assert_nonnull(events[0]);
+ g_assert_nonnull(events[1]);
+ g_assert_nonnull(events[2]);
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[0]), ==,
GPIOD_LINE_EVENT_RISING_EDGE);
- g_assert_cmpint(events[1].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[1]), ==,
GPIOD_LINE_EVENT_FALLING_EDGE);
- g_assert_cmpint(events[2].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[2]), ==,
GPIOD_LINE_EVENT_RISING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
if (!ret)
return;
@@ -820,27 +1010,37 @@ GPIOD_TEST_CASE(read_multiple_events, 0, { 8 })
* read the remainder
* - note the attempt to read more than are available
*/
- ret = gpiod_line_event_read_multiple(line, events, 5);
+ ret = gpiod_line_event_read_multiple(line, event_buf, 5);
g_assert_cmpint(ret, ==, 4);
- g_assert_cmpint(events[0].event_type, ==,
+ events[0] = gpiod_line_event_buffer_get_event(event_buf, 0);
+ events[1] = gpiod_line_event_buffer_get_event(event_buf, 1);
+ events[2] = gpiod_line_event_buffer_get_event(event_buf, 2);
+ events[3] = gpiod_line_event_buffer_get_event(event_buf, 3);
+ g_assert_nonnull(events[0]);
+ g_assert_nonnull(events[1]);
+ g_assert_nonnull(events[2]);
+ g_assert_nonnull(events[3]);
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[0]), ==,
GPIOD_LINE_EVENT_FALLING_EDGE);
- g_assert_cmpint(events[1].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[1]), ==,
GPIOD_LINE_EVENT_RISING_EDGE);
- g_assert_cmpint(events[2].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[2]), ==,
GPIOD_LINE_EVENT_FALLING_EDGE);
- g_assert_cmpint(events[3].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[3]), ==,
GPIOD_LINE_EVENT_RISING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 0);
}
GPIOD_TEST_CASE(read_multiple_events_fd, 0, { 8 })
{
+ g_autoptr(gpiod_line_event_buffer_struct) event_buf = NULL;
g_autoptr(gpiod_chip_struct) chip = NULL;
- struct gpiod_line_event events[5];
- struct timespec ts = { 1, 0 };
+ uint64_t timeout = gpiod_sec_to_nsec(1);
+ struct gpiod_line_event *events[4];
struct gpiod_line *line;
gint ret, fd;
guint i;
@@ -849,6 +1049,10 @@ GPIOD_TEST_CASE(read_multiple_events_fd, 0, { 8 })
g_assert_nonnull(chip);
gpiod_test_return_if_failed();
+ event_buf = gpiod_line_event_buffer_new(5);
+ g_assert_nonnull(event_buf);
+ gpiod_test_return_if_failed();
+
line = gpiod_chip_get_line(chip, 4);
g_assert_nonnull(line);
gpiod_test_return_if_failed();
@@ -863,7 +1067,7 @@ GPIOD_TEST_CASE(read_multiple_events_fd, 0, { 8 })
usleep(10000);
}
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
if (!ret)
return;
@@ -872,17 +1076,24 @@ GPIOD_TEST_CASE(read_multiple_events_fd, 0, { 8 })
g_assert_cmpint(fd, >=, 0);
/* read a chunk */
- ret = gpiod_line_event_read_fd_multiple(fd, events, 3);
+ ret = gpiod_line_event_read_fd_multiple(fd, event_buf, 3);
g_assert_cmpint(ret, ==, 3);
- g_assert_cmpint(events[0].event_type, ==,
+ events[0] = gpiod_line_event_buffer_get_event(event_buf, 0);
+ events[1] = gpiod_line_event_buffer_get_event(event_buf, 1);
+ events[2] = gpiod_line_event_buffer_get_event(event_buf, 2);
+ g_assert_nonnull(events[0]);
+ g_assert_nonnull(events[1]);
+ g_assert_nonnull(events[2]);
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[0]), ==,
GPIOD_LINE_EVENT_RISING_EDGE);
- g_assert_cmpint(events[1].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[1]), ==,
GPIOD_LINE_EVENT_FALLING_EDGE);
- g_assert_cmpint(events[2].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[2]), ==,
GPIOD_LINE_EVENT_RISING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 1);
if (!ret)
return;
@@ -891,18 +1102,27 @@ GPIOD_TEST_CASE(read_multiple_events_fd, 0, { 8 })
* read the remainder
* - note the attempt to read more than are available
*/
- ret = gpiod_line_event_read_fd_multiple(fd, events, 5);
+ ret = gpiod_line_event_read_fd_multiple(fd, event_buf, 5);
g_assert_cmpint(ret, ==, 4);
- g_assert_cmpint(events[0].event_type, ==,
+ events[0] = gpiod_line_event_buffer_get_event(event_buf, 0);
+ events[1] = gpiod_line_event_buffer_get_event(event_buf, 1);
+ events[2] = gpiod_line_event_buffer_get_event(event_buf, 2);
+ events[3] = gpiod_line_event_buffer_get_event(event_buf, 3);
+ g_assert_nonnull(events[0]);
+ g_assert_nonnull(events[1]);
+ g_assert_nonnull(events[2]);
+ g_assert_nonnull(events[3]);
+
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[0]), ==,
GPIOD_LINE_EVENT_FALLING_EDGE);
- g_assert_cmpint(events[1].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[1]), ==,
GPIOD_LINE_EVENT_RISING_EDGE);
- g_assert_cmpint(events[2].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[2]), ==,
GPIOD_LINE_EVENT_FALLING_EDGE);
- g_assert_cmpint(events[3].event_type, ==,
+ g_assert_cmpint(gpiod_line_event_get_event_type(events[3]), ==,
GPIOD_LINE_EVENT_RISING_EDGE);
- ret = gpiod_line_event_wait(line, &ts);
+ ret = gpiod_line_event_wait(line, timeout);
g_assert_cmpint(ret, ==, 0);
}
@@ -13,6 +13,8 @@
#include "tools-common.h"
+#define EVENT_BUF_SIZE 32
+
static const struct option longopts[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
@@ -64,10 +66,8 @@ struct mon_ctx {
char *fmt;
};
-static void event_print_custom(unsigned int offset,
- const struct timespec *ts,
- int event_type,
- struct mon_ctx *ctx)
+static void event_print_custom(unsigned int offset, uint64_t timeout,
+ int event_type, struct mon_ctx *ctx)
{
char *prev, *curr, fmt;
@@ -94,10 +94,10 @@ static void event_print_custom(unsigned int offset,
fputc('0', stdout);
break;
case 's':
- printf("%ld", ts->tv_sec);
+ printf("%ld", timeout / 1000000000);
break;
case 'n':
- printf("%ld", ts->tv_nsec);
+ printf("%ld", timeout % 1000000000);
break;
case '%':
fputc('%', stdout);
@@ -119,8 +119,7 @@ end:
}
static void event_print_human_readable(unsigned int offset,
- const struct timespec *ts,
- int event_type)
+ uint64_t timeout, int event_type)
{
char *evname;
@@ -130,11 +129,11 @@ static void event_print_human_readable(unsigned int offset,
evname = "FALLING EDGE";
printf("event: %s offset: %u timestamp: [%8ld.%09ld]\n",
- evname, offset, ts->tv_sec, ts->tv_nsec);
+ evname, offset, timeout / 1000000000, timeout % 1000000000);
}
static void handle_event(unsigned int line_offset, unsigned int event_type,
- struct timespec *timestamp, struct mon_ctx *ctx)
+ uint64_t timestamp, struct mon_ctx *ctx)
{
if (!ctx->silent) {
if (ctx->fmt)
@@ -156,8 +155,8 @@ int main(int argc, char **argv)
unsigned int offsets[64], num_lines = 0, offset,
events_wanted = 0, events_done = 0, x;
bool watch_rising = false, watch_falling = false;
+ uint64_t timeout = gpiod_sec_to_nsec(10);
int flags = 0;
- struct timespec timeout = { 10, 0 };
int optc, opti, rv, i, y, event_type;
struct mon_ctx ctx;
struct gpiod_chip *chip;
@@ -165,7 +164,8 @@ int main(int argc, char **argv)
char *end;
struct gpiod_line_request_config config;
struct gpiod_line *line;
- struct gpiod_line_event events[16];
+ struct gpiod_line_event_buffer *event_buffer;
+ struct gpiod_line_event *event;
/*
* FIXME: use signalfd once the API has been converted to using a single file
@@ -271,9 +271,13 @@ int main(int argc, char **argv)
if (!evlines)
die("out of memory");
+ event_buffer = gpiod_line_event_buffer_new(EVENT_BUF_SIZE);
+ if (!event_buffer)
+ die_perror("unable to allocate the line event buffer");
+
for (;;) {
gpiod_line_bulk_reset(evlines);
- rv = gpiod_line_event_wait_bulk(lines, &timeout, evlines);
+ rv = gpiod_line_event_wait_bulk(lines, timeout, evlines);
if (rv < 0)
die_perror("error waiting for events");
if (rv == 0)
@@ -284,15 +288,22 @@ int main(int argc, char **argv)
for (x = 0; x < num_lines; x++) {
line = gpiod_line_bulk_get_line(evlines, x);
- rv = gpiod_line_event_read_multiple(line, events,
- ARRAY_SIZE(events));
+ rv = gpiod_line_event_read_multiple(line, event_buffer,
+ EVENT_BUF_SIZE);
if (rv < 0)
die_perror("error reading line events");
for (y = 0; y < rv; y++) {
+ event = gpiod_line_event_buffer_get_event(
+ event_buffer, y);
+ if (!event)
+ die_perror("unable to retrieve the event");
+
handle_event(gpiod_line_offset(line),
- events[y].event_type,
- &events[y].ts, &ctx);
+ gpiod_line_event_get_event_type(event),
+ gpiod_line_event_get_timestamp(event),
+ &ctx);
+
events_done++;
if (events_wanted &&
Introduce opaque event objects: gpiod_line_event and gpiod_line_event_buffer. The latter serves as a container into which multiple events can be read without having to dynamically allocate memory for each one as reading line events should be as fast as possible. Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> --- include/gpiod.h | 65 +++--- lib/Makefile.am | 9 +- lib/core.c | 98 +-------- lib/event.c | 250 +++++++++++++++++++++++ lib/misc.c | 5 + tests/gpiod-test.h | 3 + tests/tests-event.c | 470 ++++++++++++++++++++++++++++++++------------ tools/gpiomon.c | 45 +++-- 8 files changed, 690 insertions(+), 255 deletions(-) create mode 100644 lib/event.c