mirror of
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
synced 2026-10-24 00:48:53 +03:00
In order to allow the upcoming GLib and DBus bindings to reuse the test code, let's put all common elements into reusable libtool objects and export the relevant symbols in internal headers. Tested-by: Alexander Sverdlin <alexander.sverdlin@siemens.com> Link: https://lore.kernel.org/r/20240812-dbus-v5-1-ead288509217@linaro.org Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
685 lines
22 KiB
C
685 lines
22 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
|
|
|
|
#include <glib.h>
|
|
#include <gpiod.h>
|
|
#include <gpiod-test.h>
|
|
#include <gpiod-test-common.h>
|
|
#include <gpiosim-glib.h>
|
|
#include <poll.h>
|
|
|
|
#include "helpers.h"
|
|
|
|
#define GPIOD_TEST_GROUP "edge-event"
|
|
|
|
GPIOD_TEST_CASE(edge_event_buffer_capacity)
|
|
{
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(32);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_capacity(buffer), ==, 32);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(edge_event_buffer_max_capacity)
|
|
{
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(16 * 64 * 2);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_capacity(buffer),
|
|
==, 16 * 64);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(edge_event_wait_timeout)
|
|
{
|
|
static const guint offset = 4;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000);
|
|
g_assert_cmpint(ret, ==, 0);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(cannot_request_lines_in_output_mode_with_edge_detection)
|
|
{
|
|
static const guint offset = 4;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
gpiod_line_settings_set_direction(settings,
|
|
GPIOD_LINE_DIRECTION_OUTPUT);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_chip_request_lines(chip, NULL, line_cfg);
|
|
g_assert_null(request);
|
|
gpiod_test_expect_errno(EINVAL);
|
|
}
|
|
|
|
static gpointer falling_and_rising_edge_events(gpointer data)
|
|
{
|
|
GPIOSimChip *sim = data;
|
|
|
|
g_usleep(1000);
|
|
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
|
|
g_usleep(1000);
|
|
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_DOWN);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
GPIOD_TEST_CASE(read_both_events)
|
|
{
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(GThread) thread = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
struct gpiod_edge_event *event;
|
|
guint64 ts_rising, ts_falling;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
thread = g_thread_new("request-release",
|
|
falling_and_rising_edge_events, sim);
|
|
g_thread_ref(thread);
|
|
|
|
/* First event. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000000);
|
|
g_assert_cmpint(ret, >, 0);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpint(gpiod_edge_event_get_event_type(event), ==,
|
|
GPIOD_EDGE_EVENT_RISING_EDGE);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 2);
|
|
ts_rising = gpiod_edge_event_get_timestamp_ns(event);
|
|
|
|
/* Second event. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000000);
|
|
g_assert_cmpint(ret, >, 0);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpint(gpiod_edge_event_get_event_type(event), ==,
|
|
GPIOD_EDGE_EVENT_FALLING_EDGE);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 2);
|
|
ts_falling = gpiod_edge_event_get_timestamp_ns(event);
|
|
|
|
g_thread_join(thread);
|
|
|
|
g_assert_cmpuint(ts_falling, >, ts_rising);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(read_rising_edge_event)
|
|
{
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(GThread) thread = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
struct gpiod_edge_event *event;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings,
|
|
GPIOD_LINE_EDGE_RISING);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
thread = g_thread_new("edge-generator",
|
|
falling_and_rising_edge_events, sim);
|
|
g_thread_ref(thread);
|
|
|
|
/* First event. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000000);
|
|
g_assert_cmpint(ret, >, 0);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpint(gpiod_edge_event_get_event_type(event), ==,
|
|
GPIOD_EDGE_EVENT_RISING_EDGE);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 2);
|
|
|
|
/* Second event. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000);
|
|
g_assert_cmpint(ret, ==, 0); /* Time-out. */
|
|
|
|
g_thread_join(thread);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(read_falling_edge_event)
|
|
{
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(GThread) thread = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
struct gpiod_edge_event *event;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings,
|
|
GPIOD_LINE_EDGE_FALLING);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
thread = g_thread_new("request-release",
|
|
falling_and_rising_edge_events, sim);
|
|
g_thread_ref(thread);
|
|
|
|
/* First event is the second generated. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000000);
|
|
g_assert_cmpint(ret, >, 0);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpint(gpiod_edge_event_get_event_type(event), ==,
|
|
GPIOD_EDGE_EVENT_FALLING_EDGE);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 2);
|
|
|
|
/* No more events. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000);
|
|
g_assert_cmpint(ret, ==, 0); /* Time-out. */
|
|
|
|
g_thread_join(thread);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(read_rising_edge_event_polled)
|
|
{
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(GThread) thread = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
struct gpiod_edge_event *event;
|
|
struct timespec ts;
|
|
struct pollfd pfd;
|
|
gint ret, fd;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings,
|
|
GPIOD_LINE_EDGE_RISING);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
thread = g_thread_new("edge-generator",
|
|
falling_and_rising_edge_events, sim);
|
|
g_thread_ref(thread);
|
|
|
|
/* First event. */
|
|
|
|
fd = gpiod_line_request_get_fd(request);
|
|
|
|
memset(&pfd, 0, sizeof(pfd));
|
|
pfd.fd = fd;
|
|
pfd.events = POLLIN | POLLPRI;
|
|
|
|
ts.tv_sec = 1;
|
|
ts.tv_nsec = 0;
|
|
|
|
ret = ppoll(&pfd, 1, &ts, NULL);
|
|
g_assert_cmpint(ret, >, 0);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpint(gpiod_edge_event_get_event_type(event), ==,
|
|
GPIOD_EDGE_EVENT_RISING_EDGE);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 2);
|
|
|
|
/* Second event. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000);
|
|
g_assert_cmpint(ret, ==, 0); /* Time-out. */
|
|
|
|
g_thread_join(thread);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(read_both_events_blocking)
|
|
{
|
|
/*
|
|
* This time without polling so that the read gets a chance to block
|
|
* and we can make sure it doesn't immediately return an error.
|
|
*/
|
|
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(GThread) thread = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
struct gpiod_edge_event *event;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
thread = g_thread_new("request-release",
|
|
falling_and_rising_edge_events, sim);
|
|
g_thread_ref(thread);
|
|
|
|
/* First event. */
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpint(gpiod_edge_event_get_event_type(event), ==,
|
|
GPIOD_EDGE_EVENT_RISING_EDGE);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 2);
|
|
|
|
/* Second event. */
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpint(gpiod_edge_event_get_event_type(event), ==,
|
|
GPIOD_EDGE_EVENT_FALLING_EDGE);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 2);
|
|
|
|
g_thread_join(thread);
|
|
}
|
|
|
|
static gpointer rising_edge_events_on_two_offsets(gpointer data)
|
|
{
|
|
GPIOSimChip *sim = data;
|
|
|
|
g_usleep(1000);
|
|
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
|
|
g_usleep(1000);
|
|
|
|
g_gpiosim_chip_set_pull(sim, 3, G_GPIOSIM_PULL_UP);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
GPIOD_TEST_CASE(seqno)
|
|
{
|
|
static const guint offsets[] = { 2, 3 };
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(GThread) thread = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
struct gpiod_edge_event *event;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, offsets, 2,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
thread = g_thread_new("request-release",
|
|
rising_edge_events_on_two_offsets, sim);
|
|
g_thread_ref(thread);
|
|
|
|
/* First event. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000000);
|
|
g_assert_cmpint(ret, >, 0);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 2);
|
|
g_assert_cmpuint(gpiod_edge_event_get_global_seqno(event), ==, 1);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_seqno(event), ==, 1);
|
|
|
|
/* Second event. */
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000000);
|
|
g_assert_cmpint(ret, >, 0);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_buffer_get_num_events(buffer), ==, 1);
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_join_thread_and_return_if_failed(thread);
|
|
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_offset(event), ==, 3);
|
|
g_assert_cmpuint(gpiod_edge_event_get_global_seqno(event), ==, 2);
|
|
g_assert_cmpuint(gpiod_edge_event_get_line_seqno(event), ==, 1);
|
|
|
|
g_thread_join(thread);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(event_copy)
|
|
{
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
g_autoptr(struct_gpiod_edge_event) copy = NULL;
|
|
struct gpiod_edge_event *event;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000000000);
|
|
g_assert_cmpint(ret, >, 0);
|
|
gpiod_test_return_if_failed();
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 1);
|
|
g_assert_cmpint(ret, ==, 1);
|
|
gpiod_test_return_if_failed();
|
|
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 0);
|
|
g_assert_nonnull(event);
|
|
gpiod_test_return_if_failed();
|
|
|
|
copy = gpiod_edge_event_copy(event);
|
|
g_assert_nonnull(copy);
|
|
g_assert_true(copy != event);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(reading_more_events_than_the_queue_contains_doesnt_block)
|
|
{
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
g_usleep(500);
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_DOWN);
|
|
g_usleep(500);
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
g_usleep(500);
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_DOWN);
|
|
g_usleep(500);
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
g_usleep(500);
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_DOWN);
|
|
g_usleep(500);
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
g_usleep(500);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 12);
|
|
g_assert_cmpint(ret, ==, 7);
|
|
gpiod_test_return_if_failed();
|
|
|
|
ret = gpiod_line_request_wait_edge_events(request, 1000);
|
|
g_assert_cmpint(ret, ==, 0);
|
|
gpiod_test_return_if_failed();
|
|
}
|
|
|
|
GPIOD_TEST_CASE(null_buffer)
|
|
{
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, NULL, 1);
|
|
g_assert_cmpint(ret, ==, -1);
|
|
gpiod_test_expect_errno(EINVAL);
|
|
}
|
|
|
|
GPIOD_TEST_CASE(get_edge_event_index_out_of_bounds)
|
|
{
|
|
static const guint offset = 2;
|
|
|
|
g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
|
|
g_autoptr(struct_gpiod_chip) chip = NULL;
|
|
g_autoptr(struct_gpiod_line_settings) settings = NULL;
|
|
g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
|
|
g_autoptr(struct_gpiod_line_request) request = NULL;
|
|
g_autoptr(struct_gpiod_edge_event_buffer) buffer = NULL;
|
|
struct gpiod_edge_event *event;
|
|
gint ret;
|
|
|
|
chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
|
|
settings = gpiod_test_create_line_settings_or_fail();
|
|
line_cfg = gpiod_test_create_line_config_or_fail();
|
|
buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
|
|
|
|
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
|
|
gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
|
|
|
|
gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1,
|
|
settings);
|
|
|
|
request = gpiod_test_chip_request_lines_or_fail(chip, NULL, line_cfg);
|
|
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
g_usleep(500);
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_DOWN);
|
|
g_usleep(500);
|
|
g_gpiosim_chip_set_pull(sim, 2, G_GPIOSIM_PULL_UP);
|
|
g_usleep(500);
|
|
|
|
ret = gpiod_line_request_read_edge_events(request, buffer, 3);
|
|
g_assert_cmpint(ret, ==, 3);
|
|
gpiod_test_return_if_failed();
|
|
|
|
event = gpiod_edge_event_buffer_get_event(buffer, 5);
|
|
g_assert_null(event);
|
|
gpiod_test_expect_errno(EINVAL);
|
|
}
|