From: Kent Gibson <warthog618@gmail.com>
To: linux-gpio@vger.kernel.org, brgl@bgdev.pl
Cc: Kent Gibson <warthog618@gmail.com>
Subject: [libgpiod][PATCH 1/4] core: examples: add dedicated examples
Date: Wed, 14 Jun 2023 11:54:23 +0800 [thread overview]
Message-ID: <20230614035426.15097-2-warthog618@gmail.com> (raw)
In-Reply-To: <20230614035426.15097-1-warthog618@gmail.com>
The tools have served as example code, but have become too complicated
to serve that purpose.
Add a set of examples that have no purpose other than providing minimal
examples of common use cases.
Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
Makefile.am | 6 ++
configure.ac | 1 +
examples/.gitignore | 7 ++
examples/Makefile.am | 17 ++++
examples/async_watch_line_value.c | 136 ++++++++++++++++++++++++++++++
examples/get_line_value.c | 97 +++++++++++++++++++++
examples/toggle_line_value.c | 106 +++++++++++++++++++++++
examples/watch_line_value.c | 127 ++++++++++++++++++++++++++++
8 files changed, 497 insertions(+)
create mode 100644 examples/.gitignore
create mode 100644 examples/Makefile.am
create mode 100644 examples/async_watch_line_value.c
create mode 100644 examples/get_line_value.c
create mode 100644 examples/toggle_line_value.c
create mode 100644 examples/watch_line_value.c
diff --git a/Makefile.am b/Makefile.am
index 10d6a9a..941d7e8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,6 +16,12 @@ EXTRA_DIST = \
LICENSES/LGPL-3.0-or-later.txt \
LICENSES/BSD-3-Clause.txt
+if WITH_EXAMPLES
+
+SUBDIRS += examples
+
+endif
+
if WITH_TOOLS
SUBDIRS += tools man
diff --git a/configure.ac b/configure.ac
index c1005a9..dde2fa5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -268,6 +268,7 @@ AC_CONFIG_FILES([Makefile
lib/Makefile
lib/libgpiod.pc
contrib/Makefile
+ examples/Makefile
tools/Makefile
tests/Makefile
tests/gpiosim/Makefile
diff --git a/examples/.gitignore b/examples/.gitignore
new file mode 100644
index 0000000..bdfde9a
--- /dev/null
+++ b/examples/.gitignore
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+async_watch_line_value
+get_line_value
+toggle_line_value
+watch_line_value
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..4ad124b
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+AM_CFLAGS = -I$(top_srcdir)/include/ -include $(top_builddir)/config.h
+AM_CFLAGS += -Wall -Wextra -g -std=gnu89
+
+LDADD = $(top_builddir)/lib/libgpiod.la
+
+bin_PROGRAMS = async_watch_line_value get_line_value toggle_line_value watch_line_value
+
+async_watch_line_value_SOURCES = async_watch_line_value.c
+
+get_line_value_SOURCES = get_line_value.c
+
+toggle_line_valuer_SOURCES = toggle_line_value.c
+
+watch_line_value_SOURCES = watch_line_value.c
diff --git a/examples/async_watch_line_value.c b/examples/async_watch_line_value.c
new file mode 100644
index 0000000..de15c97
--- /dev/null
+++ b/examples/async_watch_line_value.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of asynchronously watching for edges on a single line */
+
+#include <errno.h>
+#include <gpiod.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* request a line as input with edge detection */
+struct gpiod_line_request *request_input_line(const char *chip_path,
+ unsigned int offset,
+ const char *consumer)
+{
+ struct gpiod_line_settings *settings;
+ struct gpiod_line_request *request = NULL;
+ struct gpiod_request_config *req_cfg = NULL;
+ struct gpiod_line_config *line_cfg;
+ struct gpiod_chip *chip;
+ int ret;
+
+ chip = gpiod_chip_open(chip_path);
+ if (!chip)
+ return NULL;
+
+ settings = gpiod_line_settings_new();
+ if (!settings)
+ goto close_chip;
+
+ gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
+ gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
+ /* assume a button connecting the pin to ground, so pull it up... */
+ gpiod_line_settings_set_bias(settings, GPIOD_LINE_BIAS_PULL_UP);
+ /* ... and provide some debounce. */
+ gpiod_line_settings_set_debounce_period_us(settings, 10000);
+
+ line_cfg = gpiod_line_config_new();
+ if (!line_cfg)
+ goto free_settings;
+
+ ret = gpiod_line_config_add_line_settings(line_cfg, &offset, 1,
+ settings);
+ if (ret)
+ goto free_line_config;
+
+ if (consumer) {
+ req_cfg = gpiod_request_config_new();
+ if (!req_cfg)
+ goto free_line_config;
+
+ gpiod_request_config_set_consumer(req_cfg, consumer);
+ }
+
+ request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+
+ gpiod_request_config_free(req_cfg);
+free_line_config:
+ gpiod_line_config_free(line_cfg);
+free_settings:
+ gpiod_line_settings_free(settings);
+close_chip:
+ gpiod_chip_close(chip);
+
+ return request;
+}
+
+const char *edge_event_type_str(struct gpiod_edge_event *event)
+{
+ enum gpiod_edge_event_type eet = gpiod_edge_event_get_event_type(event);
+
+ if (eet == GPIOD_EDGE_EVENT_RISING_EDGE)
+ return "Rising ";
+ if (eet == GPIOD_EDGE_EVENT_FALLING_EDGE)
+ return "Falling";
+ return "Unknown";
+}
+
+int main(void)
+{
+ struct gpiod_line_request *request;
+ struct gpiod_edge_event_buffer *event_buffer;
+ struct gpiod_edge_event *event;
+ struct pollfd pollfd;
+ int i, ret, event_buf_size;
+ /* example configuration - customize to suit your situation */
+ const char *chip_path = "/dev/gpiochip0";
+ int line_offset = 5;
+
+ request = request_input_line(chip_path, line_offset,
+ "async-watch-line-value");
+ if (!request) {
+ fprintf(stderr, "failed to request line: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ /* a larger buffer is an optimisation for reading bursts of events from
+ * the kernel, but that is not necessary in this case, so 1 is fine.
+ */
+ event_buf_size = 1;
+ event_buffer = gpiod_edge_event_buffer_new(event_buf_size);
+ if (!event_buffer) {
+ fprintf(stderr, "failed to create event buffer: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ pollfd.fd = gpiod_line_request_get_fd(request);
+ pollfd.events = POLLIN;
+ while (1) {
+ ret = poll(&pollfd, 1, -1);
+ if (ret == -1) {
+ fprintf(stderr, "error waiting for edge events: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+ ret = gpiod_line_request_read_edge_events(request, event_buffer,
+ event_buf_size);
+ if (ret == -1) {
+ fprintf(stderr, "error reading edge events: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+ for (i = 0; i < ret; i++) {
+ event = gpiod_edge_event_buffer_get_event(event_buffer,
+ i);
+ printf("offset: %d, type: %s, event #%ld\n",
+ gpiod_edge_event_get_line_offset(event),
+ edge_event_type_str(event),
+ gpiod_edge_event_get_line_seqno(event));
+ }
+ }
+}
diff --git a/examples/get_line_value.c b/examples/get_line_value.c
new file mode 100644
index 0000000..fc96a5b
--- /dev/null
+++ b/examples/get_line_value.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of reading a single line. */
+
+#include <errno.h>
+#include <gpiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* request a line as input */
+struct gpiod_line_request *request_input_line(const char *chip_path,
+ unsigned int offset,
+ const char *consumer)
+{
+ struct gpiod_line_settings *settings;
+ struct gpiod_line_request *request = NULL;
+ struct gpiod_request_config *req_cfg = NULL;
+ struct gpiod_line_config *line_cfg;
+ struct gpiod_chip *chip;
+ int ret;
+
+ chip = gpiod_chip_open(chip_path);
+ if (!chip)
+ return NULL;
+
+ settings = gpiod_line_settings_new();
+ if (!settings)
+ goto close_chip;
+
+ gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
+
+ line_cfg = gpiod_line_config_new();
+ if (!line_cfg)
+ goto free_settings;
+
+ ret = gpiod_line_config_add_line_settings(line_cfg, &offset, 1,
+ settings);
+ if (ret)
+ goto free_line_config;
+
+ if (consumer) {
+ req_cfg = gpiod_request_config_new();
+ if (!req_cfg)
+ goto free_line_config;
+
+ gpiod_request_config_set_consumer(req_cfg, consumer);
+ }
+
+ request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+
+ gpiod_request_config_free(req_cfg);
+free_line_config:
+ gpiod_line_config_free(line_cfg);
+free_settings:
+ gpiod_line_settings_free(settings);
+close_chip:
+ gpiod_chip_close(chip);
+
+ return request;
+}
+
+int print_value(enum gpiod_line_value value)
+{
+ if (value == GPIOD_LINE_VALUE_ACTIVE)
+ printf("Active\n");
+ else if (value == GPIOD_LINE_VALUE_INACTIVE) {
+ printf("Inactive\n");
+ } else {
+ fprintf(stderr, "error reading value: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+int main(void)
+{
+ struct gpiod_line_request *request;
+ enum gpiod_line_value value;
+ int ret;
+ /* example configuration - customize to suit your situation */
+ const char *chip_path = "/dev/gpiochip0";
+ int line_offset = 5;
+
+ request = request_input_line(chip_path, line_offset, "get-line-value");
+ if (!request) {
+ fprintf(stderr, "failed to request line: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ value = gpiod_line_request_get_value(request, line_offset);
+ ret = print_value(value);
+ return ret;
+}
diff --git a/examples/toggle_line_value.c b/examples/toggle_line_value.c
new file mode 100644
index 0000000..ada163e
--- /dev/null
+++ b/examples/toggle_line_value.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of toggling a single line. */
+
+#include <errno.h>
+#include <gpiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct gpiod_line_request *request_output_line(const char *chip_path,
+ unsigned int offset,
+ enum gpiod_line_value value,
+ const char *consumer)
+{
+ struct gpiod_line_settings *settings;
+ struct gpiod_line_request *request = NULL;
+ struct gpiod_request_config *req_cfg = NULL;
+ struct gpiod_line_config *line_cfg;
+ struct gpiod_chip *chip;
+ int ret;
+
+ chip = gpiod_chip_open(chip_path);
+ if (!chip)
+ return NULL;
+
+ settings = gpiod_line_settings_new();
+ if (!settings)
+ goto close_chip;
+
+ gpiod_line_settings_set_direction(settings,
+ GPIOD_LINE_DIRECTION_OUTPUT);
+ gpiod_line_settings_set_output_value(settings, value);
+
+ line_cfg = gpiod_line_config_new();
+ if (!line_cfg)
+ goto free_settings;
+
+ ret = gpiod_line_config_add_line_settings(line_cfg, &offset, 1,
+ settings);
+ if (ret)
+ goto free_settings;
+
+ if (consumer) {
+ req_cfg = gpiod_request_config_new();
+ if (!req_cfg)
+ goto free_line_config;
+
+ gpiod_request_config_set_consumer(req_cfg, consumer);
+ }
+
+ request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+
+ gpiod_request_config_free(req_cfg);
+free_line_config:
+ gpiod_line_config_free(line_cfg);
+free_settings:
+ gpiod_line_settings_free(settings);
+close_chip:
+ gpiod_chip_close(chip);
+
+ return request;
+}
+
+enum gpiod_line_value toggle_line_value(enum gpiod_line_value value)
+{
+ return (value == GPIOD_LINE_VALUE_ACTIVE) ? GPIOD_LINE_VALUE_INACTIVE :
+ GPIOD_LINE_VALUE_ACTIVE;
+}
+
+void print_value(enum gpiod_line_value value)
+{
+ if (value == GPIOD_LINE_VALUE_ACTIVE)
+ printf("Active\n");
+ else
+ printf("Inactive\n");
+}
+
+int main(void)
+{
+ struct gpiod_line_request *request;
+ enum gpiod_line_value value = GPIOD_LINE_VALUE_ACTIVE;
+ /* example configuration - customize to suit your situation */
+ const char *chip_path = "/dev/gpiochip0";
+ int line_offset = 5;
+
+ request = request_output_line(chip_path, line_offset, value,
+ "toggle-line-value");
+ if (!request) {
+ fprintf(stderr, "failed to request line: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ while (1) {
+ print_value(value);
+ sleep(1);
+ value = toggle_line_value(value);
+ gpiod_line_request_set_value(request, line_offset, value);
+ }
+
+ gpiod_line_request_release(request);
+ return EXIT_SUCCESS;
+}
diff --git a/examples/watch_line_value.c b/examples/watch_line_value.c
new file mode 100644
index 0000000..011943e
--- /dev/null
+++ b/examples/watch_line_value.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of watching for edges on a single line. */
+
+#include <errno.h>
+#include <gpiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* request a line as input with edge detection */
+struct gpiod_line_request *request_input_line(const char *chip_path,
+ unsigned int offset,
+ const char *consumer)
+{
+ struct gpiod_line_settings *settings;
+ struct gpiod_line_request *request = NULL;
+ struct gpiod_request_config *req_cfg = NULL;
+ struct gpiod_line_config *line_cfg;
+ struct gpiod_chip *chip;
+ int ret;
+
+ chip = gpiod_chip_open(chip_path);
+ if (!chip)
+ return NULL;
+
+ settings = gpiod_line_settings_new();
+ if (!settings)
+ goto close_chip;
+
+ gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
+ gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);
+ /* assume a button connecting the pin to ground, so pull it up... */
+ gpiod_line_settings_set_bias(settings, GPIOD_LINE_BIAS_PULL_UP);
+ /* ... and provide some debounce. */
+ gpiod_line_settings_set_debounce_period_us(settings, 10000);
+
+ line_cfg = gpiod_line_config_new();
+ if (!line_cfg)
+ goto free_settings;
+
+ ret = gpiod_line_config_add_line_settings(line_cfg, &offset, 1,
+ settings);
+ if (ret)
+ goto free_line_config;
+
+ if (consumer) {
+ req_cfg = gpiod_request_config_new();
+ if (!req_cfg)
+ goto free_line_config;
+
+ gpiod_request_config_set_consumer(req_cfg, consumer);
+ }
+
+ request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+
+ gpiod_request_config_free(req_cfg);
+free_line_config:
+ gpiod_line_config_free(line_cfg);
+free_settings:
+ gpiod_line_settings_free(settings);
+close_chip:
+ gpiod_chip_close(chip);
+
+ return request;
+}
+
+const char *edge_event_type_str(struct gpiod_edge_event *event)
+{
+ enum gpiod_edge_event_type eet = gpiod_edge_event_get_event_type(event);
+
+ if (eet == GPIOD_EDGE_EVENT_RISING_EDGE)
+ return "Rising ";
+ if (eet == GPIOD_EDGE_EVENT_FALLING_EDGE)
+ return "Falling";
+ return "Unknown";
+}
+
+int main(void)
+{
+ struct gpiod_line_request *request;
+ struct gpiod_edge_event_buffer *event_buffer;
+ struct gpiod_edge_event *event;
+ int i, ret, event_buf_size;
+ /* example configuration - customize to suit your situation */
+ const char *chip_path = "/dev/gpiochip0";
+ int line_offset = 5;
+
+ request = request_input_line(chip_path, line_offset,
+ "watch-line-value");
+ if (!request) {
+ fprintf(stderr, "failed to request line: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ /* a larger buffer is an optimisation for reading bursts of events from
+ * the kernel, but that is not necessary in this case, so 1 is fine.
+ */
+ event_buf_size = 1;
+ event_buffer = gpiod_edge_event_buffer_new(event_buf_size);
+ if (!event_buffer) {
+ fprintf(stderr, "failed to create event buffer: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ while (1) {
+ /* blocks until at least one event is available */
+ ret = gpiod_line_request_read_edge_events(request, event_buffer,
+ event_buf_size);
+ if (ret == -1) {
+ fprintf(stderr, "error reading edge events: %s\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+ for (i = 0; i < ret; i++) {
+ event = gpiod_edge_event_buffer_get_event(event_buffer,
+ i);
+ printf("offset: %d, type: %s, event #%ld\n",
+ gpiod_edge_event_get_line_offset(event),
+ edge_event_type_str(event),
+ gpiod_edge_event_get_line_seqno(event));
+ }
+ }
+}
--
2.40.1
next prev parent reply other threads:[~2023-06-14 3:55 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-14 3:54 [libgpiod][PATCH 0/4] dedicated examples Kent Gibson
2023-06-14 3:54 ` Kent Gibson [this message]
2023-06-14 3:54 ` [libgpiod][PATCH 2/4] bindings: cxx: examples: add " Kent Gibson
2023-06-14 3:54 ` [libgpiod][PATCH 3/4] bindings: python: " Kent Gibson
2023-06-14 3:54 ` [libgpiod][PATCH 4/4] bindings: rust: " Kent Gibson
2023-06-14 7:52 ` Erik Schilling
2023-06-14 8:18 ` Kent Gibson
2023-06-14 8:29 ` Erik Schilling
2023-06-14 13:03 ` [libgpiod][PATCH 0/4] " Bartosz Golaszewski
2023-06-14 13:21 ` Kent Gibson
2023-06-14 13:26 ` Bartosz Golaszewski
2023-06-14 13:57 ` Kent Gibson
2023-06-14 15:11 ` Bartosz Golaszewski
2023-06-14 16:00 ` Kent Gibson
2023-06-15 15:16 ` Bartosz Golaszewski
2023-06-15 15:39 ` Kent Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230614035426.15097-2-warthog618@gmail.com \
--to=warthog618@gmail.com \
--cc=brgl@bgdev.pl \
--cc=linux-gpio@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.