linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [libgpiod][PATCH 0/8] replace tool examples with use case examples
@ 2023-06-23  4:38 Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 1/8] core: examples: consistency cleanups Kent Gibson
                   ` (8 more replies)
  0 siblings, 9 replies; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:38 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

This series is the continuation of providing a set of use case based examples
for libgpiod. The focus of this series is replacement of the examples
replicating the the tools with examples that minimally cover the use case that
each tool addresses.

The mapping from tool to use case is:
  gpiodetect  ->  get_chip_info
  gpiofind    ->  find_line_by_name
  gpioget     ->  get_multiple_line_values
  gpioinfo    ->  get_line_info
  gpiomon     ->  watch_multiple_line_values
  gpionotify  ->  watch_line_info
  gpioset     ->  toggle_multiple_line_values

Also added a watch_line_rising example to demonstrate getting events from only
one edge rather than both, so another gpiomon sub-case.

The rust bindings had a couple of additional examples, gpio_events and
gpio_threaded_info_events.

gpio_threaded_info_events is an example of using one thread to generate info
change events that are observed by another thread.  This is borrowed from test
cases and has no other practical application, but the reconfiguring component
inspired the reconfigure_input_to_output example.  That provides an example of
reconfiguring a requested line, and is provided for all languages, not just
rust.

gpio_events is an example of how borrowed buffered events must be cloned before
the event buffer can be reused.  This was simplified and renamed
buffered_event_lifetimes.  As I write this I realise it may also be applicable
to other languages - as an example of using gpiod_edge_event_copy().
Maybe provide those in v2, or a subsequent series?

The series is split into 8 parts.  For each language there is a patch that
provides some consistency cleanups to make the existing examples more consistent
with each other, with the examples in other languages, and with the examples to
follow. There are also a few minor bug fixes that didn't seem sufficiently
serious to warrant a separate patch.

The second patch for each language replaces the old tool examples with the new
use case based examples.

Cheers,
Kent.

Kent Gibson (8):
  core: examples: consistency cleanups
  core: examples: add more use case examples
  bindings: cxx: examples: consistency cleanup
  bindings: cxx: examples: replace tools examples with use case examples
  bindings: python: examples: consistency cleanup
  bindings: python: examples: replace tools examples with use case
    examples
  bindings: rust: examples: consistency cleanup
  bindings: rust: examples: replace tools examples with use case
    examples

 bindings/cxx/examples/.gitignore              |  16 +-
 bindings/cxx/examples/Makefile.am             |  42 ++---
 .../cxx/examples/async_watch_line_value.cpp   |   8 +-
 bindings/cxx/examples/find_line_by_name.cpp   |  42 +++++
 bindings/cxx/examples/get_chip_info.cpp       |  27 ++++
 bindings/cxx/examples/get_line_info.cpp       |  39 +++++
 bindings/cxx/examples/get_line_value.cpp      |  28 ++--
 .../cxx/examples/get_multiple_line_values.cpp |  40 +++++
 bindings/cxx/examples/gpiodetectcxx.cpp       |  30 ----
 bindings/cxx/examples/gpiofindcxx.cpp         |  32 ----
 bindings/cxx/examples/gpiogetcxx.cpp          |  40 -----
 bindings/cxx/examples/gpioinfocxx.cpp         |  61 -------
 bindings/cxx/examples/gpiomoncxx.cpp          |  65 --------
 bindings/cxx/examples/gpionotifycxx.cpp       |  55 -------
 bindings/cxx/examples/gpiosetcxx.cpp          |  53 ------
 .../examples/reconfigure_input_to_output.cpp  |  56 +++++++
 bindings/cxx/examples/toggle_line_value.cpp   |  16 +-
 .../examples/toggle_multiple_line_values.cpp  |  63 ++++++++
 bindings/cxx/examples/watch_line_info.cpp     |  49 ++++++
 bindings/cxx/examples/watch_line_rising.cpp   |  64 ++++++++
 bindings/cxx/examples/watch_line_value.cpp    |  12 +-
 .../examples/watch_multiple_line_values.cpp   |  60 +++++++
 bindings/python/examples/Makefile.am          |  18 ++-
 .../python/examples/async_watch_line_value.py |  15 +-
 bindings/python/examples/find_line_by_name.py |  37 +++++
 bindings/python/examples/get_chip_info.py     |  20 +++
 bindings/python/examples/get_line_info.py     |  29 ++++
 bindings/python/examples/get_line_value.py    |  13 +-
 .../examples/get_multiple_line_values.py      |  29 ++++
 bindings/python/examples/gpiodetect.py        |  15 --
 bindings/python/examples/gpiofind.py          |  20 ---
 bindings/python/examples/gpioget.py           |  29 ----
 bindings/python/examples/gpioinfo.py          |  28 ----
 bindings/python/examples/gpiomon.py           |  26 ---
 bindings/python/examples/gpionotify.py        |  21 ---
 bindings/python/examples/gpioset.py           |  36 -----
 bindings/python/examples/helpers.py           |  15 --
 .../examples/reconfigure_input_to_output.py   |  39 +++++
 bindings/python/examples/toggle_line_value.py |  34 ++--
 .../examples/toggle_multiple_line_values.py   |  47 ++++++
 bindings/python/examples/watch_line_info.py   |  23 +++
 bindings/python/examples/watch_line_rising.py |  31 ++++
 bindings/python/examples/watch_line_value.py  |  19 ++-
 .../examples/watch_multiple_line_values.py    |  43 +++++
 bindings/rust/libgpiod/examples/Makefile.am   |  21 +--
 .../examples/buffered_event_lifetimes.rs      |  58 +++++++
 .../libgpiod/examples/find_line_by_name.rs    |  29 ++++
 .../rust/libgpiod/examples/get_chip_info.rs   |  22 +++
 .../rust/libgpiod/examples/get_line_info.rs   |  37 +++++
 .../rust/libgpiod/examples/get_line_value.rs  |   4 +-
 .../examples/get_multiple_line_values.rs      |  29 ++++
 .../rust/libgpiod/examples/gpio_events.rs     |  88 ----------
 .../examples/gpio_threaded_info_events.rs     | 132 ---------------
 bindings/rust/libgpiod/examples/gpiodetect.rs |  30 ----
 bindings/rust/libgpiod/examples/gpiofind.rs   |  36 -----
 bindings/rust/libgpiod/examples/gpioget.rs    |  45 ------
 bindings/rust/libgpiod/examples/gpioinfo.rs   |  97 -----------
 bindings/rust/libgpiod/examples/gpiomon.rs    |  74 ---------
 bindings/rust/libgpiod/examples/gpionotify.rs |  53 ------
 bindings/rust/libgpiod/examples/gpioset.rs    |  63 --------
 bindings/rust/libgpiod/examples/gpiowatch.rs  |  53 ------
 .../examples/reconfigure_input_to_output.rs   |  42 +++++
 .../libgpiod/examples/toggle_line_value.rs    |  17 +-
 .../examples/toggle_multiple_line_values.rs   |  55 +++++++
 .../rust/libgpiod/examples/watch_line_info.rs |  32 ++++
 .../libgpiod/examples/watch_line_rising.rs    |  44 +++++
 .../libgpiod/examples/watch_line_value.rs     |  10 +-
 .../examples/watch_multiple_line_values.rs    |  46 ++++++
 examples/.gitignore                           |   9 ++
 examples/Makefile.am                          |  35 +++-
 examples/async_watch_line_value.c             |   6 +-
 examples/find_line_by_name.c                  | 111 +++++++++++++
 examples/get_chip_info.c                      |  40 +++++
 examples/get_line_info.c                      |  56 +++++++
 examples/get_line_value.c                     |  11 +-
 examples/get_multiple_line_values.c           | 119 ++++++++++++++
 examples/reconfigure_input_to_output.c        | 152 ++++++++++++++++++
 examples/toggle_line_value.c                  |  17 +-
 examples/toggle_multiple_line_values.c        | 136 ++++++++++++++++
 examples/watch_line_info.c                    |  72 +++++++++
 examples/watch_line_rising.c                  | 129 +++++++++++++++
 examples/watch_line_value.c                   |   6 +-
 examples/watch_multiple_line_values.c         | 140 ++++++++++++++++
 83 files changed, 2289 insertions(+), 1352 deletions(-)
 create mode 100644 bindings/cxx/examples/find_line_by_name.cpp
 create mode 100644 bindings/cxx/examples/get_chip_info.cpp
 create mode 100644 bindings/cxx/examples/get_line_info.cpp
 create mode 100644 bindings/cxx/examples/get_multiple_line_values.cpp
 delete mode 100644 bindings/cxx/examples/gpiodetectcxx.cpp
 delete mode 100644 bindings/cxx/examples/gpiofindcxx.cpp
 delete mode 100644 bindings/cxx/examples/gpiogetcxx.cpp
 delete mode 100644 bindings/cxx/examples/gpioinfocxx.cpp
 delete mode 100644 bindings/cxx/examples/gpiomoncxx.cpp
 delete mode 100644 bindings/cxx/examples/gpionotifycxx.cpp
 delete mode 100644 bindings/cxx/examples/gpiosetcxx.cpp
 create mode 100644 bindings/cxx/examples/reconfigure_input_to_output.cpp
 create mode 100644 bindings/cxx/examples/toggle_multiple_line_values.cpp
 create mode 100644 bindings/cxx/examples/watch_line_info.cpp
 create mode 100644 bindings/cxx/examples/watch_line_rising.cpp
 create mode 100644 bindings/cxx/examples/watch_multiple_line_values.cpp
 create mode 100755 bindings/python/examples/find_line_by_name.py
 create mode 100755 bindings/python/examples/get_chip_info.py
 create mode 100755 bindings/python/examples/get_line_info.py
 create mode 100755 bindings/python/examples/get_multiple_line_values.py
 delete mode 100755 bindings/python/examples/gpiodetect.py
 delete mode 100755 bindings/python/examples/gpiofind.py
 delete mode 100755 bindings/python/examples/gpioget.py
 delete mode 100755 bindings/python/examples/gpioinfo.py
 delete mode 100755 bindings/python/examples/gpiomon.py
 delete mode 100755 bindings/python/examples/gpionotify.py
 delete mode 100755 bindings/python/examples/gpioset.py
 delete mode 100644 bindings/python/examples/helpers.py
 create mode 100755 bindings/python/examples/reconfigure_input_to_output.py
 create mode 100755 bindings/python/examples/toggle_multiple_line_values.py
 create mode 100755 bindings/python/examples/watch_line_info.py
 create mode 100755 bindings/python/examples/watch_line_rising.py
 create mode 100755 bindings/python/examples/watch_multiple_line_values.py
 create mode 100644 bindings/rust/libgpiod/examples/buffered_event_lifetimes.rs
 create mode 100644 bindings/rust/libgpiod/examples/find_line_by_name.rs
 create mode 100644 bindings/rust/libgpiod/examples/get_chip_info.rs
 create mode 100644 bindings/rust/libgpiod/examples/get_line_info.rs
 create mode 100644 bindings/rust/libgpiod/examples/get_multiple_line_values.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpio_events.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpiodetect.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpiofind.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpioget.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpioinfo.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpiomon.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpionotify.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpioset.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpiowatch.rs
 create mode 100644 bindings/rust/libgpiod/examples/reconfigure_input_to_output.rs
 create mode 100644 bindings/rust/libgpiod/examples/toggle_multiple_line_values.rs
 create mode 100644 bindings/rust/libgpiod/examples/watch_line_info.rs
 create mode 100644 bindings/rust/libgpiod/examples/watch_line_rising.rs
 create mode 100644 bindings/rust/libgpiod/examples/watch_multiple_line_values.rs
 create mode 100644 examples/find_line_by_name.c
 create mode 100644 examples/get_chip_info.c
 create mode 100644 examples/get_line_info.c
 create mode 100644 examples/get_multiple_line_values.c
 create mode 100644 examples/reconfigure_input_to_output.c
 create mode 100644 examples/toggle_multiple_line_values.c
 create mode 100644 examples/watch_line_info.c
 create mode 100644 examples/watch_line_rising.c
 create mode 100644 examples/watch_multiple_line_values.c

-- 
2.41.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [libgpiod][PATCH 1/8] core: examples: consistency cleanups
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
@ 2023-06-23  4:38 ` Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 2/8] core: examples: add more use case examples Kent Gibson
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:38 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

A collection of minor cleanups to make the examples more consistent and
ease the addition of more examples:
 - reformat Makefile.am to simplify adding more examples
 - add line offset to value output
 - remove commas from edge event output
 - replace while(1) with for (;;)
 - fix a typo in Makefile.am
 - fix an error handling goto in toggle_line_value.c

Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
 examples/Makefile.am              |  8 ++++++--
 examples/async_watch_line_value.c |  6 +++---
 examples/get_line_value.c         | 11 +++++++----
 examples/toggle_line_value.c      | 17 ++++++++++-------
 examples/watch_line_value.c       |  6 +++---
 5 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/examples/Makefile.am b/examples/Makefile.am
index 4ad124b..55dfe39 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -6,12 +6,16 @@ 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
+noinst_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
+toggle_line_value_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
index 3292dda..f35fb1a 100644
--- a/examples/async_watch_line_value.c
+++ b/examples/async_watch_line_value.c
@@ -74,7 +74,7 @@ static const char *edge_event_type_str(struct gpiod_edge_event *event)
 {
 	switch (gpiod_edge_event_get_event_type(event)) {
 	case GPIOD_EDGE_EVENT_RISING_EDGE:
-		return "Rising ";
+		return "Rising";
 	case GPIOD_EDGE_EVENT_FALLING_EDGE:
 		return "Falling";
 	default:
@@ -117,7 +117,7 @@ int main(void)
 	pollfd.fd = gpiod_line_request_get_fd(request);
 	pollfd.events = POLLIN;
 
-	while (1) {
+	for (;;) {
 		ret = poll(&pollfd, 1, -1);
 		if (ret == -1) {
 			fprintf(stderr, "error waiting for edge events: %s\n",
@@ -134,7 +134,7 @@ int main(void)
 		for (i = 0; i < ret; i++) {
 			event = gpiod_edge_event_buffer_get_event(event_buffer,
 								  i);
-			printf("offset: %d, type: %s, event #%ld\n",
+			printf("offset: %d  type: %-7s  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
index 08e263a..1de9901 100644
--- a/examples/get_line_value.c
+++ b/examples/get_line_value.c
@@ -64,12 +64,12 @@ close_chip:
 	return request;
 }
 
-static int print_value(enum gpiod_line_value value)
+static int print_value(unsigned int offset, enum gpiod_line_value value)
 {
 	if (value == GPIOD_LINE_VALUE_ACTIVE)
-		printf("Active\n");
+		printf("%d=Active\n", offset);
 	else if (value == GPIOD_LINE_VALUE_INACTIVE) {
-		printf("Inactive\n");
+		printf("%d=Inactive\n", offset);
 	} else {
 		fprintf(stderr, "error reading value: %s\n",
 			strerror(errno));
@@ -97,7 +97,10 @@ int main(void)
 	}
 
 	value = gpiod_line_request_get_value(request, line_offset);
-	ret = print_value(value);
+	ret = print_value(line_offset, value);
+
+	/* not strictly required here, but if the app wasn't exiting... */
+	gpiod_line_request_release(request);
 
 	return ret;
 }
diff --git a/examples/toggle_line_value.c b/examples/toggle_line_value.c
index 63d7fb9..6e522d6 100644
--- a/examples/toggle_line_value.c
+++ b/examples/toggle_line_value.c
@@ -40,7 +40,7 @@ request_output_line(const char *chip_path, unsigned int offset,
 	ret = gpiod_line_config_add_line_settings(line_cfg, &offset, 1,
 						  settings);
 	if (ret)
-		goto free_settings;
+		goto free_line_config;
 
 	if (consumer) {
 		req_cfg = gpiod_request_config_new();
@@ -72,12 +72,15 @@ static enum gpiod_line_value toggle_line_value(enum gpiod_line_value value)
 						    GPIOD_LINE_VALUE_ACTIVE;
 }
 
-static void print_value(enum gpiod_line_value value)
+static const char * value_str(enum gpiod_line_value value)
 {
 	if (value == GPIOD_LINE_VALUE_ACTIVE)
-		printf("Active\n");
-	else
-		printf("Inactive\n");
+		return "Active";
+	else if (value == GPIOD_LINE_VALUE_INACTIVE) {
+		return "Inactive";
+	} else {
+		return "Unknown";
+	}
 }
 
 int main(void)
@@ -97,8 +100,8 @@ int main(void)
 		return EXIT_FAILURE;
 	}
 
-	while (1) {
-		print_value(value);
+	for (;;) {
+		printf("%d=%s\n", line_offset, value_str(value));
 		sleep(1);
 		value = toggle_line_value(value);
 		gpiod_line_request_set_value(request, line_offset, value);
diff --git a/examples/watch_line_value.c b/examples/watch_line_value.c
index d962f20..879b09b 100644
--- a/examples/watch_line_value.c
+++ b/examples/watch_line_value.c
@@ -73,7 +73,7 @@ static const char *edge_event_type_str(struct gpiod_edge_event *event)
 {
 	switch (gpiod_edge_event_get_event_type(event)) {
 	case GPIOD_EDGE_EVENT_RISING_EDGE:
-		return "Rising ";
+		return "Rising";
 	case GPIOD_EDGE_EVENT_FALLING_EDGE:
 		return "Falling";
 	default:
@@ -112,7 +112,7 @@ int main(void)
 		return EXIT_FAILURE;
 	}
 
-	while (1) {
+	for (;;) {
 		/* Blocks until at least one event is available. */
 		ret = gpiod_line_request_read_edge_events(request, event_buffer,
 							  event_buf_size);
@@ -124,7 +124,7 @@ int main(void)
 		for (i = 0; i < ret; i++) {
 			event = gpiod_edge_event_buffer_get_event(event_buffer,
 								  i);
-			printf("offset: %d, type: %s, event #%ld\n",
+			printf("offset: %d  type: %-7s  event #%ld\n",
 			       gpiod_edge_event_get_line_offset(event),
 			       edge_event_type_str(event),
 			       gpiod_edge_event_get_line_seqno(event));
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [libgpiod][PATCH 2/8] core: examples: add more use case examples
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 1/8] core: examples: consistency cleanups Kent Gibson
@ 2023-06-23  4:38 ` Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 3/8] bindings: cxx: examples: consistency cleanup Kent Gibson
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:38 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

Add examples for use cases drawn from the tools.

Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
 examples/.gitignore                    |   9 ++
 examples/Makefile.am                   |  29 ++++-
 examples/find_line_by_name.c           | 111 ++++++++++++++++++
 examples/get_chip_info.c               |  40 +++++++
 examples/get_line_info.c               |  56 +++++++++
 examples/get_multiple_line_values.c    | 119 +++++++++++++++++++
 examples/reconfigure_input_to_output.c | 152 +++++++++++++++++++++++++
 examples/toggle_multiple_line_values.c | 136 ++++++++++++++++++++++
 examples/watch_line_info.c             |  72 ++++++++++++
 examples/watch_line_rising.c           | 129 +++++++++++++++++++++
 examples/watch_multiple_line_values.c  | 140 +++++++++++++++++++++++
 11 files changed, 992 insertions(+), 1 deletion(-)
 create mode 100644 examples/find_line_by_name.c
 create mode 100644 examples/get_chip_info.c
 create mode 100644 examples/get_line_info.c
 create mode 100644 examples/get_multiple_line_values.c
 create mode 100644 examples/reconfigure_input_to_output.c
 create mode 100644 examples/toggle_multiple_line_values.c
 create mode 100644 examples/watch_line_info.c
 create mode 100644 examples/watch_line_rising.c
 create mode 100644 examples/watch_multiple_line_values.c

diff --git a/examples/.gitignore b/examples/.gitignore
index bdfde9a..8fd3ff3 100644
--- a/examples/.gitignore
+++ b/examples/.gitignore
@@ -2,6 +2,15 @@
 # SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
 
 async_watch_line_value
+find_line_by_name
+get_chip_info
+get_line_info
 get_line_value
+get_multiple_line_values
+reconfigure_input_to_output
 toggle_line_value
+toggle_multiple_line_values
+watch_line_info
+watch_line_rising
 watch_line_value
+watch_multiple_line_values
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 55dfe39..daf902b 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -8,14 +8,41 @@ LDADD = $(top_builddir)/lib/libgpiod.la
 
 noinst_PROGRAMS = \
 	async_watch_line_value \
+	find_line_by_name \
+	get_chip_info \
+	get_line_info \
 	get_line_value \
+	get_multiple_line_values \
+	reconfigure_input_to_output \
 	toggle_line_value \
-	watch_line_value
+	toggle_multiple_line_values \
+	watch_line_info \
+	watch_line_rising \
+	watch_line_value \
+	watch_multiple_line_values
 
 async_watch_line_value_SOURCES = async_watch_line_value.c
 
+find_line_by_name_SOURCES = find_line_by_name.c
+
+get_chip_info_SOURCES = get_chip_info.c
+
+get_line_info_SOURCES = get_line_info.c
+
 get_line_value_SOURCES = get_line_value.c
 
+get_multiple_line_values_SOURCES = get_multiple_line_values.c
+
+reconfigure_input_to_output_SOURCES = reconfigure_input_to_output.c
+
 toggle_line_value_SOURCES = toggle_line_value.c
 
+toggle_multiple_line_value_SOURCES = toggle_multiple_line_value.c
+
+watch_line_info_SOURCES = watch_line_info.c
+
+watch_line_rising_SOURCES = watch_line_rising.c
+
 watch_line_value_SOURCES = watch_line_value.c
+
+watch_multiple_line_values_SOURCES = watch_multiple_line_values.c
diff --git a/examples/find_line_by_name.c b/examples/find_line_by_name.c
new file mode 100644
index 0000000..ea1d938
--- /dev/null
+++ b/examples/find_line_by_name.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of finding a line with the given name. */
+
+#include <dirent.h>
+#include <errno.h>
+#include <gpiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+static int chip_dir_filter(const struct dirent *entry)
+{
+	struct stat sb;
+	int ret = 0;
+	char *path;
+
+	if (asprintf(&path, "/dev/%s", entry->d_name) < 0)
+		return 0;
+
+	if ((lstat(path, &sb) == 0) && (!S_ISLNK(sb.st_mode)) &&
+	    gpiod_is_gpiochip_device(path))
+		ret = 1;
+
+	free(path);
+
+	return ret;
+}
+
+static int all_chip_paths(char ***paths_ptr)
+{
+	int i, j, num_chips, ret = 0;
+	struct dirent **entries;
+	char **paths;
+
+	num_chips = scandir("/dev/", &entries, chip_dir_filter, versionsort);
+	if (num_chips < 0)
+		return 0;
+
+	paths = calloc(num_chips, sizeof(*paths));
+	if (!paths)
+		return 0;
+
+	for (i = 0; i < num_chips; i++) {
+		if (asprintf(&paths[i], "/dev/%s", entries[i]->d_name) < 0) {
+			for (j = 0; j < i; j++)
+				free(paths[j]);
+
+			free(paths);
+			return 0;
+		}
+	}
+
+	*paths_ptr = paths;
+	ret = num_chips;
+
+	for (i = 0; i < num_chips; i++)
+		free(entries[i]);
+
+	free(entries);
+	return ret;
+}
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const line_name = "GPIO19";
+
+	struct gpiod_chip *chip;
+	struct gpiod_chip_info *cinfo;
+	struct gpiod_line_info *linfo;
+	char **chip_paths;
+	const char *name;
+	unsigned int j, num_lines;
+	int i, num_chips;
+
+	/*
+	 * Names are not guaranteed unique, so this finds the first line with
+	 * the given name.
+	 */
+	num_chips = all_chip_paths(&chip_paths);
+	for (i = 0; i < num_chips; i++) {
+		chip = gpiod_chip_open(chip_paths[i]);
+		if (!chip)
+			continue;
+		cinfo = gpiod_chip_get_info(chip);
+		if (!cinfo)
+			continue;
+
+		num_lines = gpiod_chip_info_get_num_lines(cinfo);
+		for (j = 0; j < num_lines; j++) {
+			linfo = gpiod_chip_get_line_info(chip, j);
+			if (!linfo)
+				continue;
+			name = gpiod_line_info_get_name(linfo);
+			if (name && (strcmp(line_name, name) == 0)) {
+				printf("%s: %s %d\n", line_name,
+				       gpiod_chip_info_get_name(cinfo), j);
+				return EXIT_SUCCESS;
+			}
+			gpiod_line_info_free(linfo);
+		}
+		gpiod_chip_info_free(cinfo);
+		gpiod_chip_close(chip);
+	}
+
+	printf("line '%s' not found\n", line_name);
+	return EXIT_FAILURE;
+}
diff --git a/examples/get_chip_info.c b/examples/get_chip_info.c
new file mode 100644
index 0000000..5c181c8
--- /dev/null
+++ b/examples/get_chip_info.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of reading the info for a chip. */
+
+#include <errno.h>
+#include <gpiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const chip_path = "/dev/gpiochip0";
+
+	struct gpiod_chip_info *info;
+	struct gpiod_chip *chip;
+
+	chip = gpiod_chip_open(chip_path);
+	if (!chip) {
+		fprintf(stderr, "failed to open chip: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	info = gpiod_chip_get_info(chip);
+	if (!info) {
+		fprintf(stderr, "failed to read info: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	printf("%s [%s] (%zu lines)\n", gpiod_chip_info_get_name(info),
+	       gpiod_chip_info_get_label(info),
+	       gpiod_chip_info_get_num_lines(info));
+
+	gpiod_chip_info_free(info);
+	gpiod_chip_close(chip);
+
+	return EXIT_SUCCESS;
+}
diff --git a/examples/get_line_info.c b/examples/get_line_info.c
new file mode 100644
index 0000000..743c98f
--- /dev/null
+++ b/examples/get_line_info.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of reading the info for a line. */
+
+#include <errno.h>
+#include <gpiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const chip_path = "/dev/gpiochip0";
+	static const unsigned int line_offset = 3;
+
+	struct gpiod_line_info *info;
+	struct gpiod_chip *chip;
+	const char *name, *consumer, *dir;
+
+	chip = gpiod_chip_open(chip_path);
+	if (!chip) {
+		fprintf(stderr, "failed to open chip: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	info = gpiod_chip_get_line_info(chip, line_offset);
+	if (!info) {
+		fprintf(stderr, "failed to read info: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	name = gpiod_line_info_get_name(info);
+	if (!name)
+		name = "unnamed";
+
+	consumer = gpiod_line_info_get_consumer(info);
+	if (!consumer)
+		consumer = "unused";
+
+	dir = (gpiod_line_info_get_direction(info) ==
+	       GPIOD_LINE_DIRECTION_INPUT) ?
+		      "input" :
+		      "output";
+
+	printf("line %3d: %12s %12s %8s %10s\n",
+	       gpiod_line_info_get_offset(info), name, consumer, dir,
+	       gpiod_line_info_is_active_low(info) ? "active-low" :
+						     "active-high");
+
+	gpiod_line_info_free(info);
+	gpiod_chip_close(chip);
+
+	return EXIT_SUCCESS;
+}
diff --git a/examples/get_multiple_line_values.c b/examples/get_multiple_line_values.c
new file mode 100644
index 0000000..fc26636
--- /dev/null
+++ b/examples/get_multiple_line_values.c
@@ -0,0 +1,119 @@
+// 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. */
+static struct gpiod_line_request *
+request_input_lines(const char *chip_path, const unsigned int *offsets,
+		    unsigned int num_lines, const char *consumer)
+{
+	struct gpiod_request_config *req_cfg = NULL;
+	struct gpiod_line_request *request = NULL;
+	struct gpiod_line_settings *settings;
+	struct gpiod_line_config *line_cfg;
+	struct gpiod_chip *chip;
+	unsigned int i;
+	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;
+
+	for (i = 0; i < num_lines; i++) {
+		ret = gpiod_line_config_add_line_settings(line_cfg, &offsets[i],
+							  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;
+}
+
+static int print_values(const unsigned int *offsets, unsigned int num_lines,
+			enum gpiod_line_value *values)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_lines; i++) {
+		if (values[i] == GPIOD_LINE_VALUE_ACTIVE)
+			printf("%d=Active ", offsets[i]);
+		else if (values[i] == GPIOD_LINE_VALUE_INACTIVE) {
+			printf("%d=Inactive ", offsets[i]);
+		} else {
+			fprintf(stderr, "error reading value: %s\n",
+				strerror(errno));
+			return EXIT_FAILURE;
+		}
+	}
+	printf("\n");
+
+	return EXIT_SUCCESS;
+}
+
+#define NUM_LINES 3
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const chip_path = "/dev/gpiochip0";
+	static const unsigned int line_offsets[NUM_LINES] = { 5, 3, 7 };
+
+	struct gpiod_line_request *request;
+	enum gpiod_line_value values[NUM_LINES];
+	int ret;
+
+	request = request_input_lines(chip_path, line_offsets, NUM_LINES,
+				      "get-multiple-line-values");
+	if (!request) {
+		fprintf(stderr, "failed to request lines: %s\n",
+			strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	ret = gpiod_line_request_get_values(request, values);
+	if (ret == -1) {
+		fprintf(stderr, "failed to get values: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+	ret = print_values(line_offsets, NUM_LINES, values);
+
+	return ret;
+}
diff --git a/examples/reconfigure_input_to_output.c b/examples/reconfigure_input_to_output.c
new file mode 100644
index 0000000..e8fbb1c
--- /dev/null
+++ b/examples/reconfigure_input_to_output.c
@@ -0,0 +1,152 @@
+// 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. */
+static struct gpiod_line_request *request_input_line(const char *chip_path,
+						     unsigned int offset,
+						     const char *consumer)
+{
+	struct gpiod_request_config *req_cfg = NULL;
+	struct gpiod_line_request *request = NULL;
+	struct gpiod_line_settings *settings;
+	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;
+}
+
+static int reconfigure_as_output_line(struct gpiod_line_request *request,
+				      unsigned int offset,
+				      enum gpiod_line_value value)
+{
+	struct gpiod_request_config *req_cfg = NULL;
+	struct gpiod_line_settings *settings;
+	struct gpiod_line_config *line_cfg;
+	int ret = -1;
+
+	settings = gpiod_line_settings_new();
+	if (!settings)
+		return -1;
+
+	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_line_config;
+
+	ret = gpiod_line_request_reconfigure_lines(request, line_cfg);
+
+	gpiod_request_config_free(req_cfg);
+
+free_line_config:
+	gpiod_line_config_free(line_cfg);
+
+free_settings:
+	gpiod_line_settings_free(settings);
+
+	return ret;
+}
+
+static const char * value_str(enum gpiod_line_value value)
+{
+	if (value == GPIOD_LINE_VALUE_ACTIVE)
+		return "Active";
+	else if (value == GPIOD_LINE_VALUE_INACTIVE) {
+		return "Inactive";
+	} else {
+		return "Unknown";
+	}
+}
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const chip_path = "/dev/gpiochip0";
+	static const unsigned int line_offset = 5;
+
+	struct gpiod_line_request *request;
+	enum gpiod_line_value value;
+	int ret;
+
+	/* request the line initially as an input */
+	request = request_input_line(chip_path, line_offset,
+				     "reconfigure-input-to-output");
+	if (!request) {
+		fprintf(stderr, "failed to request line: %s\n",
+			strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	/* read the current line value */
+	value = gpiod_line_request_get_value(request, line_offset);
+	printf("%d=%s (input)\n", line_offset, value_str(value));
+
+	/* switch the line to an output and drive it low */
+	ret = reconfigure_as_output_line(request, line_offset,
+					 GPIOD_LINE_VALUE_INACTIVE);
+
+	/* report the current driven value */
+	value = gpiod_line_request_get_value(request, line_offset);
+	printf("%d=%s (output)\n", line_offset, value_str(value));
+
+	/* not strictly required here, but if the app wasn't exiting... */
+	gpiod_line_request_release(request);
+
+	return ret;
+}
diff --git a/examples/toggle_multiple_line_values.c b/examples/toggle_multiple_line_values.c
new file mode 100644
index 0000000..059a79f
--- /dev/null
+++ b/examples/toggle_multiple_line_values.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of toggling multiple lines. */
+
+#include <errno.h>
+#include <gpiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static struct gpiod_line_request *
+request_output_lines(const char *chip_path, const unsigned int *offsets,
+		     enum gpiod_line_value *values, unsigned int num_lines,
+		     const char *consumer)
+{
+	struct gpiod_request_config *rconfig = NULL;
+	struct gpiod_line_request *request = NULL;
+	struct gpiod_line_settings *settings;
+	struct gpiod_line_config *lconfig;
+	struct gpiod_chip *chip;
+	unsigned int i;
+	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);
+
+	lconfig = gpiod_line_config_new();
+	if (!lconfig)
+		goto free_settings;
+
+	for (i = 0; i < num_lines; i++) {
+		ret = gpiod_line_config_add_line_settings(lconfig, &offsets[i],
+							  1, settings);
+		if (ret)
+			goto free_line_config;
+	}
+	gpiod_line_config_set_output_values(lconfig, values, num_lines);
+
+	if (consumer) {
+		rconfig = gpiod_request_config_new();
+		if (!rconfig)
+			goto free_line_config;
+
+		gpiod_request_config_set_consumer(rconfig, consumer);
+	}
+
+	request = gpiod_chip_request_lines(chip, rconfig, lconfig);
+
+	gpiod_request_config_free(rconfig);
+
+free_line_config:
+	gpiod_line_config_free(lconfig);
+
+free_settings:
+	gpiod_line_settings_free(settings);
+
+close_chip:
+	gpiod_chip_close(chip);
+
+	return request;
+}
+
+static 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;
+}
+
+static void toggle_line_values(enum gpiod_line_value *values,
+			       unsigned int num_lines)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_lines; i++) {
+		values[i] = toggle_line_value(values[i]);
+	}
+}
+
+static void print_values(const unsigned int *offsets,
+			 const enum gpiod_line_value *values,
+			 unsigned int num_lines)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_lines; i++) {
+		if (values[i] == GPIOD_LINE_VALUE_ACTIVE)
+			printf("%d=Active ", offsets[i]);
+		else
+			printf("%d=Inactive ", offsets[i]);
+	}
+	printf("\n");
+}
+
+#define NUM_LINES 3
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const chip_path = "/dev/gpiochip0";
+	static const unsigned int line_offsets[NUM_LINES] = { 5, 3, 7 };
+
+	enum gpiod_line_value values[NUM_LINES] = { GPIOD_LINE_VALUE_ACTIVE,
+						    GPIOD_LINE_VALUE_ACTIVE,
+						    GPIOD_LINE_VALUE_INACTIVE };
+	struct gpiod_line_request *request;
+
+	request = request_output_lines(chip_path, line_offsets, values,
+				       NUM_LINES,
+				       "toggle-multiple-line-values");
+	if (!request) {
+		fprintf(stderr, "failed to request line: %s\n",
+			strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	for (;;) {
+		print_values(line_offsets, values, NUM_LINES);
+		sleep(1);
+		toggle_line_values(values, NUM_LINES);
+		gpiod_line_request_set_values(request, values);
+	}
+
+	gpiod_line_request_release(request);
+
+	return EXIT_SUCCESS;
+}
diff --git a/examples/watch_line_info.c b/examples/watch_line_info.c
new file mode 100644
index 0000000..51fb5c7
--- /dev/null
+++ b/examples/watch_line_info.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of watching for info changes on particular lines. */
+
+#include <errno.h>
+#include <gpiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+const char *event_type(struct gpiod_info_event *event)
+{
+	switch (gpiod_info_event_get_event_type(event)) {
+	case GPIOD_INFO_EVENT_LINE_REQUESTED:
+		return "Requested";
+	case GPIOD_INFO_EVENT_LINE_RELEASED:
+		return "Released";
+	case GPIOD_INFO_EVENT_LINE_CONFIG_CHANGED:
+		return "Reconfig";
+	default:
+		return "Unknown";
+	}
+}
+
+#define NUM_LINES 3
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const chip_path = "/dev/gpiochip0";
+	static const unsigned int line_offsets[NUM_LINES] = { 5, 3, 7 };
+
+	struct gpiod_line_info *info;
+	struct gpiod_info_event *event;
+	struct gpiod_chip *chip;
+	unsigned int i;
+	uint64_t timestamp_ns;
+
+	chip = gpiod_chip_open(chip_path);
+	if (!chip) {
+		fprintf(stderr, "failed to open chip: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	for (i = 0; i < NUM_LINES; i++) {
+		info = gpiod_chip_watch_line_info(chip, line_offsets[i]);
+		if (!info) {
+			fprintf(stderr, "failed to read info: %s\n",
+				strerror(errno));
+			return EXIT_FAILURE;
+		}
+	}
+
+	for (;;) {
+		/* Blocks until an event is available. */
+		event = gpiod_chip_read_info_event(chip);
+		if (!event) {
+			fprintf(stderr, "failed to read event: %s\n",
+				strerror(errno));
+			return EXIT_FAILURE;
+		}
+
+		info = gpiod_info_event_get_line_info(event);
+		timestamp_ns = gpiod_info_event_get_timestamp_ns(event);
+		printf("line %3d: %-9s %ld.%ld\n",
+		       gpiod_line_info_get_offset(info), event_type(event),
+		       timestamp_ns / 1000000000, timestamp_ns % 1000000000);
+
+		gpiod_info_event_free(event);
+	}
+}
diff --git a/examples/watch_line_rising.c b/examples/watch_line_rising.c
new file mode 100644
index 0000000..062a46a
--- /dev/null
+++ b/examples/watch_line_rising.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of watching for rising 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. */
+static struct gpiod_line_request *request_input_line(const char *chip_path,
+						     unsigned int offset,
+						     const char *consumer)
+{
+	struct gpiod_request_config *req_cfg = NULL;
+	struct gpiod_line_request *request = NULL;
+	struct gpiod_line_settings *settings;
+	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_RISING);
+
+	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;
+}
+
+static const char *edge_event_type_str(struct gpiod_edge_event *event)
+{
+	switch (gpiod_edge_event_get_event_type(event)) {
+	case GPIOD_EDGE_EVENT_RISING_EDGE:
+		return "Rising";
+	case GPIOD_EDGE_EVENT_FALLING_EDGE:
+		return "Falling";
+	default:
+		return "Unknown";
+	}
+}
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const chip_path = "/dev/gpiochip0";
+	static const unsigned int line_offset = 5;
+
+	struct gpiod_edge_event_buffer *event_buffer;
+	struct gpiod_line_request *request;
+	struct gpiod_edge_event *event;
+	int i, ret, event_buf_size;
+
+	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;
+	}
+
+	for (;;) {
+		/* 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: %-7s  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/watch_multiple_line_values.c b/examples/watch_multiple_line_values.c
new file mode 100644
index 0000000..6918aa6
--- /dev/null
+++ b/examples/watch_multiple_line_values.c
@@ -0,0 +1,140 @@
+// 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. */
+static struct gpiod_line_request *
+request_input_lines(const char *chip_path, const unsigned int *offsets,
+		    unsigned int num_lines, const char *consumer)
+{
+	struct gpiod_request_config *req_cfg = NULL;
+	struct gpiod_line_request *request = NULL;
+	struct gpiod_line_settings *settings;
+	struct gpiod_line_config *line_cfg;
+	struct gpiod_chip *chip;
+	unsigned int i;
+	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;
+
+	for (i = 0; i < num_lines; i++) {
+		ret = gpiod_line_config_add_line_settings(line_cfg, &offsets[i],
+							  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;
+}
+
+static const char *edge_event_type_str(struct gpiod_edge_event *event)
+{
+	switch (gpiod_edge_event_get_event_type(event)) {
+	case GPIOD_EDGE_EVENT_RISING_EDGE:
+		return "Rising";
+	case GPIOD_EDGE_EVENT_FALLING_EDGE:
+		return "Falling";
+	default:
+		return "Unknown";
+	}
+}
+
+#define NUM_LINES 3
+
+int main(void)
+{
+	/* Example configuration - customize to suit your situation. */
+	static const char *const chip_path = "/dev/gpiochip0";
+	static const unsigned int line_offsets[NUM_LINES] = { 5, 3, 7 };
+
+	struct gpiod_edge_event_buffer *event_buffer;
+	struct gpiod_line_request *request;
+	struct gpiod_edge_event *event;
+	int i, ret, event_buf_size;
+
+	request = request_input_lines(chip_path, line_offsets, NUM_LINES,
+				      "watch-multiple-line-values");
+	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, so even a value of 1 would be fine.
+	 * The size here allows for a simultaneous event on each of the lines
+	 * to be copied in one read.
+	 */
+	event_buf_size = NUM_LINES;
+	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;
+	}
+
+	for (;;) {
+		/* 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: %-7s  event #%ld\n",
+			       gpiod_edge_event_get_line_offset(event),
+			       edge_event_type_str(event),
+			       gpiod_edge_event_get_line_seqno(event));
+		}
+	}
+}
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [libgpiod][PATCH 3/8] bindings: cxx: examples: consistency cleanup
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 1/8] core: examples: consistency cleanups Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 2/8] core: examples: add more use case examples Kent Gibson
@ 2023-06-23  4:38 ` Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 4/8] bindings: cxx: examples: replace tools examples with use case examples Kent Gibson
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:38 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

A collection of minor changes to be more consistent with other examples:
 - capitalize comments
 - add line offset to value outputs
 - drop comma from edge event outputs
 - drop trailing return where example loops indefintely
 - sort includes

Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
 .../cxx/examples/async_watch_line_value.cpp   |  8 +++---
 bindings/cxx/examples/get_line_value.cpp      | 28 +++++++++++--------
 bindings/cxx/examples/toggle_line_value.cpp   | 16 +++++------
 bindings/cxx/examples/watch_line_value.cpp    | 12 ++++----
 4 files changed, 33 insertions(+), 31 deletions(-)

diff --git a/bindings/cxx/examples/async_watch_line_value.cpp b/bindings/cxx/examples/async_watch_line_value.cpp
index e1d4a1e..d8317a5 100644
--- a/bindings/cxx/examples/async_watch_line_value.cpp
+++ b/bindings/cxx/examples/async_watch_line_value.cpp
@@ -7,6 +7,7 @@
 #include <cstring>
 #include <filesystem>
 #include <gpiod.hpp>
+#include <iomanip>
 #include <iostream>
 #include <poll.h>
 
@@ -79,10 +80,9 @@ int main(void)
 
 		for (const auto& event : buffer)
 			::std::cout << "offset: " << event.line_offset()
-				    << ", type: " << edge_event_type_str(event)
-				    << ", event #" << event.line_seqno()
+				    << "  type: " << ::std::setw(7)
+				    << ::std::left << edge_event_type_str(event)
+				    << "  event #" << event.line_seqno()
 				    << ::std::endl;
 	}
-
-	return EXIT_SUCCESS;
 }
diff --git a/bindings/cxx/examples/get_line_value.cpp b/bindings/cxx/examples/get_line_value.cpp
index 8f4e739..a14d7e4 100644
--- a/bindings/cxx/examples/get_line_value.cpp
+++ b/bindings/cxx/examples/get_line_value.cpp
@@ -10,7 +10,7 @@
 
 namespace {
 
-/* example configuration - customize to suit your situation */
+/* Example configuration - customize to suit your situation */
 const ::std::filesystem::path chip_path("/dev/gpiochip0");
 const ::gpiod::line::offset line_offset = 5;
 
@@ -18,17 +18,21 @@ const ::gpiod::line::offset line_offset = 5;
 
 int main(void)
 {
-	auto request =
-		::gpiod::chip(chip_path)
-			.prepare_request()
-			.set_consumer("get-line-value")
-			.add_line_settings(
-				line_offset,
-				::gpiod::line_settings().set_direction(
-					::gpiod::line::direction::INPUT))
-			.do_request();
-
-	::std::cout << request.get_value(line_offset) << ::std::endl;
+	auto request = ::gpiod::chip(chip_path)
+			       .prepare_request()
+			       .set_consumer("get-line-value")
+			       .add_line_settings(
+				       line_offset,
+				       ::gpiod::line_settings().set_direction(
+					       ::gpiod::line::direction::INPUT))
+			       .do_request();
+
+	::std::cout << line_offset << "="
+		    << (request.get_value(line_offset) ==
+					::gpiod::line::value::ACTIVE ?
+				"Active" :
+				"Inactive")
+		    << ::std::endl;
 
 	return EXIT_SUCCESS;
 }
diff --git a/bindings/cxx/examples/toggle_line_value.cpp b/bindings/cxx/examples/toggle_line_value.cpp
index a060e8a..a17b43b 100644
--- a/bindings/cxx/examples/toggle_line_value.cpp
+++ b/bindings/cxx/examples/toggle_line_value.cpp
@@ -6,8 +6,8 @@
 #include <cstdlib>
 #include <chrono>
 #include <filesystem>
-#include <iostream>
 #include <gpiod.hpp>
+#include <iostream>
 #include <thread>
 
 namespace {
@@ -19,15 +19,15 @@ const ::gpiod::line::offset line_offset = 5;
 ::gpiod::line::value toggle_value(::gpiod::line::value v)
 {
 	return (v == ::gpiod::line::value::ACTIVE) ?
-			::gpiod::line::value::INACTIVE :
-			::gpiod::line::value::ACTIVE;
+		       ::gpiod::line::value::INACTIVE :
+		       ::gpiod::line::value::ACTIVE;
 }
 
 } /* namespace */
 
 int main(void)
 {
-	::gpiod::line::value val = ::gpiod::line::value::ACTIVE;
+	::gpiod::line::value value = ::gpiod::line::value::ACTIVE;
 
 	auto request =
 		::gpiod::chip(chip_path)
@@ -40,12 +40,10 @@ int main(void)
 			.do_request();
 
 	for (;;) {
-		::std::cout << val << ::std::endl;
+		::std::cout << line_offset << "=" << value << ::std::endl;
 
 		std::this_thread::sleep_for(std::chrono::seconds(1));
-		val = toggle_value(val);
-		request.set_value(line_offset, val);
+		value = toggle_value(value);
+		request.set_value(line_offset, value);
 	}
-
-	return EXIT_SUCCESS;
 }
diff --git a/bindings/cxx/examples/watch_line_value.cpp b/bindings/cxx/examples/watch_line_value.cpp
index 5436884..5055789 100644
--- a/bindings/cxx/examples/watch_line_value.cpp
+++ b/bindings/cxx/examples/watch_line_value.cpp
@@ -6,6 +6,7 @@
 #include <cstdlib>
 #include <filesystem>
 #include <gpiod.hpp>
+#include <iomanip>
 #include <iostream>
 
 namespace {
@@ -18,7 +19,7 @@ const char *edge_event_type_str(const ::gpiod::edge_event &event)
 {
 	switch (event.type()) {
 	case ::gpiod::edge_event::event_type::RISING_EDGE:
-		return "Rising ";
+		return "Rising";
 	case ::gpiod::edge_event::event_type::FALLING_EDGE:
 		return "Falling";
 	default:
@@ -61,11 +62,10 @@ int main(void)
 		request.read_edge_events(buffer);
 
 		for (const auto &event : buffer)
-			::std::cout << "offset: " << event.line_offset()
-				    << ", type: " << edge_event_type_str(event)
-				    << ", event #" << event.line_seqno()
+			::std::cout << "line: " << event.line_offset()
+				    << "  type: " << ::std::setw(7)
+				    << ::std::left << edge_event_type_str(event)
+				    << "  event #" << event.line_seqno()
 				    << ::std::endl;
 	}
-
-	return EXIT_SUCCESS;
 }
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [libgpiod][PATCH 4/8] bindings: cxx: examples: replace tools examples with use case examples
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
                   ` (2 preceding siblings ...)
  2023-06-23  4:38 ` [libgpiod][PATCH 3/8] bindings: cxx: examples: consistency cleanup Kent Gibson
@ 2023-06-23  4:38 ` Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 5/8] bindings: python: examples: consistency cleanup Kent Gibson
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:38 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

Replace tool examples with use case examples drawn from the tools.

Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
 bindings/cxx/examples/.gitignore              | 16 +++--
 bindings/cxx/examples/Makefile.am             | 42 +++++++-----
 bindings/cxx/examples/find_line_by_name.cpp   | 42 ++++++++++++
 bindings/cxx/examples/get_chip_info.cpp       | 27 ++++++++
 bindings/cxx/examples/get_line_info.cpp       | 39 +++++++++++
 .../cxx/examples/get_multiple_line_values.cpp | 40 ++++++++++++
 bindings/cxx/examples/gpiodetectcxx.cpp       | 30 ---------
 bindings/cxx/examples/gpiofindcxx.cpp         | 32 ---------
 bindings/cxx/examples/gpiogetcxx.cpp          | 40 ------------
 bindings/cxx/examples/gpioinfocxx.cpp         | 61 -----------------
 bindings/cxx/examples/gpiomoncxx.cpp          | 65 -------------------
 bindings/cxx/examples/gpionotifycxx.cpp       | 55 ----------------
 bindings/cxx/examples/gpiosetcxx.cpp          | 53 ---------------
 .../examples/reconfigure_input_to_output.cpp  | 56 ++++++++++++++++
 .../examples/toggle_multiple_line_values.cpp  | 63 ++++++++++++++++++
 bindings/cxx/examples/watch_line_info.cpp     | 49 ++++++++++++++
 bindings/cxx/examples/watch_line_rising.cpp   | 64 ++++++++++++++++++
 .../examples/watch_multiple_line_values.cpp   | 60 +++++++++++++++++
 18 files changed, 473 insertions(+), 361 deletions(-)
 create mode 100644 bindings/cxx/examples/find_line_by_name.cpp
 create mode 100644 bindings/cxx/examples/get_chip_info.cpp
 create mode 100644 bindings/cxx/examples/get_line_info.cpp
 create mode 100644 bindings/cxx/examples/get_multiple_line_values.cpp
 delete mode 100644 bindings/cxx/examples/gpiodetectcxx.cpp
 delete mode 100644 bindings/cxx/examples/gpiofindcxx.cpp
 delete mode 100644 bindings/cxx/examples/gpiogetcxx.cpp
 delete mode 100644 bindings/cxx/examples/gpioinfocxx.cpp
 delete mode 100644 bindings/cxx/examples/gpiomoncxx.cpp
 delete mode 100644 bindings/cxx/examples/gpionotifycxx.cpp
 delete mode 100644 bindings/cxx/examples/gpiosetcxx.cpp
 create mode 100644 bindings/cxx/examples/reconfigure_input_to_output.cpp
 create mode 100644 bindings/cxx/examples/toggle_multiple_line_values.cpp
 create mode 100644 bindings/cxx/examples/watch_line_info.cpp
 create mode 100644 bindings/cxx/examples/watch_line_rising.cpp
 create mode 100644 bindings/cxx/examples/watch_multiple_line_values.cpp

diff --git a/bindings/cxx/examples/.gitignore b/bindings/cxx/examples/.gitignore
index 268b3f6..0f9b39e 100644
--- a/bindings/cxx/examples/.gitignore
+++ b/bindings/cxx/examples/.gitignore
@@ -1,14 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 # SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
 
-gpiodetectcxx
-gpiofindcxx
-gpiogetcxx
-gpioinfocxx
-gpiomoncxx
-gpionotifycxx
-gpiosetcxx
 async_watch_line_value
+find_line_by_name
+get_chip_info
+get_line_info
 get_line_value
+get_multiple_line_values
+reconfigure_input_to_output
 toggle_line_value
+toggle_multiple_line_values
+watch_line_info
+watch_line_rising
 watch_line_value
+watch_multiple_line_values
diff --git a/bindings/cxx/examples/Makefile.am b/bindings/cxx/examples/Makefile.am
index 0213973..64ced20 100644
--- a/bindings/cxx/examples/Makefile.am
+++ b/bindings/cxx/examples/Makefile.am
@@ -6,36 +6,42 @@ AM_CXXFLAGS += -Wall -Wextra -g -std=gnu++17
 AM_LDFLAGS = -lgpiodcxx -L$(top_builddir)/bindings/cxx/
 
 noinst_PROGRAMS = \
-	gpiodetectcxx \
-	gpiofindcxx \
-	gpiogetcxx \
-	gpioinfocxx \
-	gpiomoncxx \
-	gpionotifycxx \
-	gpiosetcxx \
 	async_watch_line_value \
+	find_line_by_name \
+	get_chip_info \
+	get_line_info \
 	get_line_value \
+	get_multiple_line_values \
+	reconfigure_input_to_output \
 	toggle_line_value \
-	watch_line_value
+	toggle_multiple_line_values \
+	watch_line_info \
+	watch_line_rising \
+	watch_line_value \
+	watch_multiple_line_values
 
-gpiodetectcxx_SOURCES = gpiodetectcxx.cpp
+async_watch_line_value_SOURCES = async_watch_line_value.cpp
 
-gpiofindcxx_SOURCES = gpiofindcxx.cpp
+find_line_by_name_SOURCES = find_line_by_name.cpp
 
-gpiogetcxx_SOURCES = gpiogetcxx.cpp
+get_chip_info_SOURCES = get_chip_info.cpp
 
-gpioinfocxx_SOURCES = gpioinfocxx.cpp
+get_line_info_SOURCES = get_line_info.cpp
 
-gpiomoncxx_SOURCES = gpiomoncxx.cpp
+get_line_value_SOURCES = get_line_value.cpp
 
-gpionotifycxx_SOURCES = gpionotifycxx.cpp
+get_multiple_line_values_SOURCES = get_multiple_line_values.cpp
 
-gpiosetcxx_SOURCES = gpiosetcxx.cpp
+reconfigure_input_to_output_SOURCES = reconfigure_input_to_output.cpp
 
-async_watch_line_value_SOURCES = async_watch_line_value.cpp
+toggle_line_value_SOURCES = toggle_line_value.cpp
 
-get_line_value_SOURCES = get_line_value.cpp
+toggle_multiple_line_values_SOURCES = toggle_multiple_line_values.cpp
 
-toggle_line_value_SOURCES = toggle_line_value.cpp
+watch_line_info_SOURCES = watch_line_info.cpp
 
 watch_line_value_SOURCES = watch_line_value.cpp
+
+watch_line_rising_SOURCES = watch_line_rising.cpp
+
+watch_multiple_line_values_SOURCES = watch_multiple_line_values.cpp
diff --git a/bindings/cxx/examples/find_line_by_name.cpp b/bindings/cxx/examples/find_line_by_name.cpp
new file mode 100644
index 0000000..4529ed6
--- /dev/null
+++ b/bindings/cxx/examples/find_line_by_name.cpp
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of finding a line with the given name. */
+
+#include <cstdlib>
+#include <filesystem>
+#include <gpiod.hpp>
+#include <iostream>
+
+namespace
+{
+
+/* Example configuration - customize to suit your situation */
+const ::std::string line_name = "GPIO19";
+
+} /* namespace */
+
+int main(void)
+{
+	/*
+	 * Names are not guaranteed unique, so this finds the first line with
+	 * the given name.
+	 */
+	for (const auto &entry :
+	     ::std::filesystem::directory_iterator("/dev/")) {
+		if (::gpiod::is_gpiochip_device(entry.path())) {
+			::gpiod::chip chip(entry.path());
+
+			auto offset = chip.get_line_offset_from_name(line_name);
+			if (offset >= 0) {
+				::std::cout << line_name << ": "
+					    << chip.get_info().name() << " "
+					    << offset << ::std::endl;
+				return EXIT_SUCCESS;
+			}
+		}
+	}
+	::std::cout << "line '" << line_name << "' not found" << ::std::endl;
+
+	return EXIT_FAILURE;
+}
diff --git a/bindings/cxx/examples/get_chip_info.cpp b/bindings/cxx/examples/get_chip_info.cpp
new file mode 100644
index 0000000..073a6c3
--- /dev/null
+++ b/bindings/cxx/examples/get_chip_info.cpp
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of reading the info for a chip. */
+
+#include <cstdlib>
+#include <filesystem>
+#include <gpiod.hpp>
+#include <iostream>
+
+namespace {
+
+/* Example configuration - customize to suit your situation */
+const ::std::filesystem::path chip_path("/dev/gpiochip0");
+
+} /* namespace */
+
+int main(void)
+{
+	::gpiod::chip chip(chip_path);
+	auto info = chip.get_info();
+
+	::std::cout << info.name() << " [" << info.label() << "] ("
+		    << info.num_lines() << " lines)" << ::std::endl;
+
+	return EXIT_SUCCESS;
+}
diff --git a/bindings/cxx/examples/get_line_info.cpp b/bindings/cxx/examples/get_line_info.cpp
new file mode 100644
index 0000000..f2f071e
--- /dev/null
+++ b/bindings/cxx/examples/get_line_info.cpp
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of reading the info for a line. */
+
+#include <cstdlib>
+#include <filesystem>
+#include <gpiod.hpp>
+#include <iomanip>
+#include <iostream>
+
+namespace {
+
+/* Example configuration - customize to suit your situation */
+const ::std::filesystem::path chip_path("/dev/gpiochip0");
+const ::gpiod::line::offset line_offset = 3;
+
+} /* namespace */
+
+int main(void)
+{
+	auto chip = ::gpiod::chip(chip_path);
+	auto info = chip.get_line_info(line_offset);
+
+	::std::cout << "line " << ::std::setw(3) << info.offset() << ": "
+		    << ::std::setw(12)
+		    << (info.name().empty() ? "unnamed" : info.name()) << " "
+		    << ::std::setw(12)
+		    << (info.consumer().empty() ? "unused" : info.consumer())
+		    << " " << ::std::setw(8)
+		    << (info.direction() == ::gpiod::line::direction::INPUT ?
+				"input" :
+				"output")
+		    << " " << ::std::setw(10)
+		    << (info.active_low() ? "active-low" : "active-high")
+		    << ::std::endl;
+
+	return EXIT_SUCCESS;
+}
diff --git a/bindings/cxx/examples/get_multiple_line_values.cpp b/bindings/cxx/examples/get_multiple_line_values.cpp
new file mode 100644
index 0000000..d1f22e7
--- /dev/null
+++ b/bindings/cxx/examples/get_multiple_line_values.cpp
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of reading multiple lines. */
+
+#include <cstdlib>
+#include <gpiod.hpp>
+#include <iostream>
+
+namespace {
+
+/* Example configuration - customize to suit your situation */
+const ::std::filesystem::path chip_path("/dev/gpiochip0");
+const ::gpiod::line::offsets line_offsets = { 5, 3, 7 };
+
+} /* namespace */
+
+int main(void)
+{
+	auto request = ::gpiod::chip(chip_path)
+			       .prepare_request()
+			       .set_consumer("get-multiple-line-values")
+			       .add_line_settings(
+				       line_offsets,
+				       ::gpiod::line_settings().set_direction(
+					       ::gpiod::line::direction::INPUT))
+			       .do_request();
+
+	auto values = request.get_values();
+
+	for (size_t i = 0; i < line_offsets.size(); i++)
+		::std::cout << line_offsets[i] << "="
+			    << (values[i] == ::gpiod::line::value::ACTIVE ?
+					"Active" :
+					"Inactive")
+			    << ' ';
+	::std::cout << ::std::endl;
+
+	return EXIT_SUCCESS;
+}
diff --git a/bindings/cxx/examples/gpiodetectcxx.cpp b/bindings/cxx/examples/gpiodetectcxx.cpp
deleted file mode 100644
index 7dbb0e0..0000000
--- a/bindings/cxx/examples/gpiodetectcxx.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* C++ reimplementation of the gpiodetect tool. */
-
-#include <cstdlib>
-#include <filesystem>
-#include <gpiod.hpp>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc != 1) {
-		::std::cerr << "usage: " << argv[0] << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
-		if (::gpiod::is_gpiochip_device(entry.path())) {
-			::gpiod::chip chip(entry.path());
-			auto info = chip.get_info();
-
-			::std::cout << info.name() << " [" <<
-				       info.label() << "] (" <<
-				       info.num_lines() << " lines)" << ::std::endl;
-		}
-	}
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpiofindcxx.cpp b/bindings/cxx/examples/gpiofindcxx.cpp
deleted file mode 100644
index cd36be7..0000000
--- a/bindings/cxx/examples/gpiofindcxx.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* C++ reimplementation of the gpiofind tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <filesystem>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc != 2) {
-		::std::cerr << "usage: " << argv[0] << " <line name>" << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
-		if (::gpiod::is_gpiochip_device(entry.path())) {
-			::gpiod::chip chip(entry.path());
-
-			auto offset = chip.get_line_offset_from_name(argv[1]);
-			if (offset >= 0) {
-				::std::cout << chip.get_info().name() << " " << offset << ::std::endl;
-				return EXIT_SUCCESS;
-			}
-		}
-	}
-
-	return EXIT_FAILURE;
-}
diff --git a/bindings/cxx/examples/gpiogetcxx.cpp b/bindings/cxx/examples/gpiogetcxx.cpp
deleted file mode 100644
index b0d4a7d..0000000
--- a/bindings/cxx/examples/gpiogetcxx.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* Simplified C++ reimplementation of the gpioget tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc < 3) {
-		::std::cerr << "usage: " << argv[0] << " <chip> <line_offset0> ..." << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	::gpiod::line::offsets offsets;
-
-	for (int i = 2; i < argc; i++)
-		offsets.push_back(::std::stoul(argv[i]));
-
-	auto request = ::gpiod::chip(argv[1])
-		.prepare_request()
-		.set_consumer("gpiogetcxx")
-		.add_line_settings(
-			offsets,
-			::gpiod::line_settings()
-				.set_direction(::gpiod::line::direction::INPUT)
-		)
-		.do_request();
-
-	auto vals = request.get_values();
-
-	for (auto& it: vals)
-		::std::cout << (it == ::gpiod::line::value::ACTIVE ? "1" : "0") << ' ';
-	::std::cout << ::std::endl;
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpioinfocxx.cpp b/bindings/cxx/examples/gpioinfocxx.cpp
deleted file mode 100644
index 3612092..0000000
--- a/bindings/cxx/examples/gpioinfocxx.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* Simplified C++ reimplementation of the gpioinfo tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <filesystem>
-#include <iostream>
-
-namespace {
-
-void show_chip(const ::gpiod::chip& chip)
-{
-	auto info = chip.get_info();
-
-	::std::cout << info.name() << " - " << info.num_lines() << " lines:" << ::std::endl;
-
-	for (unsigned int offset = 0; offset < info.num_lines(); offset++) {
-		auto info = chip.get_line_info(offset);
-
-		::std::cout << "\tline ";
-		::std::cout.width(3);
-		::std::cout << info.offset() << ": ";
-
-		::std::cout.width(12);
-		::std::cout << (info.name().empty() ? "unnamed" : info.name());
-		::std::cout << " ";
-
-		::std::cout.width(12);
-		::std::cout << (info.consumer().empty() ? "unused" : info.consumer());
-		::std::cout << " ";
-
-		::std::cout.width(8);
-		::std::cout << (info.direction() == ::gpiod::line::direction::INPUT ? "input" : "output");
-		::std::cout << " ";
-
-		::std::cout.width(10);
-		::std::cout << (info.active_low() ? "active-low" : "active-high");
-
-		::std::cout << ::std::endl;
-	}
-}
-
-} /* namespace */
-
-int main(int argc, char **argv)
-{
-	if (argc != 1) {
-		::std::cerr << "usage: " << argv[0] << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
-		if (::gpiod::is_gpiochip_device(entry.path()))
-			show_chip(::gpiod::chip(entry.path()));
-	}
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpiomoncxx.cpp b/bindings/cxx/examples/gpiomoncxx.cpp
deleted file mode 100644
index 8325bf8..0000000
--- a/bindings/cxx/examples/gpiomoncxx.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* Simplified C++ reimplementation of the gpiomon tool. */
-
-#include <cstdlib>
-#include <gpiod.hpp>
-#include <iostream>
-
-namespace {
-
-void print_event(const ::gpiod::edge_event& event)
-{
-	if (event.type() == ::gpiod::edge_event::event_type::RISING_EDGE)
-		::std::cout << " RISING EDGE";
-	else
-		::std::cout << "FALLING EDGE";
-
-	::std::cout << " ";
-
-	::std::cout << event.timestamp_ns() / 1000000000;
-	::std::cout << ".";
-	::std::cout << event.timestamp_ns() % 1000000000;
-
-	::std::cout << " line: " << event.line_offset();
-
-	::std::cout << ::std::endl;
-}
-
-} /* namespace */
-
-int main(int argc, char **argv)
-{
-	if (argc < 3) {
-		::std::cout << "usage: " << argv[0] << " <chip> <offset0> ..." << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	::gpiod::line::offsets offsets;
-	offsets.reserve(argc - 2);
-	for (int i = 2; i < argc; i++)
-		offsets.push_back(::std::stoul(argv[i]));
-
-	auto request = ::gpiod::chip(argv[1])
-		.prepare_request()
-		.set_consumer("gpiomoncxx")
-		.add_line_settings(
-			offsets,
-			::gpiod::line_settings()
-				.set_direction(::gpiod::line::direction::INPUT)
-				.set_edge_detection(::gpiod::line::edge::BOTH)
-		)
-		.do_request();
-
-	::gpiod::edge_event_buffer buffer;
-
-	for (;;) {
-		request.read_edge_events(buffer);
-
-		for (const auto& event: buffer)
-			print_event(event);
-	}
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpionotifycxx.cpp b/bindings/cxx/examples/gpionotifycxx.cpp
deleted file mode 100644
index 668734c..0000000
--- a/bindings/cxx/examples/gpionotifycxx.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-
-/* Simplified C++ reimplementation of the gpionotify tool. */
-
-#include <cstdlib>
-#include <gpiod.hpp>
-#include <iostream>
-
-namespace {
-
-void print_event(const ::gpiod::info_event& event)
-{
-	switch (event.type()) {
-	case ::gpiod::info_event::event_type::LINE_REQUESTED:
-		::std::cout << "LINE REQUESTED";
-		break;
-	case ::gpiod::info_event::event_type::LINE_RELEASED:
-		::std::cout << "LINE RELEASED";
-		break;
-	case ::gpiod::info_event::event_type::LINE_CONFIG_CHANGED:
-		::std::cout << "CONFIG CHANGED";
-		break;
-	}
-
-	::std::cout << " ";
-
-	::std::cout << event.timestamp_ns() / 1000000000;
-	::std::cout << ".";
-	::std::cout << event.timestamp_ns() % 1000000000;
-
-	::std::cout << " line: " << event.get_line_info().offset();
-
-	::std::cout << ::std::endl;
-}
-
-} /* namespace */
-
-int main(int argc, char **argv)
-{
-	if (argc < 3) {
-		::std::cout << "usage: " << argv[0] << " <chip> <offset0> ..." << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	::gpiod::chip chip(argv[1]);
-
-	for (int i = 2; i < argc; i++)
-		chip.watch_line_info(::std::stoul(argv[i]));
-
-	for (;;)
-		print_event(chip.read_info_event());
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpiosetcxx.cpp b/bindings/cxx/examples/gpiosetcxx.cpp
deleted file mode 100644
index f46cb85..0000000
--- a/bindings/cxx/examples/gpiosetcxx.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* Simplified C++ reimplementation of the gpioset tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc < 3) {
-		::std::cerr << "usage: " << argv[0] <<
-			       " <chip> <line_offset0>=<value0> ..." << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	::gpiod::line::offsets offsets;
-	::gpiod::line::values values;
-
-	for (int i = 2; i < argc; i++) {
-		::std::string arg(argv[i]);
-
-		size_t pos = arg.find('=');
-
-		::std::string offset(arg.substr(0, pos));
-		::std::string value(arg.substr(pos + 1, ::std::string::npos));
-
-		if (offset.empty() || value.empty())
-			throw ::std::invalid_argument("invalid offset=value mapping: " +
-						      ::std::string(argv[i]));
-
-		offsets.push_back(::std::stoul(offset));
-		values.push_back(::std::stoul(value) ? ::gpiod::line::value::ACTIVE :
-						       ::gpiod::line::value::INACTIVE);
-	}
-
-	auto request = ::gpiod::chip(argv[1])
-		.prepare_request()
-		.set_consumer("gpiosetcxx")
-		.add_line_settings(
-			offsets,
-			::gpiod::line_settings()
-				.set_direction(::gpiod::line::direction::OUTPUT)
-		)
-		.set_output_values(values)
-		.do_request();
-
-	::std::cin.get();
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/reconfigure_input_to_output.cpp b/bindings/cxx/examples/reconfigure_input_to_output.cpp
new file mode 100644
index 0000000..7d7e75c
--- /dev/null
+++ b/bindings/cxx/examples/reconfigure_input_to_output.cpp
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of requesting a line intended for bi-directional use as input and then switching to output. */
+
+#include <cstdlib>
+#include <filesystem>
+#include <gpiod.hpp>
+#include <iostream>
+
+namespace
+{
+
+/* Example configuration - customize to suit your situation */
+const ::std::filesystem::path chip_path("/dev/gpiochip0");
+const ::gpiod::line::offset line_offset = 5;
+
+} /* namespace */
+
+int main(void)
+{
+	/* request the line initially as an input */
+	auto request = ::gpiod::chip(chip_path)
+			       .prepare_request()
+			       .set_consumer("reconfigure-input-to-output")
+			       .add_line_settings(
+				       line_offset,
+				       ::gpiod::line_settings().set_direction(
+					       ::gpiod::line::direction::INPUT))
+			       .do_request();
+
+	/* read the current line value */
+	::std::cout << line_offset << "="
+		    << (request.get_value(line_offset) ==
+					::gpiod::line::value::ACTIVE ?
+				"Active" :
+				"Inactive")
+		    << " (input)" << ::std::endl;
+
+	/* switch the line to an output and drive it low */
+	request.reconfigure_lines(::gpiod::line_config().add_line_settings(
+		line_offset,
+		::gpiod::line_settings()
+			.set_direction(::gpiod::line::direction::OUTPUT)
+			.set_output_value(::gpiod::line::value::INACTIVE)));
+
+	/* report the current driven value */
+	::std::cout << line_offset << "="
+		    << (request.get_value(line_offset) ==
+					::gpiod::line::value::ACTIVE ?
+				"Active" :
+				"Inactive")
+		    << " (output)" << ::std::endl;
+
+	return EXIT_SUCCESS;
+}
diff --git a/bindings/cxx/examples/toggle_multiple_line_values.cpp b/bindings/cxx/examples/toggle_multiple_line_values.cpp
new file mode 100644
index 0000000..a5b84bf
--- /dev/null
+++ b/bindings/cxx/examples/toggle_multiple_line_values.cpp
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of toggling multiple lines. */
+
+#include <cstdlib>
+#include <gpiod.hpp>
+#include <iostream>
+#include <thread>
+
+namespace {
+
+/* Example configuration - customize to suit your situation */
+const ::std::filesystem::path chip_path("/dev/gpiochip0");
+const ::gpiod::line::offsets line_offsets = { 5, 3, 7 };
+
+::gpiod::line::value toggle_value(::gpiod::line::value v)
+{
+	return (v == ::gpiod::line::value::ACTIVE) ?
+		       ::gpiod::line::value::INACTIVE :
+		       ::gpiod::line::value::ACTIVE;
+}
+
+void toggle_values(::gpiod::line::values &values)
+{
+	for (size_t i = 0; i < values.size(); i++)
+		values[i] = toggle_value(values[i]);
+}
+
+void print_values(::gpiod::line::offsets const &offsets,
+		  ::gpiod::line::values const &values)
+{
+	for (size_t i = 0; i < offsets.size(); i++)
+		::std::cout << offsets[i] << "=" << values[i] << ' ';
+	::std::cout << ::std::endl;
+}
+
+} /* namespace */
+
+int main(void)
+{
+	::gpiod::line::values values = { ::gpiod::line::value::ACTIVE,
+					 ::gpiod::line::value::ACTIVE,
+					 ::gpiod::line::value::INACTIVE };
+
+	auto request =
+		::gpiod::chip(chip_path)
+			.prepare_request()
+			.set_consumer("toggle-multiple-line-values")
+			.add_line_settings(
+				line_offsets,
+				::gpiod::line_settings().set_direction(
+					::gpiod::line::direction::OUTPUT))
+			.set_output_values(values)
+			.do_request();
+
+	for (;;) {
+		print_values(line_offsets, values);
+		std::this_thread::sleep_for(std::chrono::seconds(1));
+		toggle_values(values);
+		request.set_values(line_offsets, values);
+	}
+}
diff --git a/bindings/cxx/examples/watch_line_info.cpp b/bindings/cxx/examples/watch_line_info.cpp
new file mode 100644
index 0000000..fe37f18
--- /dev/null
+++ b/bindings/cxx/examples/watch_line_info.cpp
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of watching for requests on particular lines. */
+
+#include <cstdlib>
+#include <gpiod.hpp>
+#include <iomanip>
+#include <iostream>
+
+namespace {
+
+/* Example configuration - customize to suit your situation. */
+const ::std::filesystem::path chip_path("/dev/gpiochip0");
+const ::gpiod::line::offsets line_offsets = { 5, 3, 7 };
+
+const char *event_type(const ::gpiod::info_event &event)
+{
+	switch (event.type()) {
+	case ::gpiod::info_event::event_type::LINE_REQUESTED:
+		return "Requested";
+	case ::gpiod::info_event::event_type::LINE_RELEASED:
+		return "Released";
+	case ::gpiod::info_event::event_type::LINE_CONFIG_CHANGED:
+		return "Reconfig";
+	default:
+		return "Unknown";
+	}
+}
+
+} /* namespace */
+
+int main(void)
+{
+	::gpiod::chip chip(chip_path);
+	for (auto offset :line_offsets) {
+		chip.watch_line_info(offset);
+	}
+
+	for (;;) {
+		/* Blocks until at least one event is available */
+		auto event = chip.read_info_event();
+		::std::cout << "line: " << event.get_line_info().offset() << " "
+			    << ::std::setw(9) << ::std::left
+			    << event_type(event) << " "
+			    << event.timestamp_ns() / 1000000000 << "."
+			    << event.timestamp_ns() % 1000000000 << ::std::endl;
+	}
+}
diff --git a/bindings/cxx/examples/watch_line_rising.cpp b/bindings/cxx/examples/watch_line_rising.cpp
new file mode 100644
index 0000000..d773063
--- /dev/null
+++ b/bindings/cxx/examples/watch_line_rising.cpp
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of watching for rising edges on a single line. */
+
+#include <cstdlib>
+#include <filesystem>
+#include <gpiod.hpp>
+#include <iomanip>
+#include <iostream>
+
+namespace {
+
+/* Example configuration - customize to suit your situation. */
+const ::std::filesystem::path chip_path("/dev/gpiochip0");
+const ::gpiod::line::offset line_offset = 5;
+
+const char *edge_event_type_str(const ::gpiod::edge_event &event)
+{
+	switch (event.type()) {
+	case ::gpiod::edge_event::event_type::RISING_EDGE:
+		return "Rising";
+	case ::gpiod::edge_event::event_type::FALLING_EDGE:
+		return "Falling";
+	default:
+		return "Unknown";
+	}
+}
+
+} /* namespace */
+
+int main(void)
+{
+	auto request =
+		::gpiod::chip(chip_path)
+			.prepare_request()
+			.set_consumer("watch-line-value")
+			.add_line_settings(
+				line_offset,
+				::gpiod::line_settings()
+					.set_direction(
+						::gpiod::line::direction::INPUT)
+					.set_edge_detection(
+						::gpiod::line::edge::RISING)
+)
+			.do_request();
+
+	/*
+	 * 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.
+	 */
+	::gpiod::edge_event_buffer buffer(1);
+
+	for (;;) {
+		/* Blocks until at least one event is available. */
+		request.read_edge_events(buffer);
+
+		for (const auto &event : buffer)
+			::std::cout << "line: " << event.line_offset()
+				    << "  type: " << ::std::setw(7) << ::std::left << edge_event_type_str(event)
+				    << "  event #" << event.line_seqno()
+				    << ::std::endl;
+	}
+}
diff --git a/bindings/cxx/examples/watch_multiple_line_values.cpp b/bindings/cxx/examples/watch_multiple_line_values.cpp
new file mode 100644
index 0000000..42b7213
--- /dev/null
+++ b/bindings/cxx/examples/watch_multiple_line_values.cpp
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+/* Minimal example of watching for edges on multiple lines. */
+
+#include <cstdlib>
+#include <gpiod.hpp>
+#include <iomanip>
+#include <iostream>
+
+namespace {
+
+/* Example configuration - customize to suit your situation */
+const ::std::filesystem::path chip_path("/dev/gpiochip0");
+const ::gpiod::line::offsets line_offsets = { 5, 3, 7 };
+
+const char *edge_event_type_str(const ::gpiod::edge_event &event)
+{
+	switch (event.type()) {
+	case ::gpiod::edge_event::event_type::RISING_EDGE:
+		return "Rising";
+	case ::gpiod::edge_event::event_type::FALLING_EDGE:
+		return "Falling";
+	default:
+		return "Unknown";
+	}
+}
+
+} /* namespace */
+
+int main(void)
+{
+	auto request =
+		::gpiod::chip(chip_path)
+			.prepare_request()
+			.set_consumer("watch-multiple-line-values")
+			.add_line_settings(
+				line_offsets,
+				::gpiod::line_settings()
+					.set_direction(
+						::gpiod::line::direction::INPUT)
+					.set_edge_detection(
+						::gpiod::line::edge::BOTH))
+			.do_request();
+
+	::gpiod::edge_event_buffer buffer;
+
+	for (;;) {
+		/* Blocks until at leat one event available */
+		request.read_edge_events(buffer);
+
+		for (const auto &event : buffer)
+			::std::cout << "offset: " << event.line_offset()
+				    << "  type: " << ::std::setw(7)
+				    << ::std::left << edge_event_type_str(event)
+				    << "  event #" << event.global_seqno()
+				    << "  line event #" << event.line_seqno()
+				    << ::std::endl;
+	}
+}
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [libgpiod][PATCH 5/8] bindings: python: examples: consistency cleanup
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
                   ` (3 preceding siblings ...)
  2023-06-23  4:38 ` [libgpiod][PATCH 4/8] bindings: cxx: examples: replace tools examples with use case examples Kent Gibson
@ 2023-06-23  4:38 ` Kent Gibson
  2023-06-23  4:38 ` [libgpiod][PATCH 6/8] bindings: python: examples: replace tools examples with use case examples Kent Gibson
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:38 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

A collection of minor changes to be more consistent with other examples:
 - capitalize comments
 - add line offset to value outputs
 - drop comma from edge event outputs
 - improve behaviour if run on a platform that does not match the
   example configuration
 - use with to cleanup request in toggle_line_value.py

Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
 .../python/examples/async_watch_line_value.py | 15 ++++----
 bindings/python/examples/get_line_value.py    | 13 ++++---
 bindings/python/examples/toggle_line_value.py | 34 +++++++------------
 bindings/python/examples/watch_line_value.py  | 19 +++++------
 4 files changed, 35 insertions(+), 46 deletions(-)

diff --git a/bindings/python/examples/async_watch_line_value.py b/bindings/python/examples/async_watch_line_value.py
index ed09ec9..ea8314f 100755
--- a/bindings/python/examples/async_watch_line_value.py
+++ b/bindings/python/examples/async_watch_line_value.py
@@ -19,12 +19,8 @@ def edge_type(event):
     return "Unknown"
 
 
-def async_watch_line_value():
-    # example configuration - customise to suit your situation
-    chip_path = "/dev/gpiochip0"
-    line_offset = 5
-
-    # assume a button connecting the pin to ground,
+def async_watch_line_value(chip_path, line_offset):
+    # Assume a button connecting the pin to ground,
     # so pull it up and provide some debounce.
     with gpiod.request_lines(
         chip_path,
@@ -40,7 +36,7 @@ def async_watch_line_value():
         poll = select.poll()
         poll.register(request.fd, select.POLLIN)
         while True:
-            # other fds could be registered with the poll and be handled
+            # Other fds could be registered with the poll and be handled
             # separately using the return value (fd, event) from poll()
             poll.poll()
             for event in request.read_edge_events():
@@ -51,4 +47,7 @@ def async_watch_line_value():
 
 
 if __name__ == "__main__":
-    async_watch_line_value()
+    try:
+        async_watch_line_value("/dev/gpiochip0", 5)
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/get_line_value.py b/bindings/python/examples/get_line_value.py
index ab733df..f3ca13b 100755
--- a/bindings/python/examples/get_line_value.py
+++ b/bindings/python/examples/get_line_value.py
@@ -9,19 +9,18 @@ import gpiod
 from gpiod.line import Direction
 
 
-def get_line_value():
-    # example configuration - customise to suit your situation
-    chip_path = "/dev/gpiochip0"
-    line_offset = 5
-
+def get_line_value(chip_path, line_offset):
     with gpiod.request_lines(
         chip_path,
         consumer="get-line-value",
         config={line_offset: gpiod.LineSettings(direction=Direction.INPUT)},
     ) as request:
         value = request.get_value(line_offset)
-        print(value)
+        print("{}={}".format(line_offset, value))
 
 
 if __name__ == "__main__":
-    get_line_value()
+    try:
+        get_line_value("/dev/gpiochip0", 5)
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/toggle_line_value.py b/bindings/python/examples/toggle_line_value.py
index 46e52f9..e0de8fb 100755
--- a/bindings/python/examples/toggle_line_value.py
+++ b/bindings/python/examples/toggle_line_value.py
@@ -16,21 +16,11 @@ def toggle_value(value):
     return Value.INACTIVE
 
 
-def print_value(value):
-    if value == Value.ACTIVE:
-        print("Active")
-    else:
-        print("Inactive")
-
-
-def toggle_line_value():
-    # example configuration - customise to suit your situation
-    chip_path = "/dev/gpiochip0"
-    line_offset = 5
-
+def toggle_line_value(chip_path, line_offset):
+    value_str = {Value.ACTIVE: "Active", Value.INACTIVE: "Inactive"}
     value = Value.ACTIVE
 
-    request = gpiod.request_lines(
+    with gpiod.request_lines(
         chip_path,
         consumer="toggle-line-value",
         config={
@@ -38,14 +28,16 @@ def toggle_line_value():
                 direction=Direction.OUTPUT, output_value=value
             )
         },
-    )
-
-    while True:
-        print_value(value)
-        time.sleep(1)
-        value = toggle_value(value)
-        request.set_value(line_offset, value)
+    ) as request:
+        while True:
+            print("{}={}".format(line_offset, value_str[value]))
+            time.sleep(1)
+            value = toggle_value(value)
+            request.set_value(line_offset, value)
 
 
 if __name__ == "__main__":
-    toggle_line_value()
+    try:
+        toggle_line_value("/dev/gpiochip0", 5)
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/watch_line_value.py b/bindings/python/examples/watch_line_value.py
index 42fc0bd..841bf40 100755
--- a/bindings/python/examples/watch_line_value.py
+++ b/bindings/python/examples/watch_line_value.py
@@ -12,18 +12,14 @@ from gpiod.line import Bias, Edge
 
 def edge_type(event):
     if event.event_type is event.Type.RISING_EDGE:
-        return "Rising "
+        return "Rising"
     if event.event_type is event.Type.FALLING_EDGE:
         return "Falling"
     return "Unknown"
 
 
-def watch_line_value():
-    # example configuration - customise to suit your situation
-    chip_path = "/dev/gpiochip0"
-    line_offset = 5
-
-    # assume a button connecting the pin to ground,
+def watch_line_value(chip_path, line_offset):
+    # Assume a button connecting the pin to ground,
     # so pull it up and provide some debounce.
     with gpiod.request_lines(
         chip_path,
@@ -37,13 +33,16 @@ def watch_line_value():
         },
     ) as request:
         while True:
-            # blocks until at least one event is available
+            # Blocks until at least one event is available
             for event in request.read_edge_events():
                 print(
-                    "offset: %d, type: %s, event #%d"
+                    "line: %d  type: %-7s  event #%d"
                     % (event.line_offset, edge_type(event), event.line_seqno)
                 )
 
 
 if __name__ == "__main__":
-    watch_line_value()
+    try:
+        watch_line_value("/dev/gpiochip0", 5)
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [libgpiod][PATCH 6/8] bindings: python: examples: replace tools examples with use case examples
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
                   ` (4 preceding siblings ...)
  2023-06-23  4:38 ` [libgpiod][PATCH 5/8] bindings: python: examples: consistency cleanup Kent Gibson
@ 2023-06-23  4:38 ` Kent Gibson
  2023-06-23 19:31   ` Bartosz Golaszewski
  2023-06-23  4:39 ` [libgpiod][PATCH 7/8] bindings: rust: examples: consistency cleanup Kent Gibson
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:38 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

Replace tool examples with use case examples drawn from the tools.

Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
 bindings/python/examples/Makefile.am          | 18 +++----
 bindings/python/examples/find_line_by_name.py | 37 +++++++++++++++
 bindings/python/examples/get_chip_info.py     | 20 ++++++++
 bindings/python/examples/get_line_info.py     | 29 ++++++++++++
 .../examples/get_multiple_line_values.py      | 29 ++++++++++++
 bindings/python/examples/gpiodetect.py        | 15 ------
 bindings/python/examples/gpiofind.py          | 20 --------
 bindings/python/examples/gpioget.py           | 29 ------------
 bindings/python/examples/gpioinfo.py          | 28 -----------
 bindings/python/examples/gpiomon.py           | 26 ----------
 bindings/python/examples/gpionotify.py        | 21 ---------
 bindings/python/examples/gpioset.py           | 36 --------------
 bindings/python/examples/helpers.py           | 15 ------
 .../examples/reconfigure_input_to_output.py   | 39 +++++++++++++++
 .../examples/toggle_multiple_line_values.py   | 47 +++++++++++++++++++
 bindings/python/examples/watch_line_info.py   | 23 +++++++++
 bindings/python/examples/watch_line_rising.py | 31 ++++++++++++
 .../examples/watch_multiple_line_values.py    | 43 +++++++++++++++++
 18 files changed, 308 insertions(+), 198 deletions(-)
 create mode 100755 bindings/python/examples/find_line_by_name.py
 create mode 100755 bindings/python/examples/get_chip_info.py
 create mode 100755 bindings/python/examples/get_line_info.py
 create mode 100755 bindings/python/examples/get_multiple_line_values.py
 delete mode 100755 bindings/python/examples/gpiodetect.py
 delete mode 100755 bindings/python/examples/gpiofind.py
 delete mode 100755 bindings/python/examples/gpioget.py
 delete mode 100755 bindings/python/examples/gpioinfo.py
 delete mode 100755 bindings/python/examples/gpiomon.py
 delete mode 100755 bindings/python/examples/gpionotify.py
 delete mode 100755 bindings/python/examples/gpioset.py
 delete mode 100644 bindings/python/examples/helpers.py
 create mode 100755 bindings/python/examples/reconfigure_input_to_output.py
 create mode 100755 bindings/python/examples/toggle_multiple_line_values.py
 create mode 100755 bindings/python/examples/watch_line_info.py
 create mode 100755 bindings/python/examples/watch_line_rising.py
 create mode 100755 bindings/python/examples/watch_multiple_line_values.py

diff --git a/bindings/python/examples/Makefile.am b/bindings/python/examples/Makefile.am
index c8c1c98..52abafc 100644
--- a/bindings/python/examples/Makefile.am
+++ b/bindings/python/examples/Makefile.am
@@ -3,13 +3,15 @@
 
 EXTRA_DIST = \
 	async_watch_line_value.py \
+	find_line_by_name.py \
+	get_chip_info.py \
+	get_line_info.py \
 	get_line_value.py \
-	gpiodetect.py \
-	gpiofind.py \
-	gpioget.py \
-	gpioinfo.py \
-	gpiomon.py \
-	gpionotify.py \
-	gpioset.py \
+	get_multiple_line_values.py \
+	reconfigure_input_to_output.py \
 	toggle_line_value.py \
-	watch_line_value.py
+	toggle_multiple_line_values.py \
+	watch_line_requests.py \
+	watch_line_value.py \
+	watch_line_rising.py \
+	watch_multiple_line_values.py
diff --git a/bindings/python/examples/find_line_by_name.py b/bindings/python/examples/find_line_by_name.py
new file mode 100755
index 0000000..58f1cd0
--- /dev/null
+++ b/bindings/python/examples/find_line_by_name.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of finding a line with the given name."""
+
+import gpiod
+import os
+
+
+def gpio_chips():
+    for entry in os.scandir("/dev/"):
+        if gpiod.is_gpiochip_device(entry.path):
+            yield entry.path
+
+
+def find_line_by_name(line_name):
+    # Names are not guaranteed unique, so this finds the first line with
+    # the given name.
+    for path in gpio_chips():
+        with gpiod.Chip(path) as chip:
+            try:
+                offset = chip.line_offset_from_id(line_name)
+                print("{}: {} {}".format(line_name, chip.get_info().name, offset))
+                return
+            except OSError:
+                # An OSError is raised if the name is not found.
+                continue
+
+    print("line '{}' not found".format(line_name))
+
+
+if __name__ == "__main__":
+    try:
+        find_line_by_name("GPIO19")
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/get_chip_info.py b/bindings/python/examples/get_chip_info.py
new file mode 100755
index 0000000..7dc76fb
--- /dev/null
+++ b/bindings/python/examples/get_chip_info.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of reading the info for a chip."""
+
+import gpiod
+
+
+def get_chip_info(chip_path):
+    with gpiod.Chip(chip_path) as chip:
+        info = chip.get_info()
+        print("{} [{}] ({} lines)".format(info.name, info.label, info.num_lines))
+
+
+if __name__ == "__main__":
+    try:
+        get_chip_info("/dev/gpiochip0")
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/get_line_info.py b/bindings/python/examples/get_line_info.py
new file mode 100755
index 0000000..cd4ebcc
--- /dev/null
+++ b/bindings/python/examples/get_line_info.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of reading the info for a line."""
+
+import gpiod
+
+
+def get_line_info(chip_path, line_offset):
+    with gpiod.Chip(chip_path) as chip:
+        info = chip.get_line_info(line_offset)
+        is_input = info.direction == gpiod.line.Direction.INPUT
+        print(
+            "line {:>3}: {:>12} {:>12} {:>8} {:>10}".format(
+                info.offset,
+                info.name or "unnamed",
+                info.consumer or "unused",
+                "input" if is_input else "output",
+                "active-low" if info.active_low else "active-high",
+            )
+        )
+
+
+if __name__ == "__main__":
+    try:
+        get_line_info("/dev/gpiochip0", 3)
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/get_multiple_line_values.py b/bindings/python/examples/get_multiple_line_values.py
new file mode 100755
index 0000000..46cf0b2
--- /dev/null
+++ b/bindings/python/examples/get_multiple_line_values.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of reading multiple lines."""
+
+import gpiod
+
+from gpiod.line import Direction
+
+
+def get_multiple_line_values(chip_path, line_offsets):
+    with gpiod.request_lines(
+        chip_path,
+        consumer="get-multiple-line-values",
+        config={tuple(line_offsets): gpiod.LineSettings(direction=Direction.INPUT)},
+    ) as request:
+        vals = request.get_values()
+
+        for offset, val in zip(line_offsets, vals):
+            print("{}={} ".format(offset, val), end="")
+        print()
+
+
+if __name__ == "__main__":
+    try:
+        get_multiple_line_values("/dev/gpiochip0", [5, 3, 7])
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/gpiodetect.py b/bindings/python/examples/gpiodetect.py
deleted file mode 100755
index dc98b03..0000000
--- a/bindings/python/examples/gpiodetect.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
-
-"""Reimplementation of the gpiodetect tool in Python."""
-
-import gpiod
-import os
-
-from helpers import gpio_chips
-
-if __name__ == "__main__":
-    for chip in gpio_chips():
-        info = chip.get_info()
-        print("{} [{}] ({} lines)".format(info.name, info.label, info.num_lines))
diff --git a/bindings/python/examples/gpiofind.py b/bindings/python/examples/gpiofind.py
deleted file mode 100755
index d41660d..0000000
--- a/bindings/python/examples/gpiofind.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
-
-"""Reimplementation of the gpiofind tool in Python."""
-
-import gpiod
-import os
-import sys
-
-if __name__ == "__main__":
-    for entry in os.scandir("/dev/"):
-        if gpiod.is_gpiochip_device(entry.path):
-            with gpiod.Chip(entry.path) as chip:
-                offset = chip.line_offset_from_id(sys.argv[1])
-                if offset is not None:
-                    print("{} {}".format(chip.get_info().name, offset))
-                    sys.exit(0)
-
-    sys.exit(1)
diff --git a/bindings/python/examples/gpioget.py b/bindings/python/examples/gpioget.py
deleted file mode 100755
index bf7e0a6..0000000
--- a/bindings/python/examples/gpioget.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
-
-"""Simplified reimplementation of the gpioget tool in Python."""
-
-import gpiod
-import sys
-
-from gpiod.line import Direction
-
-if __name__ == "__main__":
-    if len(sys.argv) < 3:
-        raise TypeError("usage: gpioget.py <gpiochip> <offset1> <offset2> ...")
-
-    path = sys.argv[1]
-    lines = [int(line) if line.isdigit() else line for line in sys.argv[2:]]
-
-    request = gpiod.request_lines(
-        path,
-        consumer="gpioget.py",
-        config={tuple(lines): gpiod.LineSettings(direction=Direction.INPUT)},
-    )
-
-    vals = request.get_values()
-
-    for val in vals:
-        print("{} ".format(val.value), end="")
-    print()
diff --git a/bindings/python/examples/gpioinfo.py b/bindings/python/examples/gpioinfo.py
deleted file mode 100755
index 3996dcf..0000000
--- a/bindings/python/examples/gpioinfo.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
-
-"""Simplified reimplementation of the gpioinfo tool in Python."""
-
-import gpiod
-import os
-
-from helpers import gpio_chips
-
-if __name__ == "__main__":
-    for chip in gpio_chips():
-        cinfo = chip.get_info()
-        print("{} - {} lines:".format(cinfo.name, cinfo.num_lines))
-
-        for offset in range(0, cinfo.num_lines):
-            linfo = chip.get_line_info(offset)
-            is_input = linfo.direction == gpiod.line.Direction.INPUT
-            print(
-                "\tline {:>3}: {:>18} {:>12} {:>8} {:>10}".format(
-                    linfo.offset,
-                    linfo.name or "unnamed",
-                    linfo.consumer or "unused",
-                    "input" if is_input else "output",
-                    "active-low" if linfo.active_low else "active-high",
-                )
-            )
diff --git a/bindings/python/examples/gpiomon.py b/bindings/python/examples/gpiomon.py
deleted file mode 100755
index 702d7c8..0000000
--- a/bindings/python/examples/gpiomon.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
-
-"""Simplified reimplementation of the gpiomon tool in Python."""
-
-import gpiod
-import sys
-
-from gpiod.line import Edge
-
-if __name__ == "__main__":
-    if len(sys.argv) < 3:
-        raise TypeError("usage: gpiomon.py <gpiochip> <offset1> <offset2> ...")
-
-    path = sys.argv[1]
-    lines = [int(line) if line.isdigit() else line for line in sys.argv[2:]]
-
-    with gpiod.request_lines(
-        path,
-        consumer="gpiomon.py",
-        config={tuple(lines): gpiod.LineSettings(edge_detection=Edge.BOTH)},
-    ) as request:
-        while True:
-            for event in request.read_edge_events():
-                print(event)
diff --git a/bindings/python/examples/gpionotify.py b/bindings/python/examples/gpionotify.py
deleted file mode 100755
index 4e50515..0000000
--- a/bindings/python/examples/gpionotify.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-
-"""Simplified reimplementation of the gpionotify tool in Python."""
-
-import gpiod
-import sys
-
-if __name__ == "__main__":
-    if len(sys.argv) < 3:
-        raise TypeError("usage: gpionotify.py <gpiochip> <offset1> <offset2> ...")
-
-    path = sys.argv[1]
-
-    with gpiod.Chip(path) as chip:
-        for line in sys.argv[2:]:
-            chip.watch_line_info(line)
-
-        while True:
-            print(chip.read_info_event())
diff --git a/bindings/python/examples/gpioset.py b/bindings/python/examples/gpioset.py
deleted file mode 100755
index e6a516c..0000000
--- a/bindings/python/examples/gpioset.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
-
-"""Simplified reimplementation of the gpioset tool in Python."""
-
-import gpiod
-import sys
-
-from gpiod.line import Direction, Value
-
-if __name__ == "__main__":
-    if len(sys.argv) < 3:
-        raise TypeError(
-            "usage: gpioset.py <gpiochip> <offset1>=<value1> <offset2>=<value2> ..."
-        )
-
-    path = sys.argv[1]
-
-    def parse_value(arg):
-        x, y = arg.split("=")
-        return (x, Value(int(y)))
-
-    def make_settings(val):
-        return gpiod.LineSettings(direction=Direction.OUTPUT, output_value=val)
-
-    lvs = [parse_value(arg) for arg in sys.argv[2:]]
-    config = dict((l, make_settings(v)) for (l, v) in lvs)
-
-    request = gpiod.request_lines(
-        path,
-        consumer="gpioset.py",
-        config=config,
-    )
-
-    input()
diff --git a/bindings/python/examples/helpers.py b/bindings/python/examples/helpers.py
deleted file mode 100644
index 8b91173..0000000
--- a/bindings/python/examples/helpers.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
-
-import gpiod
-import os
-
-
-def gpio_chips():
-    for path in [
-        entry.path
-        for entry in os.scandir("/dev/")
-        if gpiod.is_gpiochip_device(entry.path)
-    ]:
-        with gpiod.Chip(path) as chip:
-            yield chip
diff --git a/bindings/python/examples/reconfigure_input_to_output.py b/bindings/python/examples/reconfigure_input_to_output.py
new file mode 100755
index 0000000..60d3015
--- /dev/null
+++ b/bindings/python/examples/reconfigure_input_to_output.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of requesting a line intended for bi-directional use as input and then switching to output."""
+
+import gpiod
+
+from gpiod.line import Direction, Value
+
+
+def reconfigure_input_to_output(chip_path, line_offset):
+    # request the line initially as an input
+    with gpiod.request_lines(
+        chip_path,
+        consumer="reconfigure-input-to-output",
+        config={line_offset: gpiod.LineSettings(direction=Direction.INPUT)},
+    ) as request:
+        # read the current line value
+        value = request.get_value(line_offset)
+        print("{}={} (input)".format(line_offset, value))
+        # switch the line to an output and drive it low
+        request.reconfigure_lines(
+            config={
+                line_offset: gpiod.LineSettings(
+                    direction=Direction.OUTPUT, output_value=Value.INACTIVE
+                )
+            }
+        )
+        # report the current driven value
+        value = request.get_value(line_offset)
+        print("{}={} (output)".format(line_offset, value))
+
+
+if __name__ == "__main__":
+    try:
+        reconfigure_input_to_output("/dev/gpiochip0", 5)
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/toggle_multiple_line_values.py b/bindings/python/examples/toggle_multiple_line_values.py
new file mode 100755
index 0000000..12b968d
--- /dev/null
+++ b/bindings/python/examples/toggle_multiple_line_values.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of toggling multiple lines."""
+
+import gpiod
+import time
+
+from gpiod.line import Direction, Value
+
+
+def toggle_value(value):
+    if value == Value.INACTIVE:
+        return Value.ACTIVE
+    return Value.INACTIVE
+
+
+def toggle_multiple_line_values(chip_path, line_values):
+    value_str = {Value.ACTIVE: "Active", Value.INACTIVE: "Inactive"}
+
+    request = gpiod.request_lines(
+        chip_path,
+        consumer="toggle-multiple-line-values",
+        config={
+            tuple(line_values.keys()): gpiod.LineSettings(direction=Direction.OUTPUT)
+        },
+        output_values=line_values,
+    )
+
+    while True:
+        print(
+            " ".join("{}={}".format(l, value_str[v]) for (l, v) in line_values.items())
+        )
+        time.sleep(1)
+        for l, v in line_values.items():
+            line_values[l] = toggle_value(v)
+        request.set_values(line_values)
+
+
+if __name__ == "__main__":
+    try:
+        toggle_multiple_line_values(
+            "/dev/gpiochip0", {5: Value.ACTIVE, 3: Value.ACTIVE, 7: Value.INACTIVE}
+        )
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/watch_line_info.py b/bindings/python/examples/watch_line_info.py
new file mode 100755
index 0000000..e49a669
--- /dev/null
+++ b/bindings/python/examples/watch_line_info.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of watching for info changes on particular lines."""
+
+import gpiod
+
+
+def watch_line_info(chip_path, line_offsets):
+    with gpiod.Chip(chip_path) as chip:
+        for offset in line_offsets:
+            chip.watch_line_info(offset)
+
+        while True:
+            print(chip.read_info_event())
+
+
+if __name__ == "__main__":
+    try:
+        watch_line_info("/dev/gpiochip0", [5, 3, 7])
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/watch_line_rising.py b/bindings/python/examples/watch_line_rising.py
new file mode 100755
index 0000000..2350d76
--- /dev/null
+++ b/bindings/python/examples/watch_line_rising.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of watching for rising edges on a single line."""
+
+import gpiod
+
+from gpiod.line import Edge
+
+
+def watch_line_rising(chip_path, line_offset):
+    with gpiod.request_lines(
+        chip_path,
+        consumer="watch-line-rising",
+        config={line_offset: gpiod.LineSettings(edge_detection=Edge.RISING)},
+    ) as request:
+        while True:
+            # Blocks until at least one event is available
+            for event in request.read_edge_events():
+                print(
+                    "line: %d  type: Rising   event #%d"
+                    % (event.line_offset, event.line_seqno)
+                )
+
+
+if __name__ == "__main__":
+    try:
+        watch_line_rising("/dev/gpiochip0", 5)
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
diff --git a/bindings/python/examples/watch_multiple_line_values.py b/bindings/python/examples/watch_multiple_line_values.py
new file mode 100755
index 0000000..4fbf05c
--- /dev/null
+++ b/bindings/python/examples/watch_multiple_line_values.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+
+"""Minimal example of watching for edges on multiple lines."""
+
+import gpiod
+
+from gpiod.line import Edge
+
+
+def edge_type(event):
+    if event.event_type is event.Type.RISING_EDGE:
+        return "Rising"
+    if event.event_type is event.Type.FALLING_EDGE:
+        return "Falling"
+    return "Unknown"
+
+
+def watch_multiple_line_values(chip_path, line_offsets):
+    with gpiod.request_lines(
+        chip_path,
+        consumer="watch-multiple-line-values",
+        config={tuple(line_offsets): gpiod.LineSettings(edge_detection=Edge.BOTH)},
+    ) as request:
+        while True:
+            for event in request.read_edge_events():
+                print(
+                    "offset: %d  type: %-7s  event #%d  line event #%d"
+                    % (
+                        event.line_offset,
+                        edge_type(event),
+                        event.global_seqno,
+                        event.line_seqno,
+                    )
+                )
+
+
+if __name__ == "__main__":
+    try:
+        watch_multiple_line_values("/dev/gpiochip0", [5, 3, 7])
+    except OSError as ex:
+        print(ex, "\nCustomise the example configuration to suit your situation")
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [libgpiod][PATCH 7/8] bindings: rust: examples: consistency cleanup
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
                   ` (5 preceding siblings ...)
  2023-06-23  4:38 ` [libgpiod][PATCH 6/8] bindings: python: examples: replace tools examples with use case examples Kent Gibson
@ 2023-06-23  4:39 ` Kent Gibson
  2023-06-23  7:58   ` Erik Schilling
  2023-06-23  4:39 ` [libgpiod][PATCH 8/8] bindings: rust: examples: replace tools examples with use case examples Kent Gibson
  2023-06-23 19:35 ` [libgpiod][PATCH 0/8] replace tool " Bartosz Golaszewski
  8 siblings, 1 reply; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:39 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

A collection of minor changes to be more consistent with other examples:
 - capitalize comments
 - add line offset to value outputs
 - drop comma from edge event outputs

Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
 .../rust/libgpiod/examples/get_line_value.rs    |  4 ++--
 .../rust/libgpiod/examples/toggle_line_value.rs | 17 ++++++++---------
 .../rust/libgpiod/examples/watch_line_value.rs  | 10 +++++-----
 3 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/bindings/rust/libgpiod/examples/get_line_value.rs b/bindings/rust/libgpiod/examples/get_line_value.rs
index 732fb71..39141e2 100644
--- a/bindings/rust/libgpiod/examples/get_line_value.rs
+++ b/bindings/rust/libgpiod/examples/get_line_value.rs
@@ -6,7 +6,7 @@
 use libgpiod::line;
 
 fn main() -> libgpiod::Result<()> {
-    // example configuration - customize to suit your situation
+    // Example configuration - customize to suit your situation
     let chip_path = "/dev/gpiochip0";
     let line_offset = 5;
 
@@ -23,6 +23,6 @@ fn main() -> libgpiod::Result<()> {
     let request = chip.request_lines(Some(&rconfig), &lconfig)?;
 
     let value = request.value(line_offset)?;
-    println!("{:?}", value);
+    println!("{}={:?}", line_offset, value);
     Ok(())
 }
diff --git a/bindings/rust/libgpiod/examples/toggle_line_value.rs b/bindings/rust/libgpiod/examples/toggle_line_value.rs
index cd7038e..6d5f697 100644
--- a/bindings/rust/libgpiod/examples/toggle_line_value.rs
+++ b/bindings/rust/libgpiod/examples/toggle_line_value.rs
@@ -3,22 +3,21 @@
 //
 // Minimal example of toggling a single line.
 
-use libgpiod::line;
-use std::time::Duration;
+use core::time::Duration;
+use libgpiod::line::{self, Value};
 
-fn toggle_value(value: line::Value) -> line::Value {
+fn toggle_value(value: Value) -> Value {
     match value {
-        line::Value::Active => line::Value::InActive,
-        line::Value::InActive => line::Value::Active,
+        Value::Active => Value::InActive,
+        Value::InActive => Value::Active,
     }
 }
 
 fn main() -> libgpiod::Result<()> {
-    // example configuration - customize to suit your situation
+    // Example configuration - customize to suit your situation
     let chip_path = "/dev/gpiochip0";
     let line_offset = 5;
-
-    let mut value = line::Value::Active;
+    let mut value = Value::Active;
 
     let mut settings = line::Settings::new()?;
     settings
@@ -35,7 +34,7 @@ fn main() -> libgpiod::Result<()> {
     let mut req = chip.request_lines(Some(&rconfig), &lconfig)?;
 
     loop {
-        println!("{:?}", value);
+        println!("{}={:?}", line_offset, value);
         std::thread::sleep(Duration::from_secs(1));
         value = toggle_value(value);
         req.set_value(line_offset, value)?;
diff --git a/bindings/rust/libgpiod/examples/watch_line_value.rs b/bindings/rust/libgpiod/examples/watch_line_value.rs
index 5a95b6a..3bf40af 100644
--- a/bindings/rust/libgpiod/examples/watch_line_value.rs
+++ b/bindings/rust/libgpiod/examples/watch_line_value.rs
@@ -7,12 +7,12 @@ use libgpiod::line;
 use std::time::Duration;
 
 fn main() -> libgpiod::Result<()> {
-    // example configuration - customize to suit your situation
+    // Example configuration - customize to suit your situation
     let chip_path = "/dev/gpiochip0";
     let line_offset = 5;
 
     let mut lsettings = line::Settings::new()?;
-    // assume a button connecting the pin to ground,
+    // Assume a button connecting the pin to ground,
     // so pull it up and provide some debounce.
     lsettings
         .set_edge_detection(Some(line::Edge::Both))?
@@ -28,7 +28,7 @@ fn main() -> libgpiod::Result<()> {
     let chip = libgpiod::chip::Chip::open(&chip_path)?;
     let request = chip.request_lines(Some(&rconfig), &lconfig)?;
 
-    // a larger buffer is an optimisation for reading bursts of events from the
+    // 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.
     let mut buffer = libgpiod::request::Buffer::new(1)?;
     loop {
@@ -37,10 +37,10 @@ fn main() -> libgpiod::Result<()> {
         for event in events {
             let event = event?;
             println!(
-                "line: {}, type: {}, event #{}",
+                "line: {}  type: {:<7}  event #{}",
                 event.line_offset(),
                 match event.event_type()? {
-                    line::EdgeKind::Rising => "Rising ",
+                    line::EdgeKind::Rising => "Rising",
                     line::EdgeKind::Falling => "Falling",
                 },
                 event.line_seqno()
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [libgpiod][PATCH 8/8] bindings: rust: examples: replace tools examples with use case examples
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
                   ` (6 preceding siblings ...)
  2023-06-23  4:39 ` [libgpiod][PATCH 7/8] bindings: rust: examples: consistency cleanup Kent Gibson
@ 2023-06-23  4:39 ` Kent Gibson
  2023-06-23  7:57   ` Erik Schilling
  2023-06-23 19:35 ` [libgpiod][PATCH 0/8] replace tool " Bartosz Golaszewski
  8 siblings, 1 reply; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  4:39 UTC (permalink / raw)
  To: linux-gpio, brgl; +Cc: Kent Gibson

Replace tool examples with use case examples drawn from the tools,
gpio_events example with buffered_event_lifetimes, and
gpio_threaded_info_events with reconfigure_input_to_output.

Signed-off-by: Kent Gibson <warthog618@gmail.com>
---
 bindings/rust/libgpiod/examples/Makefile.am   |  21 +--
 .../examples/buffered_event_lifetimes.rs      |  58 ++++++++
 .../libgpiod/examples/find_line_by_name.rs    |  29 ++++
 .../rust/libgpiod/examples/get_chip_info.rs   |  22 +++
 .../rust/libgpiod/examples/get_line_info.rs   |  37 +++++
 .../examples/get_multiple_line_values.rs      |  29 ++++
 .../rust/libgpiod/examples/gpio_events.rs     |  88 ------------
 .../examples/gpio_threaded_info_events.rs     | 132 ------------------
 bindings/rust/libgpiod/examples/gpiodetect.rs |  30 ----
 bindings/rust/libgpiod/examples/gpiofind.rs   |  36 -----
 bindings/rust/libgpiod/examples/gpioget.rs    |  45 ------
 bindings/rust/libgpiod/examples/gpioinfo.rs   |  97 -------------
 bindings/rust/libgpiod/examples/gpiomon.rs    |  74 ----------
 bindings/rust/libgpiod/examples/gpionotify.rs |  53 -------
 bindings/rust/libgpiod/examples/gpioset.rs    |  63 ---------
 bindings/rust/libgpiod/examples/gpiowatch.rs  |  53 -------
 .../examples/reconfigure_input_to_output.rs   |  42 ++++++
 .../examples/toggle_multiple_line_values.rs   |  55 ++++++++
 .../rust/libgpiod/examples/watch_line_info.rs |  32 +++++
 .../libgpiod/examples/watch_line_rising.rs    |  44 ++++++
 .../examples/watch_multiple_line_values.rs    |  46 ++++++
 21 files changed, 405 insertions(+), 681 deletions(-)
 create mode 100644 bindings/rust/libgpiod/examples/buffered_event_lifetimes.rs
 create mode 100644 bindings/rust/libgpiod/examples/find_line_by_name.rs
 create mode 100644 bindings/rust/libgpiod/examples/get_chip_info.rs
 create mode 100644 bindings/rust/libgpiod/examples/get_line_info.rs
 create mode 100644 bindings/rust/libgpiod/examples/get_multiple_line_values.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpio_events.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpiodetect.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpiofind.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpioget.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpioinfo.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpiomon.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpionotify.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpioset.rs
 delete mode 100644 bindings/rust/libgpiod/examples/gpiowatch.rs
 create mode 100644 bindings/rust/libgpiod/examples/reconfigure_input_to_output.rs
 create mode 100644 bindings/rust/libgpiod/examples/toggle_multiple_line_values.rs
 create mode 100644 bindings/rust/libgpiod/examples/watch_line_info.rs
 create mode 100644 bindings/rust/libgpiod/examples/watch_line_rising.rs
 create mode 100644 bindings/rust/libgpiod/examples/watch_multiple_line_values.rs

diff --git a/bindings/rust/libgpiod/examples/Makefile.am b/bindings/rust/libgpiod/examples/Makefile.am
index b3338bd..ea1826f 100644
--- a/bindings/rust/libgpiod/examples/Makefile.am
+++ b/bindings/rust/libgpiod/examples/Makefile.am
@@ -3,16 +3,17 @@
 # SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
 
 EXTRA_DIST = \
+	buffered_event_lifetimes.rs \
+	find_line_by_name.rs \
+	get_chip_info.rs \
+	get_line_info.rs \
 	get_line_value.rs \
-	gpiodetect.rs \
-	gpio_events.rs \
-	gpiofind.rs \
-	gpioget.rs \
-	gpioinfo.rs \
-	gpiomon.rs \
-	gpionotify.rs \
-	gpioset.rs \
+	get_multiple_line_values.rs \
 	gpio_threaded_info_events.rs \
-	gpiowatch.rs \
+	reconfigure_input_to_output \
 	toggle_line_value.rs \
-	watch_line_value.rs
+	toggle_multiple_line_values.rs \
+	watch_line_info.rs \
+	watch_line_rising.rs \
+	watch_line_value.rs \
+	watch_multiple_line_values.rs
diff --git a/bindings/rust/libgpiod/examples/buffered_event_lifetimes.rs b/bindings/rust/libgpiod/examples/buffered_event_lifetimes.rs
new file mode 100644
index 0000000..ad90d7b
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/buffered_event_lifetimes.rs
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2022 Linaro Ltd.
+// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
+//
+// An example demonstrating that an edge event must be cloned to outlive
+// subsequent writes to the containing event buffer.
+
+use libgpiod::line;
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+    let line_offset = 5;
+
+    let mut lsettings = line::Settings::new()?;
+    lsettings.set_edge_detection(Some(line::Edge::Both))?;
+
+    let mut lconfig = line::Config::new()?;
+    lconfig.add_line_settings(&[line_offset], lsettings)?;
+
+    let mut rconfig = libgpiod::request::Config::new()?;
+    rconfig.set_consumer("buffered-event-lifetimes")?;
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+    let request = chip.request_lines(Some(&rconfig), &lconfig)?;
+
+    let mut buffer = libgpiod::request::Buffer::new(4)?;
+
+    loop {
+        // Blocks until at least one event is available
+        let mut events = request.read_edge_events(&mut buffer)?;
+
+        // This can't be used across the next read_edge_events().
+        let event = events.next().unwrap()?;
+
+        // This will out live `event` and the next read_edge_events().
+        let cloned_event = libgpiod::request::Event::event_clone(event)?;
+
+        let events = request.read_edge_events(&mut buffer)?;
+        for event in events {
+            let event = event?;
+            println!(
+                "line: {}  type: {:?}  event #{}",
+                event.line_offset(),
+                event.event_type(),
+                event.line_seqno(),
+            );
+        }
+
+        // `cloned_event` is still available to be used.
+        println!(
+            "line: {}  type: {:?}  event #{}",
+            cloned_event.line_offset(),
+            cloned_event.event_type(),
+            cloned_event.line_seqno(),
+        );
+    }
+}
diff --git a/bindings/rust/libgpiod/examples/find_line_by_name.rs b/bindings/rust/libgpiod/examples/find_line_by_name.rs
new file mode 100644
index 0000000..f7b9919
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/find_line_by_name.rs
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of finding a line with the given name.
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let line_name = "GPIO19";
+
+    // Names are not guaranteed unique, so this finds the first line with
+    // the given name.
+    for chip in libgpiod::gpiochip_devices(&"/dev")? {
+        let offset = chip.line_offset_from_name(line_name);
+
+        if offset.is_ok() {
+            let info = chip.info()?;
+            println!(
+                "{}: {} {}",
+                line_name,
+                info.name()?,
+                offset?
+            );
+            return Ok(());
+        }
+    }
+
+    println!("line '{}' not found", line_name);
+    Ok(())
+}
diff --git a/bindings/rust/libgpiod/examples/get_chip_info.rs b/bindings/rust/libgpiod/examples/get_chip_info.rs
new file mode 100644
index 0000000..cc23c86
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/get_chip_info.rs
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of reading the info for a chip.
+
+use libgpiod::{self, Result};
+
+fn main() -> Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+    let info = chip.info()?;
+    println!(
+        "{} [{}] ({} lines)",
+        info.name()?,
+        info.label()?,
+        info.num_lines(),
+    );
+
+    Ok(())
+}
diff --git a/bindings/rust/libgpiod/examples/get_line_info.rs b/bindings/rust/libgpiod/examples/get_line_info.rs
new file mode 100644
index 0000000..086db90
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/get_line_info.rs
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of reading the info for a line.
+
+use libgpiod::line::Direction;
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+    let line_offset = 3;
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+    let info = chip.line_info(line_offset)?;
+
+    let name = info.name().unwrap_or("unnamed");
+    let consumer = info.consumer().unwrap_or("unused");
+
+    let dir = match info.direction()? {
+        Direction::AsIs => "none",
+        Direction::Input => "input",
+        Direction::Output => "output",
+    };
+
+    let low = if info.is_active_low() {
+        "active-low"
+    } else {
+        "active-high"
+    };
+
+    println!(
+        "line {:>3}: {:>12} {:>12} {:>8} {:>10}",
+        line_offset, name, consumer, dir, low
+    );
+
+    Ok(())
+}
diff --git a/bindings/rust/libgpiod/examples/get_multiple_line_values.rs b/bindings/rust/libgpiod/examples/get_multiple_line_values.rs
new file mode 100644
index 0000000..a1be5a6
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/get_multiple_line_values.rs
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of reading multiple lines.
+
+use libgpiod::line::{self, Direction};
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+    let line_offsets = [5, 3, 7];
+
+    let mut lsettings = line::Settings::new()?;
+    let mut lconfig = line::Config::new()?;
+
+    lsettings.set_direction(Direction::Input)?;
+    lconfig.add_line_settings(&line_offsets, lsettings)?;
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+
+    let mut rconfig = libgpiod::request::Config::new()?;
+    rconfig.set_consumer("get-multiple-line-values")?;
+
+    let request = chip.request_lines(Some(&rconfig), &lconfig)?;
+    let values = request.values()?;
+
+    println!("{:?}", values);
+    Ok(())
+}
diff --git a/bindings/rust/libgpiod/examples/gpio_events.rs b/bindings/rust/libgpiod/examples/gpio_events.rs
deleted file mode 100644
index a45b6db..0000000
--- a/bindings/rust/libgpiod/examples/gpio_events.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation to show handling of events, when the buffer
-// is read into multiple times. Based on gpiomon example.
-
-use std::env;
-
-use libgpiod::{
-    chip::Chip,
-    line::{self, Edge, Offset},
-    request, Error, Result,
-};
-
-fn usage(name: &str) {
-    println!("Usage: {} <chip> <offset0> ...", name);
-}
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() < 3 {
-        usage(&args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    let mut lsettings = line::Settings::new()?;
-    let mut lconfig = line::Config::new()?;
-    let mut offsets = Vec::<Offset>::new();
-
-    for arg in &args[2..] {
-        let offset = arg.parse::<Offset>().map_err(|_| Error::InvalidArguments)?;
-        offsets.push(offset);
-    }
-
-    lsettings.set_edge_detection(Some(Edge::Both))?;
-    lconfig.add_line_settings(&offsets, lsettings)?;
-
-    let path = format!("/dev/gpiochip{}", args[1]);
-    let chip = Chip::open(&path)?;
-
-    let rconfig = request::Config::new()?;
-
-    let mut buffer = request::Buffer::new(1)?;
-    let request = chip.request_lines(Some(&rconfig), &lconfig)?;
-
-    loop {
-        match request.wait_edge_events(None) {
-            Err(x) => {
-                println!("{:?}", x);
-                return Err(Error::InvalidArguments);
-            }
-
-            Ok(false) => {
-                // This shouldn't happen as the call is blocking.
-                panic!();
-            }
-            Ok(true) => (),
-        }
-
-        let mut events = request.read_edge_events(&mut buffer)?;
-
-        // This can't be used across the next read_edge_events().
-        let event = events.next().unwrap()?;
-
-        // This will out live `event` and the next read_edge_events().
-        let cloned_event = request::Event::event_clone(event)?;
-
-        let events = request.read_edge_events(&mut buffer)?;
-        for event in events {
-            let event = event?;
-            println!(
-                "line: {} type: {:?}, time: {:?}",
-                event.line_offset(),
-                event.event_type(),
-                event.timestamp()
-            );
-        }
-
-        // `cloned_event` is still available to be used.
-        println!(
-            "line: {} type: {:?}, time: {:?}",
-            cloned_event.line_offset(),
-            cloned_event.event_type(),
-            cloned_event.timestamp()
-        );
-    }
-}
diff --git a/bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs b/bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs
deleted file mode 100644
index 8853a7b..0000000
--- a/bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs
+++ /dev/null
@@ -1,132 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation to show handling of info events, that are
-// generated from another thread.
-
-use std::{
-    env,
-    sync::{
-        mpsc::{self, Receiver, Sender},
-        Arc, Mutex,
-    },
-    thread,
-    time::Duration,
-};
-
-use libgpiod::{
-    chip::Chip,
-    line::{self, Direction, InfoChangeKind, Offset},
-    request, Error, Result,
-};
-
-fn usage(name: &str) {
-    println!("Usage: {} <chip> <offset>", name);
-}
-
-fn request_reconfigure_line(
-    chip: Arc<Mutex<Chip>>,
-    offset: Offset,
-    tx: Sender<()>,
-    rx: Receiver<()>,
-) {
-    thread::spawn(move || {
-        let mut lconfig = line::Config::new().unwrap();
-        let lsettings = line::Settings::new().unwrap();
-        lconfig.add_line_settings(&[offset], lsettings).unwrap();
-        let rconfig = request::Config::new().unwrap();
-
-        let mut request = chip
-            .lock()
-            .unwrap()
-            .request_lines(Some(&rconfig), &lconfig)
-            .unwrap();
-
-        // Signal the parent to continue
-        tx.send(()).expect("Could not send signal on channel");
-
-        // Wait for parent to signal
-        rx.recv().expect("Could not receive from channel");
-
-        let mut lconfig = line::Config::new().unwrap();
-        let mut lsettings = line::Settings::new().unwrap();
-        lsettings.set_direction(Direction::Output).unwrap();
-        lconfig.add_line_settings(&[offset], lsettings).unwrap();
-
-        request.reconfigure_lines(&lconfig).unwrap();
-
-        // Signal the parent to continue
-        tx.send(()).expect("Could not send signal on channel");
-
-        // Wait for parent to signal
-        rx.recv().expect("Could not receive from channel");
-    });
-}
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() != 3 {
-        usage(&args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    let path = format!("/dev/gpiochip{}", args[1]);
-    let offset = args[2]
-        .parse::<Offset>()
-        .map_err(|_| Error::InvalidArguments)?;
-
-    let chip = Arc::new(Mutex::new(Chip::open(&path)?));
-    chip.lock().unwrap().watch_line_info(offset)?;
-
-    // Thread synchronizing mechanism
-    let (tx_main, rx_thread) = mpsc::channel();
-    let (tx_thread, rx_main) = mpsc::channel();
-
-    // Generate events
-    request_reconfigure_line(chip.clone(), offset, tx_thread, rx_thread);
-
-    // Wait for thread to signal
-    rx_main.recv().expect("Could not receive from channel");
-
-    // Line requested event
-    assert!(chip
-        .lock()
-        .unwrap()
-        .wait_info_event(Some(Duration::from_secs(1)))?);
-    let event = chip.lock().unwrap().read_info_event()?;
-    assert_eq!(event.event_type()?, InfoChangeKind::LineRequested);
-
-    // Signal the thread to continue
-    tx_main.send(()).expect("Could not send signal on channel");
-
-    // Wait for thread to signal
-    rx_main.recv().expect("Could not receive from channel");
-
-    // Line changed event
-    assert!(chip
-        .lock()
-        .unwrap()
-        .wait_info_event(Some(Duration::from_millis(10)))?);
-    let event = chip.lock().unwrap().read_info_event()?;
-    assert_eq!(event.event_type()?, InfoChangeKind::LineConfigChanged);
-
-    // Signal the thread to continue
-    tx_main.send(()).expect("Could not send signal on channel");
-
-    // Line released event
-    assert!(chip
-        .lock()
-        .unwrap()
-        .wait_info_event(Some(Duration::from_millis(10)))?);
-    let event = chip.lock().unwrap().read_info_event()?;
-    assert_eq!(event.event_type().unwrap(), InfoChangeKind::LineReleased);
-
-    // No events available
-    assert!(!chip
-        .lock()
-        .unwrap()
-        .wait_info_event(Some(Duration::from_millis(100)))?);
-
-    Ok(())
-}
diff --git a/bindings/rust/libgpiod/examples/gpiodetect.rs b/bindings/rust/libgpiod/examples/gpiodetect.rs
deleted file mode 100644
index 9792252..0000000
--- a/bindings/rust/libgpiod/examples/gpiodetect.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation of gpiodetect tool.
-
-use std::env;
-use std::path::Path;
-
-use libgpiod::{self, Error, Result};
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() > 1 {
-        println!("Usage: {}", args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    for chip in libgpiod::gpiochip_devices(&Path::new("/dev"))? {
-        let info = chip.info()?;
-        println!(
-            "{} [{}] ({})",
-            info.name()?,
-            info.label()?,
-            info.num_lines(),
-        );
-    }
-
-    Ok(())
-}
diff --git a/bindings/rust/libgpiod/examples/gpiofind.rs b/bindings/rust/libgpiod/examples/gpiofind.rs
deleted file mode 100644
index da0530d..0000000
--- a/bindings/rust/libgpiod/examples/gpiofind.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation of gpiofind tool.
-
-use std::env;
-use std::path::Path;
-
-use libgpiod::{self, Error, Result};
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() != 2 {
-        println!("Usage: {} <line-name>", args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    for chip in libgpiod::gpiochip_devices(&Path::new("/dev"))? {
-        let offset = chip.line_offset_from_name(&args[1]);
-        let info = chip.info()?;
-
-        if offset.is_ok() {
-            println!(
-                "Line {} found: Chip: {}, offset: {}",
-                args[1],
-                info.name()?,
-                offset?
-            );
-            return Ok(());
-        }
-    }
-
-    println!("Failed to find line: {}", args[1]);
-    Ok(())
-}
diff --git a/bindings/rust/libgpiod/examples/gpioget.rs b/bindings/rust/libgpiod/examples/gpioget.rs
deleted file mode 100644
index 8e390f3..0000000
--- a/bindings/rust/libgpiod/examples/gpioget.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation of gpioget tool.
-
-use std::env;
-
-use libgpiod::{
-    chip::Chip,
-    line::{self, Direction, Offset},
-    request, Error, Result,
-};
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() < 3 {
-        println!("Usage: {} <chip> <line_offset0> ...", args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    let mut lsettings = line::Settings::new()?;
-    let mut lconfig = line::Config::new()?;
-    let mut offsets = Vec::<Offset>::new();
-
-    for arg in &args[2..] {
-        let offset = arg.parse::<Offset>().map_err(|_| Error::InvalidArguments)?;
-        offsets.push(offset);
-    }
-
-    lsettings.set_direction(Direction::Input)?;
-    lconfig.add_line_settings(&offsets, lsettings)?;
-
-    let path = format!("/dev/gpiochip{}", args[1]);
-    let chip = Chip::open(&path)?;
-
-    let mut rconfig = request::Config::new()?;
-    rconfig.set_consumer(&args[0])?;
-
-    let request = chip.request_lines(Some(&rconfig), &lconfig)?;
-    let map = request.values()?;
-
-    println!("{:?}", map);
-    Ok(())
-}
diff --git a/bindings/rust/libgpiod/examples/gpioinfo.rs b/bindings/rust/libgpiod/examples/gpioinfo.rs
deleted file mode 100644
index 1fe1ae0..0000000
--- a/bindings/rust/libgpiod/examples/gpioinfo.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation of gpioinfo tool.
-
-use std::env;
-use std::path::Path;
-
-use libgpiod::{
-    chip::Chip,
-    line::{Direction, Offset},
-    Error, Result,
-};
-
-fn line_info(chip: &Chip, offset: Offset) -> Result<()> {
-    let info = chip.line_info(offset)?;
-    let off = info.offset();
-
-    let name = match info.name() {
-        Ok(name) => name,
-        _ => "unused",
-    };
-
-    let consumer = match info.consumer() {
-        Ok(name) => name,
-        _ => "unnamed",
-    };
-
-    let low = if info.is_active_low() {
-        "active-low"
-    } else {
-        "active-high"
-    };
-
-    let dir = match info.direction()? {
-        Direction::AsIs => "None",
-        Direction::Input => "Input",
-        Direction::Output => "Output",
-    };
-
-    println!(
-        "\tline {:>3}\
-              \t{:>10}\
-              \t{:>10}\
-              \t{:>6}\
-              \t{:>14}",
-        off, name, consumer, dir, low
-    );
-
-    Ok(())
-}
-
-fn chip_info(chip: &Chip) -> Result<()> {
-    let info = chip.info()?;
-    let ngpio = info.num_lines();
-
-    println!("GPIO Chip name: {}", info.name()?);
-    println!("\tlabel: {}", info.label()?);
-    println!("\tpath: {}", chip.path()?);
-    println!("\tngpio: {}\n", ngpio);
-
-    println!("\tLine information:");
-
-    for offset in 0..ngpio {
-        line_info(chip, offset as Offset)?;
-    }
-    println!("\n");
-
-    Ok(())
-}
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() > 2 {
-        println!("Usage: {}", args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    if args.len() == 1 {
-        for chip in libgpiod::gpiochip_devices(&Path::new("/dev"))? {
-            chip_info(&chip)?;
-        }
-    } else {
-        let index = args[1]
-            .parse::<u32>()
-            .map_err(|_| Error::InvalidArguments)?;
-        let path = format!("/dev/gpiochip{}", index);
-        if libgpiod::is_gpiochip_device(&path) {
-            let chip = Chip::open(&path)?;
-
-            chip_info(&chip)?;
-        }
-    }
-
-    Ok(())
-}
diff --git a/bindings/rust/libgpiod/examples/gpiomon.rs b/bindings/rust/libgpiod/examples/gpiomon.rs
deleted file mode 100644
index c3564db..0000000
--- a/bindings/rust/libgpiod/examples/gpiomon.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation of the gpiomon tool.
-
-use std::env;
-
-use libgpiod::{
-    chip::Chip,
-    line::{self, Edge, EdgeKind, Offset},
-    request, Error, Result,
-};
-
-fn usage(name: &str) {
-    println!("Usage: {} <chip> <offset0> ...", name);
-}
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() < 3 {
-        usage(&args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    let mut lsettings = line::Settings::new()?;
-    let mut lconfig = line::Config::new()?;
-    let mut offsets = Vec::<Offset>::new();
-
-    for arg in &args[2..] {
-        let offset = arg.parse::<Offset>().map_err(|_| Error::InvalidArguments)?;
-        offsets.push(offset);
-    }
-
-    lsettings.set_edge_detection(Some(Edge::Both))?;
-    lconfig.add_line_settings(&offsets, lsettings)?;
-
-    let path = format!("/dev/gpiochip{}", args[1]);
-    let chip = Chip::open(&path)?;
-
-    let rconfig = request::Config::new()?;
-
-    let mut buffer = request::Buffer::new(1)?;
-    let request = chip.request_lines(Some(&rconfig), &lconfig)?;
-
-    loop {
-        match request.wait_edge_events(None) {
-            Err(x) => {
-                println!("{:?}", x);
-                return Err(Error::InvalidArguments);
-            }
-
-            Ok(false) => {
-                // This shouldn't happen as the call is blocking.
-                panic!();
-            }
-            Ok(true) => (),
-        }
-
-        let events = request.read_edge_events(&mut buffer)?;
-        for event in events {
-            let event = event?;
-            println!(
-                "line: {} type: {}, time: {:?}",
-                event.line_offset(),
-                match event.event_type()? {
-                    EdgeKind::Rising => "Rising",
-                    EdgeKind::Falling => "Falling",
-                },
-                event.timestamp()
-            );
-        }
-    }
-}
diff --git a/bindings/rust/libgpiod/examples/gpionotify.rs b/bindings/rust/libgpiod/examples/gpionotify.rs
deleted file mode 100644
index fca1086..0000000
--- a/bindings/rust/libgpiod/examples/gpionotify.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2023 Linaro Ltd.
-// SPDX-FileCopyrightText: 2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-//
-// Simplified Rust implementation of the gpionotify tool.
-
-use std::env;
-
-use libgpiod::{
-    chip::Chip,
-    line::{Offset, InfoChangeKind},
-    Error, Result,
-};
-
-fn usage(name: &str) {
-    println!("Usage: {} <chip> <offset0> ...", name);
-}
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() < 3 {
-        usage(&args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    let mut offsets = Vec::<Offset>::new();
-
-    for arg in &args[2..] {
-        let offset = arg.parse::<Offset>().map_err(|_| Error::InvalidArguments)?;
-        offsets.push(offset);
-    }
-
-    let path = format!("/dev/gpiochip{}", args[1]);
-    let chip = Chip::open(&path)?;
-
-    for &offset in offsets.iter() {
-        let _info = chip.watch_line_info(offset).unwrap();
-    }
-
-    loop {
-        let event = chip.read_info_event().unwrap();
-        println!(
-            "event: {}, line: {}, timestamp: {:?}",
-            match event.event_type()? {
-                InfoChangeKind::LineRequested => "Line requested",
-                InfoChangeKind::LineReleased => "Line released",
-                InfoChangeKind::LineConfigChanged => "Line config changed",
-            },
-            event.line_info().unwrap().offset(),
-            event.timestamp()
-        );
-    }
-}
diff --git a/bindings/rust/libgpiod/examples/gpioset.rs b/bindings/rust/libgpiod/examples/gpioset.rs
deleted file mode 100644
index 607407d..0000000
--- a/bindings/rust/libgpiod/examples/gpioset.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation of the gpioset tool.
-
-use std::env;
-use std::io::{stdin, Read};
-
-use libgpiod::{
-    chip::Chip,
-    line::{self, Direction, Offset, SettingVal, Value},
-    request, Error, Result,
-};
-
-fn usage(name: &str) {
-    println!("Usage: {} <chip> <line_offset0>=<value0> ...", name);
-}
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() < 3 {
-        usage(&args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    let mut lconfig = line::Config::new()?;
-
-    for arg in &args[2..] {
-        let pair: Vec<&str> = arg.split('=').collect();
-        if pair.len() != 2 {
-            usage(&args[0]);
-            return Err(Error::InvalidArguments);
-        }
-
-        let offset = pair[0]
-            .parse::<Offset>()
-            .map_err(|_| Error::InvalidArguments)?;
-        let value = pair[1]
-            .parse::<i32>()
-            .map_err(|_| Error::InvalidArguments)?;
-
-        let mut lsettings = line::Settings::new()?;
-        lsettings.set_prop(&[
-            SettingVal::Direction(Direction::Output),
-            SettingVal::OutputValue(Value::new(value)?),
-        ])?;
-        lconfig.add_line_settings(&[offset], lsettings)?;
-    }
-
-    let path = format!("/dev/gpiochip{}", args[1]);
-    let chip = Chip::open(&path)?;
-
-    let mut rconfig = request::Config::new()?;
-    rconfig.set_consumer(&args[0])?;
-
-    chip.request_lines(Some(&rconfig), &lconfig)?;
-
-    // Wait for keypress, let user verify line status.
-    stdin().read_exact(&mut [0u8]).unwrap();
-
-    Ok(())
-}
diff --git a/bindings/rust/libgpiod/examples/gpiowatch.rs b/bindings/rust/libgpiod/examples/gpiowatch.rs
deleted file mode 100644
index 26a2ed8..0000000
--- a/bindings/rust/libgpiod/examples/gpiowatch.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
-// SPDX-FileCopyrightText: 2022 Linaro Ltd.
-// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-//
-// Simplified Rust implementation of the gpiowatch tool.
-
-use std::env;
-
-use libgpiod::{chip::Chip, line::Offset, Error, Result};
-
-fn usage(name: &str) {
-    println!("Usage: {} <chip> <offset0> ...", name);
-}
-
-fn main() -> Result<()> {
-    let args: Vec<String> = env::args().collect();
-    if args.len() < 2 {
-        usage(&args[0]);
-        return Err(Error::InvalidArguments);
-    }
-
-    let path = format!("/dev/gpiochip{}", args[1]);
-    let offset = args[2]
-        .parse::<Offset>()
-        .map_err(|_| Error::InvalidArguments)?;
-
-    let chip = Chip::open(&path)?;
-    let _info = chip.watch_line_info(offset)?;
-
-    match chip.wait_info_event(None) {
-        Err(x) => {
-            println!("{:?}", x);
-            return Err(Error::InvalidArguments);
-        }
-
-        Ok(false) => {
-            // This shouldn't happen as the call is blocking.
-            panic!();
-        }
-        Ok(true) => (),
-    }
-
-    let event = chip.read_info_event()?;
-    println!(
-        "line: {} type: {:?}, time: {:?}",
-        offset,
-        event.event_type()?,
-        event.timestamp()
-    );
-
-    chip.unwatch(offset);
-    Ok(())
-}
diff --git a/bindings/rust/libgpiod/examples/reconfigure_input_to_output.rs b/bindings/rust/libgpiod/examples/reconfigure_input_to_output.rs
new file mode 100644
index 0000000..3e2f2c7
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/reconfigure_input_to_output.rs
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of requesting a line intended for bi-directional use as input and then switching to output.
+
+use libgpiod::line;
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+    let line_offset = 5;
+
+    let mut lsettings = line::Settings::new()?;
+    lsettings.set_direction(line::Direction::Input)?;
+
+    let mut lconfig = line::Config::new()?;
+    lconfig.add_line_settings(&[line_offset], lsettings)?;
+
+    let mut rconfig = libgpiod::request::Config::new()?;
+    rconfig.set_consumer("reconfigure-input-to-output")?;
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+    // request the line initially as an input
+    let mut request = chip.request_lines(Some(&rconfig), &lconfig)?;
+
+    // read the current line value
+    let value = request.value(line_offset)?;
+    println!("{}={:?} (input)", line_offset, value);
+
+    // switch the line to an output and drive it low
+    let mut lsettings = line::Settings::new()?;
+    lsettings.set_direction(line::Direction::Output)?;
+    lsettings.set_output_value(line::Value::InActive)?;
+    lconfig.add_line_settings(&[line_offset], lsettings)?;
+    request.reconfigure_lines(&lconfig)?;
+
+    // report the current driven value
+    let value = request.value(line_offset)?;
+    println!("{}={:?} (output)", line_offset, value);
+
+    Ok(())
+}
diff --git a/bindings/rust/libgpiod/examples/toggle_multiple_line_values.rs b/bindings/rust/libgpiod/examples/toggle_multiple_line_values.rs
new file mode 100644
index 0000000..b7e6915
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/toggle_multiple_line_values.rs
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of toggling multiple lines.
+
+use core::time::Duration;
+use libgpiod::line::{self, Offset, Value};
+
+fn toggle_value(value: Value) -> Value {
+    match value {
+        Value::Active => Value::InActive,
+        Value::InActive => Value::Active,
+    }
+}
+
+fn toggle_values(values: &mut [Value]) {
+    for i in values.iter_mut() {
+        *i = toggle_value(*i);
+    }
+}
+
+fn print_values(offsets: &[Offset], values: &[Value]) {
+    for i in 0..offsets.len() {
+        print!("{}={:?} ", offsets[i], values[i]);
+    }
+    println!();
+}
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+    let line_offsets = [5, 3, 7];
+    let mut values = vec![Value::Active, Value::Active, Value::InActive];
+
+    let mut lsettings = line::Settings::new()?;
+    lsettings.set_direction(line::Direction::Output)?;
+
+    let mut lconfig = line::Config::new()?;
+    lconfig
+        .add_line_settings(&line_offsets, lsettings)?
+        .set_output_values(&values)?;
+
+    let mut rconfig = libgpiod::request::Config::new()?;
+    rconfig.set_consumer("toggle-multiple-line-values")?;
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+    let mut req = chip.request_lines(Some(&rconfig), &lconfig)?;
+
+    loop {
+        print_values(&line_offsets, &values);
+        std::thread::sleep(Duration::from_secs(1));
+        toggle_values(&mut values);
+        req.set_values(&values)?;
+    }
+}
diff --git a/bindings/rust/libgpiod/examples/watch_line_info.rs b/bindings/rust/libgpiod/examples/watch_line_info.rs
new file mode 100644
index 0000000..e84ce13
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/watch_line_info.rs
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of watching for info changes on particular lines.
+
+use libgpiod::line::InfoChangeKind;
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+    let line_offsets = [5, 3, 7];
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+    for offset in line_offsets {
+        let _info = chip.watch_line_info(offset)?;
+    }
+
+    loop {
+        // Blocks until at least one event is available.
+        let event = chip.read_info_event()?;
+        println!(
+            "line: {} {:<9} {:?}",
+            event.line_info()?.offset(),
+            match event.event_type()? {
+                InfoChangeKind::LineRequested => "Requested",
+                InfoChangeKind::LineReleased => "Released",
+                InfoChangeKind::LineConfigChanged => "Reconfig",
+            },
+            event.timestamp()
+        );
+    }
+}
diff --git a/bindings/rust/libgpiod/examples/watch_line_rising.rs b/bindings/rust/libgpiod/examples/watch_line_rising.rs
new file mode 100644
index 0000000..81a2407
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/watch_line_rising.rs
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of watching for edges on a single line.
+
+use libgpiod::line;
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+    let line_offset = 5;
+
+    let mut lsettings = line::Settings::new()?;
+    lsettings.set_edge_detection(Some(line::Edge::Rising))?;
+
+    let mut lconfig = line::Config::new()?;
+    lconfig.add_line_settings(&[line_offset], lsettings)?;
+
+    let mut rconfig = libgpiod::request::Config::new()?;
+    rconfig.set_consumer("watch-line-value")?;
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+    let request = chip.request_lines(Some(&rconfig), &lconfig)?;
+
+    // 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.
+    let mut buffer = libgpiod::request::Buffer::new(1)?;
+    loop {
+        // blocks until at least one event is available
+        let events = request.read_edge_events(&mut buffer)?;
+        for event in events {
+            let event = event?;
+            println!(
+                "line: {}  type: {:<7}  event #{}",
+                event.line_offset(),
+                match event.event_type()? {
+                    line::EdgeKind::Rising => "Rising",
+                    line::EdgeKind::Falling => "Falling",
+                },
+                event.line_seqno()
+            );
+        }
+    }
+}
diff --git a/bindings/rust/libgpiod/examples/watch_multiple_line_values.rs b/bindings/rust/libgpiod/examples/watch_multiple_line_values.rs
new file mode 100644
index 0000000..3fc88ba
--- /dev/null
+++ b/bindings/rust/libgpiod/examples/watch_multiple_line_values.rs
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
+// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
+//
+// Minimal example of watching for edges on multiple lines.
+
+use libgpiod::{
+    line::{self, EdgeKind},
+    request,
+};
+
+fn main() -> libgpiod::Result<()> {
+    // Example configuration - customize to suit your situation
+    let chip_path = "/dev/gpiochip0";
+    let line_offsets = [5, 3, 7];
+
+    let mut lsettings = line::Settings::new()?;
+    lsettings.set_edge_detection(Some(line::Edge::Both))?;
+
+    let mut lconfig = line::Config::new()?;
+    lconfig.add_line_settings(&line_offsets, lsettings)?;
+
+    let mut rconfig = request::Config::new()?;
+    rconfig.set_consumer("watch-multiple-line-values")?;
+
+    let chip = libgpiod::chip::Chip::open(&chip_path)?;
+    let request = chip.request_lines(Some(&rconfig), &lconfig)?;
+
+    let mut buffer = request::Buffer::new(4)?;
+    loop {
+        // Blocks until at least one event is available.
+        let events = request.read_edge_events(&mut buffer)?;
+        for event in events {
+            let event = event?;
+            println!(
+                "offset: {}  type: {:<7}  event #{}  line event #{}",
+                event.line_offset(),
+                match event.event_type()? {
+                    EdgeKind::Rising => "Rising",
+                    EdgeKind::Falling => "Falling",
+                },
+                event.global_seqno(),
+                event.line_seqno(),
+            );
+        }
+    }
+}
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [libgpiod][PATCH 8/8] bindings: rust: examples: replace tools examples with use case examples
  2023-06-23  4:39 ` [libgpiod][PATCH 8/8] bindings: rust: examples: replace tools examples with use case examples Kent Gibson
@ 2023-06-23  7:57   ` Erik Schilling
  2023-06-23  8:26     ` Kent Gibson
  0 siblings, 1 reply; 14+ messages in thread
From: Erik Schilling @ 2023-06-23  7:57 UTC (permalink / raw)
  To: Kent Gibson, linux-gpio, brgl

On Fri Jun 23, 2023 at 6:39 AM CEST, Kent Gibson wrote:
> Replace tool examples with use case examples drawn from the tools,
> gpio_events example with buffered_event_lifetimes, and
> gpio_threaded_info_events with reconfigure_input_to_output.
>
> Signed-off-by: Kent Gibson <warthog618@gmail.com>

Reviewed-by: Erik Schilling <erik.schilling@linaro.org>

>     let mut buffer = libgpiod::request::Buffer::new(4)?;

Slightly tangential:

Maybe the API should provide some sensible defaults for the buffer size?
(Or just set a sane default and provide ways to override it)? The change
from 1 -> 4 for bulk operations seems reasonable, but I feel like a user
just getting started with all of this likely won't know what might be
good values to pick...

- Erik

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [libgpiod][PATCH 7/8] bindings: rust: examples: consistency cleanup
  2023-06-23  4:39 ` [libgpiod][PATCH 7/8] bindings: rust: examples: consistency cleanup Kent Gibson
@ 2023-06-23  7:58   ` Erik Schilling
  0 siblings, 0 replies; 14+ messages in thread
From: Erik Schilling @ 2023-06-23  7:58 UTC (permalink / raw)
  To: Kent Gibson, linux-gpio, brgl

On Fri Jun 23, 2023 at 6:39 AM CEST, Kent Gibson wrote:
> A collection of minor changes to be more consistent with other examples:
>  - capitalize comments
>  - add line offset to value outputs
>  - drop comma from edge event outputs
>
> Signed-off-by: Kent Gibson <warthog618@gmail.com>

Reviewed-by: Erik Schilling <erik.schilling@linaro.org>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [libgpiod][PATCH 8/8] bindings: rust: examples: replace tools examples with use case examples
  2023-06-23  7:57   ` Erik Schilling
@ 2023-06-23  8:26     ` Kent Gibson
  0 siblings, 0 replies; 14+ messages in thread
From: Kent Gibson @ 2023-06-23  8:26 UTC (permalink / raw)
  To: Erik Schilling; +Cc: linux-gpio, brgl

On Fri, Jun 23, 2023 at 09:57:17AM +0200, Erik Schilling wrote:
> On Fri Jun 23, 2023 at 6:39 AM CEST, Kent Gibson wrote:
> > Replace tool examples with use case examples drawn from the tools,
> > gpio_events example with buffered_event_lifetimes, and
> > gpio_threaded_info_events with reconfigure_input_to_output.
> >
> > Signed-off-by: Kent Gibson <warthog618@gmail.com>
> 
> Reviewed-by: Erik Schilling <erik.schilling@linaro.org>
> 
> >     let mut buffer = libgpiod::request::Buffer::new(4)?;
> 
> Slightly tangential:
> 
> Maybe the API should provide some sensible defaults for the buffer size?
> (Or just set a sane default and provide ways to override it)? The change
> from 1 -> 4 for bulk operations seems reasonable, but I feel like a user
> just getting started with all of this likely won't know what might be
> good values to pick...
> 


The C API does that - it defaults to 64, IIRC - if you pass in 0.
And the Rust will do the same - read the docs:

    /// Create a new edge event buffer.
    ///
    /// If capacity equals 0, it will be set to a default value of 64. If
    /// capacity is larger than 1024, it will be limited to 1024.

Using 64 seems excessive to me, so I explictly set more reasonable
sizes in the examples.

Btw a casual user is probably fine with 1 - the events will still be
buffered in the kernel so the only advantages of > 1 is to reduce the
number of reads when handling bursts, and so drain the kernel buffer
slightly quicker.  I expect that the only users who would see an
appreciable difference in behaviour with different userspace buffer
sizes probably have a good idea why they want to be setting it.
Again, would be good to document that - if it isn't already.

Cheers,
Kent.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [libgpiod][PATCH 6/8] bindings: python: examples: replace tools examples with use case examples
  2023-06-23  4:38 ` [libgpiod][PATCH 6/8] bindings: python: examples: replace tools examples with use case examples Kent Gibson
@ 2023-06-23 19:31   ` Bartosz Golaszewski
  0 siblings, 0 replies; 14+ messages in thread
From: Bartosz Golaszewski @ 2023-06-23 19:31 UTC (permalink / raw)
  To: Kent Gibson; +Cc: linux-gpio

On Fri, Jun 23, 2023 at 6:40 AM Kent Gibson <warthog618@gmail.com> wrote:
>
> Replace tool examples with use case examples drawn from the tools.
>
> Signed-off-by: Kent Gibson <warthog618@gmail.com>
> ---
>  bindings/python/examples/Makefile.am          | 18 +++----
>  bindings/python/examples/find_line_by_name.py | 37 +++++++++++++++
>  bindings/python/examples/get_chip_info.py     | 20 ++++++++
>  bindings/python/examples/get_line_info.py     | 29 ++++++++++++
>  .../examples/get_multiple_line_values.py      | 29 ++++++++++++
>  bindings/python/examples/gpiodetect.py        | 15 ------
>  bindings/python/examples/gpiofind.py          | 20 --------
>  bindings/python/examples/gpioget.py           | 29 ------------
>  bindings/python/examples/gpioinfo.py          | 28 -----------
>  bindings/python/examples/gpiomon.py           | 26 ----------
>  bindings/python/examples/gpionotify.py        | 21 ---------
>  bindings/python/examples/gpioset.py           | 36 --------------
>  bindings/python/examples/helpers.py           | 15 ------
>  .../examples/reconfigure_input_to_output.py   | 39 +++++++++++++++
>  .../examples/toggle_multiple_line_values.py   | 47 +++++++++++++++++++
>  bindings/python/examples/watch_line_info.py   | 23 +++++++++
>  bindings/python/examples/watch_line_rising.py | 31 ++++++++++++
>  .../examples/watch_multiple_line_values.py    | 43 +++++++++++++++++
>  18 files changed, 308 insertions(+), 198 deletions(-)
>  create mode 100755 bindings/python/examples/find_line_by_name.py
>  create mode 100755 bindings/python/examples/get_chip_info.py
>  create mode 100755 bindings/python/examples/get_line_info.py
>  create mode 100755 bindings/python/examples/get_multiple_line_values.py
>  delete mode 100755 bindings/python/examples/gpiodetect.py
>  delete mode 100755 bindings/python/examples/gpiofind.py
>  delete mode 100755 bindings/python/examples/gpioget.py
>  delete mode 100755 bindings/python/examples/gpioinfo.py
>  delete mode 100755 bindings/python/examples/gpiomon.py
>  delete mode 100755 bindings/python/examples/gpionotify.py
>  delete mode 100755 bindings/python/examples/gpioset.py
>  delete mode 100644 bindings/python/examples/helpers.py
>  create mode 100755 bindings/python/examples/reconfigure_input_to_output.py
>  create mode 100755 bindings/python/examples/toggle_multiple_line_values.py
>  create mode 100755 bindings/python/examples/watch_line_info.py
>  create mode 100755 bindings/python/examples/watch_line_rising.py
>  create mode 100755 bindings/python/examples/watch_multiple_line_values.py
>
> diff --git a/bindings/python/examples/Makefile.am b/bindings/python/examples/Makefile.am
> index c8c1c98..52abafc 100644
> --- a/bindings/python/examples/Makefile.am
> +++ b/bindings/python/examples/Makefile.am
> @@ -3,13 +3,15 @@
>
>  EXTRA_DIST = \
>         async_watch_line_value.py \
> +       find_line_by_name.py \
> +       get_chip_info.py \
> +       get_line_info.py \
>         get_line_value.py \
> -       gpiodetect.py \
> -       gpiofind.py \
> -       gpioget.py \
> -       gpioinfo.py \
> -       gpiomon.py \
> -       gpionotify.py \
> -       gpioset.py \
> +       get_multiple_line_values.py \
> +       reconfigure_input_to_output.py \
>         toggle_line_value.py \
> -       watch_line_value.py
> +       toggle_multiple_line_values.py \
> +       watch_line_requests.py \
> +       watch_line_value.py \
> +       watch_line_rising.py \
> +       watch_multiple_line_values.py
> diff --git a/bindings/python/examples/find_line_by_name.py b/bindings/python/examples/find_line_by_name.py
> new file mode 100755
> index 0000000..58f1cd0
> --- /dev/null
> +++ b/bindings/python/examples/find_line_by_name.py
> @@ -0,0 +1,37 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of finding a line with the given name."""
> +
> +import gpiod
> +import os
> +
> +
> +def gpio_chips():

Please call it get_gpio_chip() to indicate it's an action performed by
the function.

> +    for entry in os.scandir("/dev/"):
> +        if gpiod.is_gpiochip_device(entry.path):
> +            yield entry.path
> +
> +
> +def find_line_by_name(line_name):
> +    # Names are not guaranteed unique, so this finds the first line with
> +    # the given name.
> +    for path in gpio_chips():
> +        with gpiod.Chip(path) as chip:
> +            try:
> +                offset = chip.line_offset_from_id(line_name)
> +                print("{}: {} {}".format(line_name, chip.get_info().name, offset))
> +                return
> +            except OSError:
> +                # An OSError is raised if the name is not found.
> +                continue
> +
> +    print("line '{}' not found".format(line_name))
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        find_line_by_name("GPIO19")
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> diff --git a/bindings/python/examples/get_chip_info.py b/bindings/python/examples/get_chip_info.py
> new file mode 100755
> index 0000000..7dc76fb
> --- /dev/null
> +++ b/bindings/python/examples/get_chip_info.py
> @@ -0,0 +1,20 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of reading the info for a chip."""
> +
> +import gpiod
> +
> +
> +def get_chip_info(chip_path):
> +    with gpiod.Chip(chip_path) as chip:
> +        info = chip.get_info()
> +        print("{} [{}] ({} lines)".format(info.name, info.label, info.num_lines))
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        get_chip_info("/dev/gpiochip0")
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> diff --git a/bindings/python/examples/get_line_info.py b/bindings/python/examples/get_line_info.py
> new file mode 100755
> index 0000000..cd4ebcc
> --- /dev/null
> +++ b/bindings/python/examples/get_line_info.py
> @@ -0,0 +1,29 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of reading the info for a line."""
> +
> +import gpiod
> +
> +
> +def get_line_info(chip_path, line_offset):
> +    with gpiod.Chip(chip_path) as chip:
> +        info = chip.get_line_info(line_offset)
> +        is_input = info.direction == gpiod.line.Direction.INPUT
> +        print(
> +            "line {:>3}: {:>12} {:>12} {:>8} {:>10}".format(
> +                info.offset,
> +                info.name or "unnamed",
> +                info.consumer or "unused",
> +                "input" if is_input else "output",
> +                "active-low" if info.active_low else "active-high",
> +            )
> +        )
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        get_line_info("/dev/gpiochip0", 3)
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> diff --git a/bindings/python/examples/get_multiple_line_values.py b/bindings/python/examples/get_multiple_line_values.py
> new file mode 100755
> index 0000000..46cf0b2
> --- /dev/null
> +++ b/bindings/python/examples/get_multiple_line_values.py
> @@ -0,0 +1,29 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of reading multiple lines."""
> +
> +import gpiod
> +
> +from gpiod.line import Direction
> +
> +
> +def get_multiple_line_values(chip_path, line_offsets):
> +    with gpiod.request_lines(
> +        chip_path,
> +        consumer="get-multiple-line-values",
> +        config={tuple(line_offsets): gpiod.LineSettings(direction=Direction.INPUT)},
> +    ) as request:
> +        vals = request.get_values()
> +
> +        for offset, val in zip(line_offsets, vals):
> +            print("{}={} ".format(offset, val), end="")
> +        print()
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        get_multiple_line_values("/dev/gpiochip0", [5, 3, 7])
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> diff --git a/bindings/python/examples/gpiodetect.py b/bindings/python/examples/gpiodetect.py
> deleted file mode 100755
> index dc98b03..0000000
> --- a/bindings/python/examples/gpiodetect.py
> +++ /dev/null
> @@ -1,15 +0,0 @@
> -#!/usr/bin/env python3
> -# SPDX-License-Identifier: GPL-2.0-or-later
> -# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
> -
> -"""Reimplementation of the gpiodetect tool in Python."""
> -
> -import gpiod
> -import os
> -
> -from helpers import gpio_chips
> -
> -if __name__ == "__main__":
> -    for chip in gpio_chips():
> -        info = chip.get_info()
> -        print("{} [{}] ({} lines)".format(info.name, info.label, info.num_lines))
> diff --git a/bindings/python/examples/gpiofind.py b/bindings/python/examples/gpiofind.py
> deleted file mode 100755
> index d41660d..0000000
> --- a/bindings/python/examples/gpiofind.py
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -#!/usr/bin/env python3
> -# SPDX-License-Identifier: GPL-2.0-or-later
> -# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
> -
> -"""Reimplementation of the gpiofind tool in Python."""
> -
> -import gpiod
> -import os
> -import sys
> -
> -if __name__ == "__main__":
> -    for entry in os.scandir("/dev/"):
> -        if gpiod.is_gpiochip_device(entry.path):
> -            with gpiod.Chip(entry.path) as chip:
> -                offset = chip.line_offset_from_id(sys.argv[1])
> -                if offset is not None:
> -                    print("{} {}".format(chip.get_info().name, offset))
> -                    sys.exit(0)
> -
> -    sys.exit(1)
> diff --git a/bindings/python/examples/gpioget.py b/bindings/python/examples/gpioget.py
> deleted file mode 100755
> index bf7e0a6..0000000
> --- a/bindings/python/examples/gpioget.py
> +++ /dev/null
> @@ -1,29 +0,0 @@
> -#!/usr/bin/env python3
> -# SPDX-License-Identifier: GPL-2.0-or-later
> -# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
> -
> -"""Simplified reimplementation of the gpioget tool in Python."""
> -
> -import gpiod
> -import sys
> -
> -from gpiod.line import Direction
> -
> -if __name__ == "__main__":
> -    if len(sys.argv) < 3:
> -        raise TypeError("usage: gpioget.py <gpiochip> <offset1> <offset2> ...")
> -
> -    path = sys.argv[1]
> -    lines = [int(line) if line.isdigit() else line for line in sys.argv[2:]]
> -
> -    request = gpiod.request_lines(
> -        path,
> -        consumer="gpioget.py",
> -        config={tuple(lines): gpiod.LineSettings(direction=Direction.INPUT)},
> -    )
> -
> -    vals = request.get_values()
> -
> -    for val in vals:
> -        print("{} ".format(val.value), end="")
> -    print()
> diff --git a/bindings/python/examples/gpioinfo.py b/bindings/python/examples/gpioinfo.py
> deleted file mode 100755
> index 3996dcf..0000000
> --- a/bindings/python/examples/gpioinfo.py
> +++ /dev/null
> @@ -1,28 +0,0 @@
> -#!/usr/bin/env python3
> -# SPDX-License-Identifier: GPL-2.0-or-later
> -# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
> -
> -"""Simplified reimplementation of the gpioinfo tool in Python."""
> -
> -import gpiod
> -import os
> -
> -from helpers import gpio_chips
> -
> -if __name__ == "__main__":
> -    for chip in gpio_chips():
> -        cinfo = chip.get_info()
> -        print("{} - {} lines:".format(cinfo.name, cinfo.num_lines))
> -
> -        for offset in range(0, cinfo.num_lines):
> -            linfo = chip.get_line_info(offset)
> -            is_input = linfo.direction == gpiod.line.Direction.INPUT
> -            print(
> -                "\tline {:>3}: {:>18} {:>12} {:>8} {:>10}".format(
> -                    linfo.offset,
> -                    linfo.name or "unnamed",
> -                    linfo.consumer or "unused",
> -                    "input" if is_input else "output",
> -                    "active-low" if linfo.active_low else "active-high",
> -                )
> -            )
> diff --git a/bindings/python/examples/gpiomon.py b/bindings/python/examples/gpiomon.py
> deleted file mode 100755
> index 702d7c8..0000000
> --- a/bindings/python/examples/gpiomon.py
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -#!/usr/bin/env python3
> -# SPDX-License-Identifier: GPL-2.0-or-later
> -# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
> -
> -"""Simplified reimplementation of the gpiomon tool in Python."""
> -
> -import gpiod
> -import sys
> -
> -from gpiod.line import Edge
> -
> -if __name__ == "__main__":
> -    if len(sys.argv) < 3:
> -        raise TypeError("usage: gpiomon.py <gpiochip> <offset1> <offset2> ...")
> -
> -    path = sys.argv[1]
> -    lines = [int(line) if line.isdigit() else line for line in sys.argv[2:]]
> -
> -    with gpiod.request_lines(
> -        path,
> -        consumer="gpiomon.py",
> -        config={tuple(lines): gpiod.LineSettings(edge_detection=Edge.BOTH)},
> -    ) as request:
> -        while True:
> -            for event in request.read_edge_events():
> -                print(event)
> diff --git a/bindings/python/examples/gpionotify.py b/bindings/python/examples/gpionotify.py
> deleted file mode 100755
> index 4e50515..0000000
> --- a/bindings/python/examples/gpionotify.py
> +++ /dev/null
> @@ -1,21 +0,0 @@
> -#!/usr/bin/env python3
> -# SPDX-License-Identifier: GPL-2.0-or-later
> -# SPDX-FileCopyrightText: 2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> -
> -"""Simplified reimplementation of the gpionotify tool in Python."""
> -
> -import gpiod
> -import sys
> -
> -if __name__ == "__main__":
> -    if len(sys.argv) < 3:
> -        raise TypeError("usage: gpionotify.py <gpiochip> <offset1> <offset2> ...")
> -
> -    path = sys.argv[1]
> -
> -    with gpiod.Chip(path) as chip:
> -        for line in sys.argv[2:]:
> -            chip.watch_line_info(line)
> -
> -        while True:
> -            print(chip.read_info_event())
> diff --git a/bindings/python/examples/gpioset.py b/bindings/python/examples/gpioset.py
> deleted file mode 100755
> index e6a516c..0000000
> --- a/bindings/python/examples/gpioset.py
> +++ /dev/null
> @@ -1,36 +0,0 @@
> -#!/usr/bin/env python3
> -# SPDX-License-Identifier: GPL-2.0-or-later
> -# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
> -
> -"""Simplified reimplementation of the gpioset tool in Python."""
> -
> -import gpiod
> -import sys
> -
> -from gpiod.line import Direction, Value
> -
> -if __name__ == "__main__":
> -    if len(sys.argv) < 3:
> -        raise TypeError(
> -            "usage: gpioset.py <gpiochip> <offset1>=<value1> <offset2>=<value2> ..."
> -        )
> -
> -    path = sys.argv[1]
> -
> -    def parse_value(arg):
> -        x, y = arg.split("=")
> -        return (x, Value(int(y)))
> -
> -    def make_settings(val):
> -        return gpiod.LineSettings(direction=Direction.OUTPUT, output_value=val)
> -
> -    lvs = [parse_value(arg) for arg in sys.argv[2:]]
> -    config = dict((l, make_settings(v)) for (l, v) in lvs)
> -
> -    request = gpiod.request_lines(
> -        path,
> -        consumer="gpioset.py",
> -        config=config,
> -    )
> -
> -    input()
> diff --git a/bindings/python/examples/helpers.py b/bindings/python/examples/helpers.py
> deleted file mode 100644
> index 8b91173..0000000
> --- a/bindings/python/examples/helpers.py
> +++ /dev/null
> @@ -1,15 +0,0 @@
> -# SPDX-License-Identifier: LGPL-2.1-or-later
> -# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
> -
> -import gpiod
> -import os
> -
> -
> -def gpio_chips():
> -    for path in [
> -        entry.path
> -        for entry in os.scandir("/dev/")
> -        if gpiod.is_gpiochip_device(entry.path)
> -    ]:
> -        with gpiod.Chip(path) as chip:
> -            yield chip
> diff --git a/bindings/python/examples/reconfigure_input_to_output.py b/bindings/python/examples/reconfigure_input_to_output.py
> new file mode 100755
> index 0000000..60d3015
> --- /dev/null
> +++ b/bindings/python/examples/reconfigure_input_to_output.py
> @@ -0,0 +1,39 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of requesting a line intended for bi-directional use as input and then switching to output."""

black doesn't break strings but could you limit it to 88 chars here?

> +
> +import gpiod
> +
> +from gpiod.line import Direction, Value
> +
> +
> +def reconfigure_input_to_output(chip_path, line_offset):
> +    # request the line initially as an input
> +    with gpiod.request_lines(
> +        chip_path,
> +        consumer="reconfigure-input-to-output",
> +        config={line_offset: gpiod.LineSettings(direction=Direction.INPUT)},
> +    ) as request:
> +        # read the current line value
> +        value = request.get_value(line_offset)
> +        print("{}={} (input)".format(line_offset, value))
> +        # switch the line to an output and drive it low
> +        request.reconfigure_lines(
> +            config={
> +                line_offset: gpiod.LineSettings(
> +                    direction=Direction.OUTPUT, output_value=Value.INACTIVE
> +                )
> +            }
> +        )
> +        # report the current driven value
> +        value = request.get_value(line_offset)
> +        print("{}={} (output)".format(line_offset, value))
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        reconfigure_input_to_output("/dev/gpiochip0", 5)
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> diff --git a/bindings/python/examples/toggle_multiple_line_values.py b/bindings/python/examples/toggle_multiple_line_values.py
> new file mode 100755
> index 0000000..12b968d
> --- /dev/null
> +++ b/bindings/python/examples/toggle_multiple_line_values.py
> @@ -0,0 +1,47 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of toggling multiple lines."""
> +
> +import gpiod
> +import time
> +
> +from gpiod.line import Direction, Value
> +
> +
> +def toggle_value(value):
> +    if value == Value.INACTIVE:
> +        return Value.ACTIVE
> +    return Value.INACTIVE
> +
> +
> +def toggle_multiple_line_values(chip_path, line_values):
> +    value_str = {Value.ACTIVE: "Active", Value.INACTIVE: "Inactive"}
> +
> +    request = gpiod.request_lines(
> +        chip_path,
> +        consumer="toggle-multiple-line-values",
> +        config={
> +            tuple(line_values.keys()): gpiod.LineSettings(direction=Direction.OUTPUT)
> +        },
> +        output_values=line_values,
> +    )
> +
> +    while True:
> +        print(
> +            " ".join("{}={}".format(l, value_str[v]) for (l, v) in line_values.items())
> +        )
> +        time.sleep(1)
> +        for l, v in line_values.items():
> +            line_values[l] = toggle_value(v)
> +        request.set_values(line_values)
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        toggle_multiple_line_values(
> +            "/dev/gpiochip0", {5: Value.ACTIVE, 3: Value.ACTIVE, 7: Value.INACTIVE}
> +        )
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> diff --git a/bindings/python/examples/watch_line_info.py b/bindings/python/examples/watch_line_info.py
> new file mode 100755
> index 0000000..e49a669
> --- /dev/null
> +++ b/bindings/python/examples/watch_line_info.py
> @@ -0,0 +1,23 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of watching for info changes on particular lines."""
> +
> +import gpiod
> +
> +
> +def watch_line_info(chip_path, line_offsets):
> +    with gpiod.Chip(chip_path) as chip:
> +        for offset in line_offsets:
> +            chip.watch_line_info(offset)
> +
> +        while True:
> +            print(chip.read_info_event())
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        watch_line_info("/dev/gpiochip0", [5, 3, 7])
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> diff --git a/bindings/python/examples/watch_line_rising.py b/bindings/python/examples/watch_line_rising.py
> new file mode 100755
> index 0000000..2350d76
> --- /dev/null
> +++ b/bindings/python/examples/watch_line_rising.py
> @@ -0,0 +1,31 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of watching for rising edges on a single line."""
> +
> +import gpiod
> +
> +from gpiod.line import Edge
> +
> +
> +def watch_line_rising(chip_path, line_offset):
> +    with gpiod.request_lines(
> +        chip_path,
> +        consumer="watch-line-rising",
> +        config={line_offset: gpiod.LineSettings(edge_detection=Edge.RISING)},
> +    ) as request:
> +        while True:
> +            # Blocks until at least one event is available
> +            for event in request.read_edge_events():
> +                print(
> +                    "line: %d  type: Rising   event #%d"
> +                    % (event.line_offset, event.line_seqno)
> +                )
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        watch_line_rising("/dev/gpiochip0", 5)
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> diff --git a/bindings/python/examples/watch_multiple_line_values.py b/bindings/python/examples/watch_multiple_line_values.py
> new file mode 100755
> index 0000000..4fbf05c
> --- /dev/null
> +++ b/bindings/python/examples/watch_multiple_line_values.py
> @@ -0,0 +1,43 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
> +
> +"""Minimal example of watching for edges on multiple lines."""
> +
> +import gpiod
> +
> +from gpiod.line import Edge
> +
> +
> +def edge_type(event):
> +    if event.event_type is event.Type.RISING_EDGE:
> +        return "Rising"
> +    if event.event_type is event.Type.FALLING_EDGE:
> +        return "Falling"
> +    return "Unknown"
> +
> +
> +def watch_multiple_line_values(chip_path, line_offsets):
> +    with gpiod.request_lines(
> +        chip_path,
> +        consumer="watch-multiple-line-values",
> +        config={tuple(line_offsets): gpiod.LineSettings(edge_detection=Edge.BOTH)},
> +    ) as request:
> +        while True:
> +            for event in request.read_edge_events():
> +                print(
> +                    "offset: %d  type: %-7s  event #%d  line event #%d"

Could you please stick to the "{}".format() style of output formatting
for print() that we already use across the code base? Unless there's a
very good reason not to?

Bart

> +                    % (
> +                        event.line_offset,
> +                        edge_type(event),
> +                        event.global_seqno,
> +                        event.line_seqno,
> +                    )
> +                )
> +
> +
> +if __name__ == "__main__":
> +    try:
> +        watch_multiple_line_values("/dev/gpiochip0", [5, 3, 7])
> +    except OSError as ex:
> +        print(ex, "\nCustomise the example configuration to suit your situation")
> --
> 2.41.0
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [libgpiod][PATCH 0/8] replace tool examples with use case examples
  2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
                   ` (7 preceding siblings ...)
  2023-06-23  4:39 ` [libgpiod][PATCH 8/8] bindings: rust: examples: replace tools examples with use case examples Kent Gibson
@ 2023-06-23 19:35 ` Bartosz Golaszewski
  8 siblings, 0 replies; 14+ messages in thread
From: Bartosz Golaszewski @ 2023-06-23 19:35 UTC (permalink / raw)
  To: Kent Gibson; +Cc: linux-gpio

On Fri, Jun 23, 2023 at 6:39 AM Kent Gibson <warthog618@gmail.com> wrote:
>
> This series is the continuation of providing a set of use case based examples
> for libgpiod. The focus of this series is replacement of the examples
> replicating the the tools with examples that minimally cover the use case that
> each tool addresses.
>
> The mapping from tool to use case is:
>   gpiodetect  ->  get_chip_info
>   gpiofind    ->  find_line_by_name
>   gpioget     ->  get_multiple_line_values
>   gpioinfo    ->  get_line_info
>   gpiomon     ->  watch_multiple_line_values
>   gpionotify  ->  watch_line_info
>   gpioset     ->  toggle_multiple_line_values
>
> Also added a watch_line_rising example to demonstrate getting events from only
> one edge rather than both, so another gpiomon sub-case.
>
> The rust bindings had a couple of additional examples, gpio_events and
> gpio_threaded_info_events.
>
> gpio_threaded_info_events is an example of using one thread to generate info
> change events that are observed by another thread.  This is borrowed from test
> cases and has no other practical application, but the reconfiguring component
> inspired the reconfigure_input_to_output example.  That provides an example of
> reconfiguring a requested line, and is provided for all languages, not just
> rust.
>
> gpio_events is an example of how borrowed buffered events must be cloned before
> the event buffer can be reused.  This was simplified and renamed
> buffered_event_lifetimes.  As I write this I realise it may also be applicable
> to other languages - as an example of using gpiod_edge_event_copy().
> Maybe provide those in v2, or a subsequent series?
>
> The series is split into 8 parts.  For each language there is a patch that
> provides some consistency cleanups to make the existing examples more consistent
> with each other, with the examples in other languages, and with the examples to
> follow. There are also a few minor bug fixes that didn't seem sufficiently
> serious to warrant a separate patch.
>
> The second patch for each language replaces the old tool examples with the new
> use case based examples.
>
> Cheers,
> Kent.
>
> Kent Gibson (8):
>   core: examples: consistency cleanups
>   core: examples: add more use case examples
>   bindings: cxx: examples: consistency cleanup
>   bindings: cxx: examples: replace tools examples with use case examples
>   bindings: python: examples: consistency cleanup
>   bindings: python: examples: replace tools examples with use case
>     examples
>   bindings: rust: examples: consistency cleanup
>   bindings: rust: examples: replace tools examples with use case
>     examples
>
>  bindings/cxx/examples/.gitignore              |  16 +-
>  bindings/cxx/examples/Makefile.am             |  42 ++---
>  .../cxx/examples/async_watch_line_value.cpp   |   8 +-
>  bindings/cxx/examples/find_line_by_name.cpp   |  42 +++++
>  bindings/cxx/examples/get_chip_info.cpp       |  27 ++++
>  bindings/cxx/examples/get_line_info.cpp       |  39 +++++
>  bindings/cxx/examples/get_line_value.cpp      |  28 ++--
>  .../cxx/examples/get_multiple_line_values.cpp |  40 +++++
>  bindings/cxx/examples/gpiodetectcxx.cpp       |  30 ----
>  bindings/cxx/examples/gpiofindcxx.cpp         |  32 ----
>  bindings/cxx/examples/gpiogetcxx.cpp          |  40 -----
>  bindings/cxx/examples/gpioinfocxx.cpp         |  61 -------
>  bindings/cxx/examples/gpiomoncxx.cpp          |  65 --------
>  bindings/cxx/examples/gpionotifycxx.cpp       |  55 -------
>  bindings/cxx/examples/gpiosetcxx.cpp          |  53 ------
>  .../examples/reconfigure_input_to_output.cpp  |  56 +++++++
>  bindings/cxx/examples/toggle_line_value.cpp   |  16 +-
>  .../examples/toggle_multiple_line_values.cpp  |  63 ++++++++
>  bindings/cxx/examples/watch_line_info.cpp     |  49 ++++++
>  bindings/cxx/examples/watch_line_rising.cpp   |  64 ++++++++
>  bindings/cxx/examples/watch_line_value.cpp    |  12 +-
>  .../examples/watch_multiple_line_values.cpp   |  60 +++++++
>  bindings/python/examples/Makefile.am          |  18 ++-
>  .../python/examples/async_watch_line_value.py |  15 +-
>  bindings/python/examples/find_line_by_name.py |  37 +++++
>  bindings/python/examples/get_chip_info.py     |  20 +++
>  bindings/python/examples/get_line_info.py     |  29 ++++
>  bindings/python/examples/get_line_value.py    |  13 +-
>  .../examples/get_multiple_line_values.py      |  29 ++++
>  bindings/python/examples/gpiodetect.py        |  15 --
>  bindings/python/examples/gpiofind.py          |  20 ---
>  bindings/python/examples/gpioget.py           |  29 ----
>  bindings/python/examples/gpioinfo.py          |  28 ----
>  bindings/python/examples/gpiomon.py           |  26 ---
>  bindings/python/examples/gpionotify.py        |  21 ---
>  bindings/python/examples/gpioset.py           |  36 -----
>  bindings/python/examples/helpers.py           |  15 --
>  .../examples/reconfigure_input_to_output.py   |  39 +++++
>  bindings/python/examples/toggle_line_value.py |  34 ++--
>  .../examples/toggle_multiple_line_values.py   |  47 ++++++
>  bindings/python/examples/watch_line_info.py   |  23 +++
>  bindings/python/examples/watch_line_rising.py |  31 ++++
>  bindings/python/examples/watch_line_value.py  |  19 ++-
>  .../examples/watch_multiple_line_values.py    |  43 +++++
>  bindings/rust/libgpiod/examples/Makefile.am   |  21 +--
>  .../examples/buffered_event_lifetimes.rs      |  58 +++++++
>  .../libgpiod/examples/find_line_by_name.rs    |  29 ++++
>  .../rust/libgpiod/examples/get_chip_info.rs   |  22 +++
>  .../rust/libgpiod/examples/get_line_info.rs   |  37 +++++
>  .../rust/libgpiod/examples/get_line_value.rs  |   4 +-
>  .../examples/get_multiple_line_values.rs      |  29 ++++
>  .../rust/libgpiod/examples/gpio_events.rs     |  88 ----------
>  .../examples/gpio_threaded_info_events.rs     | 132 ---------------
>  bindings/rust/libgpiod/examples/gpiodetect.rs |  30 ----
>  bindings/rust/libgpiod/examples/gpiofind.rs   |  36 -----
>  bindings/rust/libgpiod/examples/gpioget.rs    |  45 ------
>  bindings/rust/libgpiod/examples/gpioinfo.rs   |  97 -----------
>  bindings/rust/libgpiod/examples/gpiomon.rs    |  74 ---------
>  bindings/rust/libgpiod/examples/gpionotify.rs |  53 ------
>  bindings/rust/libgpiod/examples/gpioset.rs    |  63 --------
>  bindings/rust/libgpiod/examples/gpiowatch.rs  |  53 ------
>  .../examples/reconfigure_input_to_output.rs   |  42 +++++
>  .../libgpiod/examples/toggle_line_value.rs    |  17 +-
>  .../examples/toggle_multiple_line_values.rs   |  55 +++++++
>  .../rust/libgpiod/examples/watch_line_info.rs |  32 ++++
>  .../libgpiod/examples/watch_line_rising.rs    |  44 +++++
>  .../libgpiod/examples/watch_line_value.rs     |  10 +-
>  .../examples/watch_multiple_line_values.rs    |  46 ++++++
>  examples/.gitignore                           |   9 ++
>  examples/Makefile.am                          |  35 +++-
>  examples/async_watch_line_value.c             |   6 +-
>  examples/find_line_by_name.c                  | 111 +++++++++++++
>  examples/get_chip_info.c                      |  40 +++++
>  examples/get_line_info.c                      |  56 +++++++
>  examples/get_line_value.c                     |  11 +-
>  examples/get_multiple_line_values.c           | 119 ++++++++++++++
>  examples/reconfigure_input_to_output.c        | 152 ++++++++++++++++++
>  examples/toggle_line_value.c                  |  17 +-
>  examples/toggle_multiple_line_values.c        | 136 ++++++++++++++++
>  examples/watch_line_info.c                    |  72 +++++++++
>  examples/watch_line_rising.c                  | 129 +++++++++++++++
>  examples/watch_line_value.c                   |   6 +-
>  examples/watch_multiple_line_values.c         | 140 ++++++++++++++++
>  83 files changed, 2289 insertions(+), 1352 deletions(-)
>  create mode 100644 bindings/cxx/examples/find_line_by_name.cpp
>  create mode 100644 bindings/cxx/examples/get_chip_info.cpp
>  create mode 100644 bindings/cxx/examples/get_line_info.cpp
>  create mode 100644 bindings/cxx/examples/get_multiple_line_values.cpp
>  delete mode 100644 bindings/cxx/examples/gpiodetectcxx.cpp
>  delete mode 100644 bindings/cxx/examples/gpiofindcxx.cpp
>  delete mode 100644 bindings/cxx/examples/gpiogetcxx.cpp
>  delete mode 100644 bindings/cxx/examples/gpioinfocxx.cpp
>  delete mode 100644 bindings/cxx/examples/gpiomoncxx.cpp
>  delete mode 100644 bindings/cxx/examples/gpionotifycxx.cpp
>  delete mode 100644 bindings/cxx/examples/gpiosetcxx.cpp
>  create mode 100644 bindings/cxx/examples/reconfigure_input_to_output.cpp
>  create mode 100644 bindings/cxx/examples/toggle_multiple_line_values.cpp
>  create mode 100644 bindings/cxx/examples/watch_line_info.cpp
>  create mode 100644 bindings/cxx/examples/watch_line_rising.cpp
>  create mode 100644 bindings/cxx/examples/watch_multiple_line_values.cpp
>  create mode 100755 bindings/python/examples/find_line_by_name.py
>  create mode 100755 bindings/python/examples/get_chip_info.py
>  create mode 100755 bindings/python/examples/get_line_info.py
>  create mode 100755 bindings/python/examples/get_multiple_line_values.py
>  delete mode 100755 bindings/python/examples/gpiodetect.py
>  delete mode 100755 bindings/python/examples/gpiofind.py
>  delete mode 100755 bindings/python/examples/gpioget.py
>  delete mode 100755 bindings/python/examples/gpioinfo.py
>  delete mode 100755 bindings/python/examples/gpiomon.py
>  delete mode 100755 bindings/python/examples/gpionotify.py
>  delete mode 100755 bindings/python/examples/gpioset.py
>  delete mode 100644 bindings/python/examples/helpers.py
>  create mode 100755 bindings/python/examples/reconfigure_input_to_output.py
>  create mode 100755 bindings/python/examples/toggle_multiple_line_values.py
>  create mode 100755 bindings/python/examples/watch_line_info.py
>  create mode 100755 bindings/python/examples/watch_line_rising.py
>  create mode 100755 bindings/python/examples/watch_multiple_line_values.py
>  create mode 100644 bindings/rust/libgpiod/examples/buffered_event_lifetimes.rs
>  create mode 100644 bindings/rust/libgpiod/examples/find_line_by_name.rs
>  create mode 100644 bindings/rust/libgpiod/examples/get_chip_info.rs
>  create mode 100644 bindings/rust/libgpiod/examples/get_line_info.rs
>  create mode 100644 bindings/rust/libgpiod/examples/get_multiple_line_values.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpio_events.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpiodetect.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpiofind.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpioget.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpioinfo.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpiomon.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpionotify.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpioset.rs
>  delete mode 100644 bindings/rust/libgpiod/examples/gpiowatch.rs
>  create mode 100644 bindings/rust/libgpiod/examples/reconfigure_input_to_output.rs
>  create mode 100644 bindings/rust/libgpiod/examples/toggle_multiple_line_values.rs
>  create mode 100644 bindings/rust/libgpiod/examples/watch_line_info.rs
>  create mode 100644 bindings/rust/libgpiod/examples/watch_line_rising.rs
>  create mode 100644 bindings/rust/libgpiod/examples/watch_multiple_line_values.rs
>  create mode 100644 examples/find_line_by_name.c
>  create mode 100644 examples/get_chip_info.c
>  create mode 100644 examples/get_line_info.c
>  create mode 100644 examples/get_multiple_line_values.c
>  create mode 100644 examples/reconfigure_input_to_output.c
>  create mode 100644 examples/toggle_multiple_line_values.c
>  create mode 100644 examples/watch_line_info.c
>  create mode 100644 examples/watch_line_rising.c
>  create mode 100644 examples/watch_multiple_line_values.c
>
> --
> 2.41.0
>

Thanks! I applied patches 1-5 and 7-8. I had some comments on patch 6,
you don't have to resend the others.

Bart

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2023-06-23 19:36 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-06-23  4:38 [libgpiod][PATCH 0/8] replace tool examples with use case examples Kent Gibson
2023-06-23  4:38 ` [libgpiod][PATCH 1/8] core: examples: consistency cleanups Kent Gibson
2023-06-23  4:38 ` [libgpiod][PATCH 2/8] core: examples: add more use case examples Kent Gibson
2023-06-23  4:38 ` [libgpiod][PATCH 3/8] bindings: cxx: examples: consistency cleanup Kent Gibson
2023-06-23  4:38 ` [libgpiod][PATCH 4/8] bindings: cxx: examples: replace tools examples with use case examples Kent Gibson
2023-06-23  4:38 ` [libgpiod][PATCH 5/8] bindings: python: examples: consistency cleanup Kent Gibson
2023-06-23  4:38 ` [libgpiod][PATCH 6/8] bindings: python: examples: replace tools examples with use case examples Kent Gibson
2023-06-23 19:31   ` Bartosz Golaszewski
2023-06-23  4:39 ` [libgpiod][PATCH 7/8] bindings: rust: examples: consistency cleanup Kent Gibson
2023-06-23  7:58   ` Erik Schilling
2023-06-23  4:39 ` [libgpiod][PATCH 8/8] bindings: rust: examples: replace tools examples with use case examples Kent Gibson
2023-06-23  7:57   ` Erik Schilling
2023-06-23  8:26     ` Kent Gibson
2023-06-23 19:35 ` [libgpiod][PATCH 0/8] replace tool " Bartosz Golaszewski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).