diff mbox series

[libgpiod,v2] chip: don't set the request's file descriptor to non-blocking

Message ID 20220426114850.2593123-1-brgl@bgdev.pl
State New
Headers show
Series [libgpiod,v2] chip: don't set the request's file descriptor to non-blocking | expand

Commit Message

Bartosz Golaszewski April 26, 2022, 11:48 a.m. UTC
Make the behavior consistent with the documentation and don't set the
line request's fd to non-blocking. Add two more test-cases that make
sure the library behaves correctly.

Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
---
 lib/chip.c               |  23 --------
 tests/tests-edge-event.c | 119 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+), 23 deletions(-)
diff mbox series

Patch

diff --git a/lib/chip.c b/lib/chip.c
index eef3be2..fc3dda2 100644
--- a/lib/chip.c
+++ b/lib/chip.c
@@ -181,23 +181,6 @@  GPIOD_API int gpiod_chip_get_line_offset_from_name(struct gpiod_chip *chip,
 	return -1;
 }
 
-static int set_fd_noblock(int fd)
-{
-	int ret, flags;
-
-	flags = fcntl(fd, F_GETFL, 0);
-	if (flags < 0)
-		return -1;
-
-	flags |= O_NONBLOCK;
-
-	ret = fcntl(fd, F_SETFL, flags);
-	if (ret < 0)
-		return -1;
-
-	return 0;
-}
-
 GPIOD_API struct gpiod_line_request *
 gpiod_chip_request_lines(struct gpiod_chip *chip,
 			 struct gpiod_request_config *req_cfg,
@@ -222,12 +205,6 @@  gpiod_chip_request_lines(struct gpiod_chip *chip,
 	if (ret < 0)
 		return NULL;
 
-	ret = set_fd_noblock(uapi_req.fd);
-	if (ret) {
-		close(uapi_req.fd);
-		return NULL;
-	}
-
 	request = gpiod_line_request_from_uapi(&uapi_req);
 	if (!request) {
 		close(uapi_req.fd);
diff --git a/tests/tests-edge-event.c b/tests/tests-edge-event.c
index 306383f..987155f 100644
--- a/tests/tests-edge-event.c
+++ b/tests/tests-edge-event.c
@@ -357,6 +357,75 @@  GPIOD_TEST_CASE(read_rising_edge_event_polled)
 	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_request_config) req_cfg = 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));
+	req_cfg = gpiod_test_create_request_config_or_fail();
+	line_cfg = gpiod_test_create_line_config_or_fail();
+	buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
+
+	gpiod_request_config_set_offsets(req_cfg, 1, &offset);
+	gpiod_line_config_set_direction_default(line_cfg,
+						GPIOD_LINE_DIRECTION_INPUT);
+	gpiod_line_config_set_edge_detection_default(line_cfg,
+						     GPIOD_LINE_EDGE_BOTH);
+
+	request = gpiod_test_request_lines_or_fail(chip, req_cfg, 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_event(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_event(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;
@@ -488,3 +557,53 @@  GPIOD_TEST_CASE(event_copy)
 	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_request_config) req_cfg = 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;
+	gint ret;
+
+	chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
+	req_cfg = gpiod_test_create_request_config_or_fail();
+	line_cfg = gpiod_test_create_line_config_or_fail();
+	buffer = gpiod_test_create_edge_event_buffer_or_fail(64);
+
+	gpiod_request_config_set_offsets(req_cfg, 1, &offset);
+	gpiod_line_config_set_direction_default(line_cfg,
+						GPIOD_LINE_DIRECTION_INPUT);
+	gpiod_line_config_set_edge_detection_default(line_cfg,
+						     GPIOD_LINE_EDGE_BOTH);
+
+	request = gpiod_test_request_lines_or_fail(chip, req_cfg, 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_event(request, buffer, 12);
+	g_assert_cmpint(ret, ==, 7);
+	gpiod_test_return_if_failed();
+
+	ret = gpiod_line_request_wait_edge_event(request, 1000);
+	g_assert_cmpint(ret, ==, 0);
+	gpiod_test_return_if_failed();
+}