All of lore.kernel.org
 help / color / mirror / Atom feed
* [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0
@ 2020-12-10 13:23 Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 01/14] bindings: cxx: check for error from gpiod_line_bulk_new() Bartosz Golaszewski
                   ` (14 more replies)
  0 siblings, 15 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

The following series removes a lot of interfaces that were deemed overkill
in libgpiod and the removal of which was suggested to me before proceeding
with the new API.

This leaves a couple holes in the library but we'll follow them up with
more improvements all over the tree. We'll create a new object called
gpiod_request for dealing with line requests of arbitrary size. We'll
probably remove the the bulk objects from bindings and eventually we'll
switch to using the v2 kernel uAPI.

Andy - a note for you: I know you're always very thorough in your reviews
but in this case let's consider this series preparing a construction zone
for the new API. Please don't nitpick too much. :)

Bartosz Golaszewski (14):
  bindings: cxx: check for error from gpiod_line_bulk_new()
  build: drop the message about tests having been built successfully
  core: export gpiod_is_gpiochip_device()
  bulk: drop the limit on the max number of lines
  core: drop line iterators
  treewide: kill opening chips by label
  API: move gpiod_line_get_chip() to line attributes section
  core: kill gpiod_line_close_chip()
  core: kill gpiod_line_get()
  treewide: kill global line lookup
  treewide: kill find_lines()
  core: rework gpiod_chip_find_line()
  build: add a configure switch for building examples
  core: kill chip iterators

 bindings/cxx/Makefile.am                |   8 +-
 bindings/cxx/chip.cpp                   |  47 +--
 bindings/cxx/examples/Makefile.am       |   4 +-
 bindings/cxx/examples/gpiodetectcxx.cpp |  13 +-
 bindings/cxx/examples/gpiofindcxx.cpp   |  18 +-
 bindings/cxx/examples/gpioinfocxx.cpp   |  43 ++-
 bindings/cxx/gpiod.hpp                  | 147 +-------
 bindings/cxx/iter.cpp                   |  95 +----
 bindings/cxx/line.cpp                   |  15 -
 bindings/cxx/line_bulk.cpp              |  24 +-
 bindings/cxx/tests/tests-chip.cpp       |  62 ++--
 bindings/cxx/tests/tests-iter.cpp       |  37 --
 bindings/cxx/tests/tests-line.cpp       |  19 -
 bindings/python/Makefile.am             |  10 +-
 bindings/python/examples/gpiodetect.py  |  12 +-
 bindings/python/examples/gpiofind.py    |  15 +-
 bindings/python/examples/gpioinfo.py    |  33 +-
 bindings/python/gpiodmodule.c           | 473 +++++++-----------------
 bindings/python/tests/gpiod_py_test.py  | 100 +----
 configure.ac                            |  12 +
 include/gpiod.h                         | 258 ++-----------
 lib/Makefile.am                         |   2 +-
 lib/core.c                              |  12 +-
 lib/helpers.c                           | 176 +++------
 lib/iter.c                              | 171 ---------
 tests/Makefile.am                       |  13 -
 tests/gpiod-test.h                      |   4 -
 tests/tests-bulk.c                      |   9 -
 tests/tests-chip.c                      |  97 +----
 tests/tests-iter.c                      | 123 ------
 tests/tests-line.c                      |  52 ---
 tools/gpiodetect.c                      |  29 +-
 tools/gpiofind.c                        |  34 +-
 tools/gpioinfo.c                        |  41 +-
 tools/gpiomon.c                         |   5 +-
 tools/tools-common.c                    |  15 +
 tools/tools-common.h                    |   3 +
 37 files changed, 557 insertions(+), 1674 deletions(-)
 delete mode 100644 lib/iter.c
 delete mode 100644 tests/tests-iter.c

-- 
2.29.1


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

* [libgpiod][PATCH 01/14] bindings: cxx: check for error from gpiod_line_bulk_new()
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 02/14] build: drop the message about tests having been built successfully Bartosz Golaszewski
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

We call gpiod_line_bulk_new() in C++ bindings but never check its return
value. This function can fail so add a private method to line_bulk that
calls it and throws an exception if it returns NULL.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/gpiod.hpp     |  1 +
 bindings/cxx/line_bulk.cpp | 22 ++++++++++++++++------
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
index a4ef7c9..8c8e6c9 100644
--- a/bindings/cxx/gpiod.hpp
+++ b/bindings/cxx/gpiod.hpp
@@ -869,6 +869,7 @@ private:
 
 	using line_bulk_ptr = ::std::unique_ptr<::gpiod_line_bulk, line_bulk_deleter>;
 
+	line_bulk_ptr make_line_bulk_ptr(void) const;
 	line_bulk_ptr to_line_bulk(void) const;
 
 	::std::vector<line> _m_bulk;
diff --git a/bindings/cxx/line_bulk.cpp b/bindings/cxx/line_bulk.cpp
index c24e91d..1de90eb 100644
--- a/bindings/cxx/line_bulk.cpp
+++ b/bindings/cxx/line_bulk.cpp
@@ -256,8 +256,7 @@ line_bulk line_bulk::event_wait(const ::std::chrono::nanoseconds& timeout) const
 	this->throw_if_empty();
 	line::chip_guard lock_chip(this->_m_bulk.front());
 
-	auto ev_bulk = ::gpiod_line_bulk_new(this->size());
-	line_bulk_ptr ev_bulk_deleter(ev_bulk);
+	auto ev_bulk = this->make_line_bulk_ptr();
 	auto bulk = this->to_line_bulk();
 	::timespec ts;
 	line_bulk ret;
@@ -266,16 +265,16 @@ line_bulk line_bulk::event_wait(const ::std::chrono::nanoseconds& timeout) const
 	ts.tv_sec = timeout.count() / 1000000000ULL;
 	ts.tv_nsec = timeout.count() % 1000000000ULL;
 
-	rv = ::gpiod_line_event_wait_bulk(bulk.get(), ::std::addressof(ts), ev_bulk);
+	rv = ::gpiod_line_event_wait_bulk(bulk.get(), ::std::addressof(ts), ev_bulk.get());
 	if (rv < 0) {
 		throw ::std::system_error(errno, ::std::system_category(),
 					  "error polling for events");
 	} else if (rv > 0) {
 		auto chip = this->_m_bulk[0].get_chip();
-		auto num_lines = ::gpiod_line_bulk_num_lines(ev_bulk);
+		auto num_lines = ::gpiod_line_bulk_num_lines(ev_bulk.get());
 
 		for (unsigned int i = 0; i < num_lines; i++)
-			ret.append(line(::gpiod_line_bulk_get_line(ev_bulk, i), chip));
+			ret.append(line(::gpiod_line_bulk_get_line(ev_bulk.get(), i), chip));
 	}
 
 	return ret;
@@ -340,10 +339,21 @@ void line_bulk::throw_if_empty(void) const
 		throw ::std::logic_error("line_bulk not holding any GPIO lines");
 }
 
-line_bulk::line_bulk_ptr line_bulk::to_line_bulk(void) const
+line_bulk::line_bulk_ptr line_bulk::make_line_bulk_ptr(void) const
 {
 	line_bulk_ptr bulk(::gpiod_line_bulk_new(this->size()));
 
+	if (!bulk)
+		throw ::std::system_error(errno, ::std::system_category(),
+					  "unable to allocate new bulk object");
+
+	return bulk;
+}
+
+line_bulk::line_bulk_ptr line_bulk::to_line_bulk(void) const
+{
+	line_bulk_ptr bulk = this->make_line_bulk_ptr();
+
 	for (auto& it: this->_m_bulk)
 		::gpiod_line_bulk_add_line(bulk.get(), it._m_line);
 
-- 
2.29.1


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

* [libgpiod][PATCH 02/14] build: drop the message about tests having been built successfully
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 01/14] bindings: cxx: check for error from gpiod_line_bulk_new() Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 03/14] core: export gpiod_is_gpiochip_device() Bartosz Golaszewski
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

This is a leftover from early times. We now have multiple different
test suites and none prints such a message. Drop it.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 tests/Makefile.am | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5c7edb6..2d3b959 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -28,15 +28,3 @@ gpiod_test_SOURCES =			\
 		tests-iter.c		\
 		tests-line.c		\
 		tests-misc.c
-
-all-local: gpiod-test
-	@echo " ********************************************************"
-	@echo " * Core tests have been built as tests/gpiod-test.      *"
-	@echo " *                                                      *"
-	@echo " * They require a recent linux kernel version and the   *"
-	@echo " * gpio-mockup module (must not be built-in).           *"
-	@echo " *                                                      *"
-	@echo " * Run the test executable with superuser privileges or *"
-	@echo " * make sure /dev/gpiochipX files are readable and      *"
-	@echo " * writable by normal users.                            *"
-	@echo " ********************************************************"
-- 
2.29.1


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

* [libgpiod][PATCH 03/14] core: export gpiod_is_gpiochip_device()
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 01/14] bindings: cxx: check for error from gpiod_line_bulk_new() Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 02/14] build: drop the message about tests having been built successfully Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 04/14] bulk: drop the limit on the max number of lines Bartosz Golaszewski
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

We'll be dropping chip iterators treewide. Instead we'll encourage
scanning /dev for GPIO chip devices. Exporting this function allows
users to easily check if given file represents a GPIO chip character
device.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 include/gpiod.h    |  8 ++++++++
 lib/core.c         |  4 ++--
 tests/tests-chip.c | 15 +++++++++++++++
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/include/gpiod.h b/include/gpiod.h
index 355a99a..742dfc2 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -71,6 +71,14 @@ struct gpiod_line_bulk;
  * Functions and data structures dealing with GPIO chips.
  */
 
+/**
+ * @brief Check if the file pointed to by path is a GPIO chip character device.
+ * @param path Path to check.
+ * @return True if the file exists and is a GPIO chip character device or a
+ *         symbolic link to it.
+ */
+bool gpiod_is_gpiochip_device(const char *path) GPIOD_API;
+
 /**
  * @brief Open a gpiochip by path.
  * @param path Path to the gpiochip device file.
diff --git a/lib/core.c b/lib/core.c
index bf52fa6..efba959 100644
--- a/lib/core.c
+++ b/lib/core.c
@@ -177,7 +177,7 @@ void gpiod_line_bulk_foreach_line(struct gpiod_line_bulk *bulk,
 	     (index) < (bulk)->num_lines;				\
 	     (index)++, (line) = (bulk)->lines[(index)])
 
-static bool is_gpiochip_cdev(const char *path)
+bool gpiod_is_gpiochip_device(const char *path)
 {
 	char *name, *realname, *sysfsp, sysfsdev[16], devstr[16];
 	struct stat statbuf;
@@ -282,7 +282,7 @@ struct gpiod_chip *gpiod_chip_open(const char *path)
 	 * We were able to open the file but is it really a gpiochip character
 	 * device?
 	 */
-	if (!is_gpiochip_cdev(path))
+	if (!gpiod_is_gpiochip_device(path))
 		goto err_close_fd;
 
 	chip = malloc(sizeof(*chip));
diff --git a/tests/tests-chip.c b/tests/tests-chip.c
index 289c458..2f19c49 100644
--- a/tests/tests-chip.c
+++ b/tests/tests-chip.c
@@ -11,6 +11,21 @@
 
 #define GPIOD_TEST_GROUP "chip"
 
+GPIOD_TEST_CASE(is_gpiochip_good, 0, { 8 })
+{
+	g_assert_true(gpiod_is_gpiochip_device(gpiod_test_chip_path(0)));
+}
+
+GPIOD_TEST_CASE(is_gpiochip_bad, 0, { 8 })
+{
+	g_assert_false(gpiod_is_gpiochip_device("/dev/null"));
+}
+
+GPIOD_TEST_CASE(is_gpiochip_nonexistent, 0, { 8 })
+{
+	g_assert_false(gpiod_is_gpiochip_device("/dev/nonexistent_gpiochip"));
+}
+
 GPIOD_TEST_CASE(open_good, 0, { 8 })
 {
 	g_autoptr(gpiod_chip_struct) chip = NULL;
-- 
2.29.1


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

* [libgpiod][PATCH 04/14] bulk: drop the limit on the max number of lines
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (2 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 03/14] core: export gpiod_is_gpiochip_device() Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 05/14] core: drop line iterators Bartosz Golaszewski
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

The limit of 64 lines max per bulk object is wrong. We may want to
retrieve all lines from a chip exporting more than 64. We'll be reducing
the role of bulk objects soon so drop this limit now.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/line_bulk.cpp    |  2 +-
 bindings/python/gpiodmodule.c | 14 ++++++++------
 include/gpiod.h               |  7 -------
 lib/core.c                    |  8 +++++---
 tests/tests-bulk.c            |  9 ---------
 tools/gpiomon.c               |  5 ++++-
 6 files changed, 18 insertions(+), 27 deletions(-)

diff --git a/bindings/cxx/line_bulk.cpp b/bindings/cxx/line_bulk.cpp
index 1de90eb..6e88d21 100644
--- a/bindings/cxx/line_bulk.cpp
+++ b/bindings/cxx/line_bulk.cpp
@@ -48,7 +48,7 @@ const ::std::map<::std::bitset<32>, int, bitset_cmp> reqflag_mapping = {
 
 } /* namespace */
 
-const unsigned int line_bulk::MAX_LINES = GPIOD_LINE_BULK_MAX_LINES;
+const unsigned int line_bulk::MAX_LINES = 64;
 
 line_bulk::line_bulk(const ::std::vector<line>& lines)
 	: _m_bulk()
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index b5e69a5..b9b5770 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -8,6 +8,8 @@
 #include <Python.h>
 #include <gpiod.h>
 
+#define LINE_REQUEST_MAX_LINES 64
+
 typedef struct {
 	PyObject_HEAD
 	struct gpiod_chip *chip;
@@ -1138,7 +1140,7 @@ static int gpiod_LineBulk_init(gpiod_LineBulkObject *self,
 				"Argument must be a non-empty sequence");
 		return -1;
 	}
-	if (self->num_lines > GPIOD_LINE_BULK_MAX_LINES) {
+	if (self->num_lines > LINE_REQUEST_MAX_LINES) {
 		PyErr_SetString(PyExc_TypeError,
 				"Too many objects in the sequence");
 		return -1;
@@ -1334,7 +1336,7 @@ static PyObject *gpiod_LineBulk_request(gpiod_LineBulkObject *self,
 				  NULL };
 
 	int rv, type = gpiod_LINE_REQ_DIR_AS_IS, flags = 0,
-	    default_vals[GPIOD_LINE_BULK_MAX_LINES], val;
+	    default_vals[LINE_REQUEST_MAX_LINES], val;
 	PyObject *def_vals_obj = NULL, *iter, *next;
 	struct gpiod_line_request_config conf;
 	struct gpiod_line_bulk *bulk;
@@ -1413,7 +1415,7 @@ PyDoc_STRVAR(gpiod_LineBulk_get_values_doc,
 static PyObject *gpiod_LineBulk_get_values(gpiod_LineBulkObject *self,
 					   PyObject *Py_UNUSED(ignored))
 {
-	int rv, vals[GPIOD_LINE_BULK_MAX_LINES];
+	int rv, vals[LINE_REQUEST_MAX_LINES];
 	struct gpiod_line_bulk *bulk;
 	PyObject *val_list, *val;
 	Py_ssize_t i;
@@ -1506,7 +1508,7 @@ PyDoc_STRVAR(gpiod_LineBulk_set_values_doc,
 static PyObject *gpiod_LineBulk_set_values(gpiod_LineBulkObject *self,
 					   PyObject *args)
 {
-	int rv, vals[GPIOD_LINE_BULK_MAX_LINES];
+	int rv, vals[LINE_REQUEST_MAX_LINES];
 	struct gpiod_line_bulk *bulk;
 	PyObject *val_list;
 
@@ -1556,7 +1558,7 @@ PyDoc_STRVAR(gpiod_LineBulk_set_config_doc,
 static PyObject *gpiod_LineBulk_set_config(gpiod_LineBulkObject *self,
 					   PyObject *args)
 {
-	int rv, vals[GPIOD_LINE_BULK_MAX_LINES];
+	int rv, vals[LINE_REQUEST_MAX_LINES];
 	struct gpiod_line_bulk *bulk;
 	PyObject *val_list;
 	const int *valp;
@@ -1672,7 +1674,7 @@ static PyObject *gpiod_LineBulk_set_direction_output(
 				gpiod_LineBulkObject *self,
 				PyObject *args)
 {
-	int rv, vals[GPIOD_LINE_BULK_MAX_LINES];
+	int rv, vals[LINE_REQUEST_MAX_LINES];
 	struct gpiod_line_bulk *bulk;
 	PyObject *val_list;
 	const int *valp;
diff --git a/include/gpiod.h b/include/gpiod.h
index 742dfc2..9ffb446 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -225,17 +225,10 @@ gpiod_chip_find_lines(struct gpiod_chip *chip, const char **names) GPIOD_API;
  * on multiple lines at once.
  */
 
-/**
- * @brief Maximum number of GPIO lines that can be requested at once or stored
- *        in a line bulk object at the same time.
- */
-#define GPIOD_LINE_BULK_MAX_LINES	64
-
 /**
  * @brief Allocate and initialize a new line bulk object.
  * @param max_lines Maximum number of lines this object can hold.
  * @return New line bulk object or NULL on error.
- * @note max_lines must not exceed ::GPIOD_LINE_BULK_MAX_LINES.
  */
 struct gpiod_line_bulk *gpiod_line_bulk_new(unsigned int max_lines) GPIOD_API;
 
diff --git a/lib/core.c b/lib/core.c
index efba959..d96e6cf 100644
--- a/lib/core.c
+++ b/lib/core.c
@@ -22,6 +22,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#define LINE_REQUEST_MAX_LINES	64
+
 enum {
 	LINE_FREE = 0,
 	LINE_REQUESTED_VALUES,
@@ -94,7 +96,7 @@ struct gpiod_line_bulk *gpiod_line_bulk_new(unsigned int max_lines)
 	struct gpiod_line_bulk *bulk;
 	size_t size;
 
-	if (max_lines < 1 || max_lines > GPIOD_LINE_BULK_MAX_LINES) {
+	if (max_lines == 0) {
 		errno = EINVAL;
 		return NULL;
 	}
@@ -1066,7 +1068,7 @@ int gpiod_line_set_flags(struct gpiod_line *line, int flags)
 int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
 {
 	struct gpiod_line *line;
-	int values[GPIOD_LINE_BULK_MAX_LINES];
+	int values[LINE_REQUEST_MAX_LINES];
 	unsigned int i;
 	int direction;
 
@@ -1129,7 +1131,7 @@ int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
 			       const struct timespec *timeout,
 			       struct gpiod_line_bulk *event_bulk)
 {
-	struct pollfd fds[GPIOD_LINE_BULK_MAX_LINES];
+	struct pollfd fds[LINE_REQUEST_MAX_LINES];
 	unsigned int off, num_lines;
 	struct gpiod_line *line;
 	int rv;
diff --git a/tests/tests-bulk.c b/tests/tests-bulk.c
index e2520fc..22cae84 100644
--- a/tests/tests-bulk.c
+++ b/tests/tests-bulk.c
@@ -20,15 +20,6 @@ GPIOD_TEST_CASE(alloc_zero_lines, 0, { 1 })
 	g_assert_cmpint(errno, ==, EINVAL);
 }
 
-GPIOD_TEST_CASE(alloc_too_many_lines, 0, { 1 })
-{
-	struct gpiod_line_bulk *bulk;
-
-	bulk = gpiod_line_bulk_new(GPIOD_LINE_BULK_MAX_LINES + 1);
-	g_assert_null(bulk);
-	g_assert_cmpint(errno, ==, EINVAL);
-}
-
 GPIOD_TEST_CASE(add_too_many_lines, 0, { 8 })
 {
 	g_autoptr(gpiod_line_bulk_struct) bulk = NULL;
diff --git a/tools/gpiomon.c b/tools/gpiomon.c
index 44fb431..c271913 100644
--- a/tools/gpiomon.c
+++ b/tools/gpiomon.c
@@ -157,7 +157,7 @@ static void handle_signal(int signum UNUSED)
 
 int main(int argc, char **argv)
 {
-	unsigned int offsets[GPIOD_LINE_BULK_MAX_LINES], num_lines = 0, offset,
+	unsigned int offsets[64], num_lines = 0, offset,
 		     events_wanted = 0, events_done = 0, x;
 	bool watch_rising = false, watch_falling = false;
 	int flags = 0;
@@ -241,6 +241,9 @@ int main(int argc, char **argv)
 	if (argc < 2)
 		die("at least one GPIO line offset must be specified");
 
+	if (argc > 65)
+		die("too many offsets given");
+
 	for (i = 1; i < argc; i++) {
 		offset = strtoul(argv[i], &end, 10);
 		if (*end != '\0' || offset > INT_MAX)
-- 
2.29.1


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

* [libgpiod][PATCH 05/14] core: drop line iterators
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (3 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 04/14] bulk: drop the limit on the max number of lines Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 06/14] treewide: kill opening chips by label Bartosz Golaszewski
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Hand-crafted iterators don't make much sense in C and impose an
additional layer of memory allocation and resource releasing. Remove
the line iterators from the core C library.

We're leaving the iterators where they make sense: in C++ and Python
bindings but we convert them to using other means of keeping track of
lines.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/gpiod.hpp        |  1 -
 bindings/cxx/iter.cpp         | 28 +++++---------------
 bindings/python/gpiodmodule.c | 21 +++++----------
 include/gpiod.h               | 36 --------------------------
 lib/helpers.c                 | 32 ++++++++++-------------
 lib/iter.c                    | 48 -----------------------------------
 tests/gpiod-test.h            |  2 --
 tests/tests-iter.c            | 23 -----------------
 tools/gpioinfo.c              | 14 ++++------
 9 files changed, 33 insertions(+), 172 deletions(-)

diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
index 8c8e6c9..0f1d9b2 100644
--- a/bindings/cxx/gpiod.hpp
+++ b/bindings/cxx/gpiod.hpp
@@ -1083,7 +1083,6 @@ public:
 
 private:
 
-	::std::shared_ptr<::gpiod_line_iter> _m_iter;
 	line _m_current;
 };
 
diff --git a/bindings/cxx/iter.cpp b/bindings/cxx/iter.cpp
index 7985910..15c3925 100644
--- a/bindings/cxx/iter.cpp
+++ b/bindings/cxx/iter.cpp
@@ -17,23 +17,6 @@ void chip_iter_deleter(::gpiod_chip_iter* iter)
 	::gpiod_chip_iter_free_noclose(iter);
 }
 
-void line_iter_deleter(::gpiod_line_iter* iter)
-{
-	::gpiod_line_iter_free(iter);
-}
-
-::gpiod_line_iter* make_line_iter(::gpiod_chip* chip)
-{
-	::gpiod_line_iter* iter;
-
-	iter = ::gpiod_line_iter_new(chip);
-	if (!iter)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error creating GPIO line iterator");
-
-	return iter;
-}
-
 } /* namespace */
 
 chip_iter make_chip_iter(void)
@@ -105,17 +88,20 @@ line_iter end(const line_iter&) noexcept
 }
 
 line_iter::line_iter(const chip& owner)
-	: _m_iter(make_line_iter(owner._m_chip.get()), line_iter_deleter),
-	  _m_current(line(::gpiod_line_iter_next(this->_m_iter.get()), owner))
+	: _m_current(owner.get_line(0))
 {
 
 }
 
 line_iter& line_iter::operator++(void)
 {
-	::gpiod_line* next = ::gpiod_line_iter_next(this->_m_iter.get());
+	unsigned int offset = this->_m_current.offset() + 1;
+	chip owner = this->_m_current.get_chip();
 
-	this->_m_current = next ? line(next, this->_m_current._m_owner) : line();
+	if (offset == owner.num_lines())
+		this->_m_current = line(); /* Last element */
+	else
+		this->_m_current = owner.get_line(offset);
 
 	return *this;
 }
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index b9b5770..11d1407 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -41,7 +41,7 @@ typedef struct {
 
 typedef struct {
 	PyObject_HEAD
-	struct gpiod_line_iter *iter;
+	unsigned int offset;
 	gpiod_ChipObject *owner;
 } gpiod_LineIterObject;
 
@@ -2621,14 +2621,7 @@ static int gpiod_LineIter_init(gpiod_LineIterObject *self,
 	if (gpiod_ChipIsClosed(chip_obj))
 		return -1;
 
-	Py_BEGIN_ALLOW_THREADS;
-	self->iter = gpiod_line_iter_new(chip_obj->chip);
-	Py_END_ALLOW_THREADS;
-	if (!self->iter) {
-		PyErr_SetFromErrno(PyExc_OSError);
-		return -1;
-	}
-
+	self->offset = 0;
 	self->owner = chip_obj;
 	Py_INCREF(chip_obj);
 
@@ -2637,9 +2630,6 @@ static int gpiod_LineIter_init(gpiod_LineIterObject *self,
 
 static void gpiod_LineIter_dealloc(gpiod_LineIterObject *self)
 {
-	if (self->iter)
-		gpiod_line_iter_free(self->iter);
-
 	PyObject_Del(self);
 }
 
@@ -2647,10 +2637,13 @@ static gpiod_LineObject *gpiod_LineIter_next(gpiod_LineIterObject *self)
 {
 	struct gpiod_line *line;
 
-	line = gpiod_line_iter_next(self->iter);
-	if (!line)
+	if (self->offset == gpiod_chip_num_lines(self->owner->chip))
 		return NULL; /* Last element. */
 
+	line = gpiod_chip_get_line(self->owner->chip, self->offset++);
+	if (!line)
+		return (gpiod_LineObject *)PyErr_SetFromErrno(PyExc_OSError);
+
 	return gpiod_MakeLineObject(self->owner, line);
 }
 
diff --git a/include/gpiod.h b/include/gpiod.h
index 9ffb446..b5965ed 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -40,7 +40,6 @@ extern "C" {
 struct gpiod_chip;
 struct gpiod_line;
 struct gpiod_chip_iter;
-struct gpiod_line_iter;
 struct gpiod_line_bulk;
 
 /**
@@ -1202,41 +1201,6 @@ gpiod_chip_iter_next_noclose(struct gpiod_chip_iter *iter) GPIOD_API;
 	     (chip);							\
 	     (chip) = gpiod_chip_iter_next_noclose(iter))
 
-/**
- * @brief Create a new line iterator.
- * @param chip Active gpiochip handle over the lines of which we want
- *             to iterate.
- * @return New line iterator or NULL if an error occurred.
- */
-struct gpiod_line_iter *
-gpiod_line_iter_new(struct gpiod_chip *chip) GPIOD_API;
-
-/**
- * @brief Free all resources associated with a GPIO line iterator.
- * @param iter Line iterator object.
- */
-void gpiod_line_iter_free(struct gpiod_line_iter *iter) GPIOD_API;
-
-/**
- * @brief Get the next GPIO line handle.
- * @param iter The GPIO line iterator object.
- * @return Pointer to the next GPIO line handle or NULL if there are no more
- *         lines left.
- */
-struct gpiod_line *
-gpiod_line_iter_next(struct gpiod_line_iter *iter) GPIOD_API;
-
-/**
- * @brief Iterate over all GPIO lines of a single chip.
- * @param iter An initialized GPIO line iterator.
- * @param line Pointer to a GPIO line handle - on each iteration, the
- *             next GPIO line will be assigned to this argument.
- */
-#define gpiod_foreach_line(iter, line)					\
-	for ((line) = gpiod_line_iter_next(iter);			\
-	     (line);							\
-	     (line) = gpiod_line_iter_next(iter))
-
 /**
  * @}
  *
diff --git a/lib/helpers.c b/lib/helpers.c
index a343f71..3b7428b 100644
--- a/lib/helpers.c
+++ b/lib/helpers.c
@@ -124,24 +124,23 @@ gpiod_chip_get_lines(struct gpiod_chip *chip,
 
 struct gpiod_line_bulk *gpiod_chip_get_all_lines(struct gpiod_chip *chip)
 {
-	struct gpiod_line_iter *iter;
 	struct gpiod_line_bulk *bulk;
 	struct gpiod_line *line;
+	unsigned int offset;
 
 	bulk = gpiod_line_bulk_new(gpiod_chip_num_lines(chip));
 	if (!bulk)
 		return NULL;
 
-	iter = gpiod_line_iter_new(chip);
-	if (!iter) {
-		gpiod_line_bulk_free(bulk);
-		return NULL;
-	}
+	for (offset = 0; offset < gpiod_chip_num_lines(chip); offset++) {
+		line = gpiod_chip_get_line(chip, offset);
+		if (!line) {
+			gpiod_line_bulk_free(bulk);
+			return NULL;
+		}
 
-	gpiod_foreach_line(iter, line)
 		gpiod_line_bulk_add_line(bulk, line);
-
-	gpiod_line_iter_free(iter);
+	}
 
 	return bulk;
 }
@@ -149,24 +148,21 @@ struct gpiod_line_bulk *gpiod_chip_get_all_lines(struct gpiod_chip *chip)
 struct gpiod_line *
 gpiod_chip_find_line(struct gpiod_chip *chip, const char *name)
 {
-	struct gpiod_line_iter *iter;
 	struct gpiod_line *line;
+	unsigned int offset;
 	const char *tmp;
 
-	iter = gpiod_line_iter_new(chip);
-	if (!iter)
-		return NULL;
+	for (offset = 0; offset < gpiod_chip_num_lines(chip); offset++) {
+		line = gpiod_chip_get_line(chip, offset);
+		if (!line)
+			return NULL;
 
-	gpiod_foreach_line(iter, line) {
 		tmp = gpiod_line_name(line);
-		if (tmp && strcmp(tmp, name) == 0) {
-			gpiod_line_iter_free(iter);
+		if (tmp && strcmp(tmp, name) == 0)
 			return line;
-		}
 	}
 
 	errno = ENOENT;
-	gpiod_line_iter_free(iter);
 
 	return NULL;
 }
diff --git a/lib/iter.c b/lib/iter.c
index bfd2852..2ff767c 100644
--- a/lib/iter.c
+++ b/lib/iter.c
@@ -17,12 +17,6 @@ struct gpiod_chip_iter {
 	unsigned int offset;
 };
 
-struct gpiod_line_iter {
-	struct gpiod_line **lines;
-	unsigned int num_lines;
-	unsigned int offset;
-};
-
 static int dir_filter(const struct dirent *dir)
 {
 	return !strncmp(dir->d_name, "gpiochip", 8);
@@ -127,45 +121,3 @@ struct gpiod_chip *gpiod_chip_iter_next_noclose(struct gpiod_chip_iter *iter)
 	return iter->offset < (iter->num_chips)
 					? iter->chips[iter->offset++] : NULL;
 }
-
-struct gpiod_line_iter *gpiod_line_iter_new(struct gpiod_chip *chip)
-{
-	struct gpiod_line_iter *iter;
-	unsigned int i;
-
-	iter = malloc(sizeof(*iter));
-	if (!iter)
-		return NULL;
-
-	iter->num_lines = gpiod_chip_num_lines(chip);
-	iter->offset = 0;
-
-	iter->lines = calloc(iter->num_lines, sizeof(*iter->lines));
-	if (!iter->lines) {
-		free(iter);
-		return NULL;
-	}
-
-	for (i = 0; i < iter->num_lines; i++) {
-		iter->lines[i] = gpiod_chip_get_line(chip, i);
-		if (!iter->lines[i]) {
-			free(iter->lines);
-			free(iter);
-			return NULL;
-		}
-	}
-
-	return iter;
-}
-
-void gpiod_line_iter_free(struct gpiod_line_iter *iter)
-{
-	free(iter->lines);
-	free(iter);
-}
-
-struct gpiod_line *gpiod_line_iter_next(struct gpiod_line_iter *iter)
-{
-	return iter->offset < (iter->num_lines)
-					? iter->lines[iter->offset++] : NULL;
-}
diff --git a/tests/gpiod-test.h b/tests/gpiod-test.h
index a43109a..df9f0c7 100644
--- a/tests/gpiod-test.h
+++ b/tests/gpiod-test.h
@@ -26,12 +26,10 @@
 typedef struct gpiod_chip gpiod_chip_struct;
 typedef struct gpiod_line_bulk gpiod_line_bulk_struct;
 typedef struct gpiod_chip_iter gpiod_chip_iter_struct;
-typedef struct gpiod_line_iter gpiod_line_iter_struct;
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_struct, gpiod_chip_close);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_bulk_struct, gpiod_line_bulk_free);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_iter_struct, gpiod_chip_iter_free);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_iter_struct, gpiod_line_iter_free);
 
 /* These are private definitions and should not be used directly. */
 typedef void (*_gpiod_test_func)(void);
diff --git a/tests/tests-iter.c b/tests/tests-iter.c
index 8deee8e..163a820 100644
--- a/tests/tests-iter.c
+++ b/tests/tests-iter.c
@@ -98,26 +98,3 @@ GPIOD_TEST_CASE(chip_iter_break, 0, { 8, 8, 8, 8, 8 })
 
 	g_assert_cmpuint(i, ==, 3);
 }
-
-GPIOD_TEST_CASE(line_iter, 0, { 8 })
-{
-	g_autoptr(gpiod_line_iter_struct) iter = NULL;
-	g_autoptr(gpiod_chip_struct) chip = NULL;
-	struct gpiod_line *line;
-	guint i = 0;
-
-	chip = gpiod_chip_open(gpiod_test_chip_path(0));
-	g_assert_nonnull(chip);
-	gpiod_test_return_if_failed();
-
-	iter = gpiod_line_iter_new(chip);
-	g_assert_nonnull(iter);
-	gpiod_test_return_if_failed();
-
-	gpiod_foreach_line(iter, line) {
-		g_assert_cmpuint(i, ==, gpiod_line_offset(line));
-		i++;
-	}
-
-	g_assert_cmpuint(i, ==, 8);
-}
diff --git a/tools/gpioinfo.c b/tools/gpioinfo.c
index 67be379..dd4a388 100644
--- a/tools/gpioinfo.c
+++ b/tools/gpioinfo.c
@@ -116,22 +116,20 @@ static PRINTF(3, 4) void prinfo(bool *of,
 
 static void list_lines(struct gpiod_chip *chip)
 {
-	struct gpiod_line_iter *iter;
 	int direction, active_state;
 	const char *name, *consumer;
 	struct gpiod_line *line;
 	unsigned int i, offset;
 	bool flag_printed, of;
 
-	iter = gpiod_line_iter_new(chip);
-	if (!iter)
-		die_perror("error creating line iterator");
-
 	printf("%s - %u lines:\n",
 	       gpiod_chip_name(chip), gpiod_chip_num_lines(chip));
 
-	gpiod_foreach_line(iter, line) {
-		offset = gpiod_line_offset(line);
+	for (offset = 0; offset < gpiod_chip_num_lines(chip); offset++) {
+		line = gpiod_chip_get_line(chip, offset);
+		if (!line)
+			die_perror("unable to retrieve the line object from chip");
+
 		name = gpiod_line_name(line);
 		consumer = gpiod_line_consumer(line);
 		direction = gpiod_line_direction(line);
@@ -178,8 +176,6 @@ static void list_lines(struct gpiod_chip *chip)
 
 		printf("\n");
 	}
-
-	gpiod_line_iter_free(iter);
 }
 
 int main(int argc, char **argv)
-- 
2.29.1


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

* [libgpiod][PATCH 06/14] treewide: kill opening chips by label
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (4 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 05/14] core: drop line iterators Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 07/14] API: move gpiod_line_get_chip() to line attributes section Bartosz Golaszewski
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Chip labels are not unique - opening chips by label may lead to errors
or to ignoring chips with duplicate labels. Users can easily implement
chip lookup by label themselves so remove this part from the core library
and all bindings.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/chip.cpp                  |  6 -----
 bindings/cxx/gpiod.hpp                 |  2 --
 bindings/cxx/tests/tests-chip.cpp      | 20 ----------------
 bindings/python/gpiodmodule.c          | 17 ++++---------
 bindings/python/tests/gpiod_py_test.py |  8 -------
 include/gpiod.h                        | 14 ++---------
 lib/helpers.c                          | 33 ++++----------------------
 tests/tests-chip.c                     | 24 -------------------
 8 files changed, 10 insertions(+), 114 deletions(-)

diff --git a/bindings/cxx/chip.cpp b/bindings/cxx/chip.cpp
index 1fc0723..dffa7a2 100644
--- a/bindings/cxx/chip.cpp
+++ b/bindings/cxx/chip.cpp
@@ -30,11 +30,6 @@ namespace {
 	return ::gpiod_chip_open_by_name(device.c_str());
 }
 
-::gpiod_chip* open_by_label(const ::std::string& device)
-{
-	return ::gpiod_chip_open_by_label(device.c_str());
-}
-
 ::gpiod_chip* open_by_number(const ::std::string& device)
 {
 	return ::gpiod_chip_open_by_number(::std::stoul(device));
@@ -46,7 +41,6 @@ const ::std::map<int, open_func> open_funcs = {
 	{ chip::OPEN_LOOKUP,	open_lookup,	},
 	{ chip::OPEN_BY_PATH,	open_by_path,	},
 	{ chip::OPEN_BY_NAME,	open_by_name,	},
-	{ chip::OPEN_BY_LABEL,	open_by_label,	},
 	{ chip::OPEN_BY_NUMBER,	open_by_number,	},
 };
 
diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
index 0f1d9b2..0d443b0 100644
--- a/bindings/cxx/gpiod.hpp
+++ b/bindings/cxx/gpiod.hpp
@@ -190,8 +190,6 @@ public:
 		/**< Assume the string is a path to the GPIO chardev. */
 		OPEN_BY_NAME,
 		/**< Assume the string is the name of the chip */
-		OPEN_BY_LABEL,
-		/**< Assume the string is the label of the GPIO chip. */
 		OPEN_BY_NUMBER,
 		/**< Assume the string is the number of the GPIO chip. */
 	};
diff --git a/bindings/cxx/tests/tests-chip.cpp b/bindings/cxx/tests/tests-chip.cpp
index 1c69872..4c9f113 100644
--- a/bindings/cxx/tests/tests-chip.cpp
+++ b/bindings/cxx/tests/tests-chip.cpp
@@ -28,11 +28,6 @@ TEST_CASE("GPIO chip device can be opened in different modes", "[chip]")
 				::gpiod::chip::OPEN_BY_PATH));
 	}
 
-	SECTION("open by label")
-	{
-		REQUIRE_NOTHROW(::gpiod::chip("gpio-mockup-B", ::gpiod::chip::OPEN_BY_LABEL));
-	}
-
 	SECTION("open by number")
 	{
 		REQUIRE_NOTHROW(::gpiod::chip(::std::to_string(mockup::instance().chip_num(1)),
@@ -54,11 +49,6 @@ TEST_CASE("GPIO chip device can be opened with implicit lookup", "[chip]")
 		REQUIRE_NOTHROW(::gpiod::chip(mockup::instance().chip_path(1)));
 	}
 
-	SECTION("lookup by label")
-	{
-		REQUIRE_NOTHROW(::gpiod::chip("gpio-mockup-B"));
-	}
-
 	SECTION("lookup by number")
 	{
 		REQUIRE_NOTHROW(::gpiod::chip(::std::to_string(mockup::instance().chip_num(1))));
@@ -84,11 +74,6 @@ TEST_CASE("GPIO chip can be opened with the open() method in different modes", "
 					  ::gpiod::chip::OPEN_BY_PATH));
 	}
 
-	SECTION("open by label")
-	{
-		REQUIRE_NOTHROW(chip.open("gpio-mockup-B", ::gpiod::chip::OPEN_BY_LABEL));
-	}
-
 	SECTION("open by number")
 	{
 		REQUIRE_NOTHROW(chip.open(::std::to_string(mockup::instance().chip_num(1)),
@@ -126,11 +111,6 @@ TEST_CASE("GPIO chip can be opened with the open() method with implicit lookup",
 		REQUIRE_NOTHROW(chip.open(mockup::instance().chip_path(1)));
 	}
 
-	SECTION("lookup by label")
-	{
-		REQUIRE_NOTHROW(chip.open("gpio-mockup-B"));
-	}
-
 	SECTION("lookup by number")
 	{
 		REQUIRE_NOTHROW(chip.open(::std::to_string(mockup::instance().chip_num(1))));
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index 11d1407..17a58b1 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -1961,7 +1961,6 @@ enum {
 	gpiod_OPEN_LOOKUP = 1,
 	gpiod_OPEN_BY_NAME,
 	gpiod_OPEN_BY_PATH,
-	gpiod_OPEN_BY_LABEL,
 	gpiod_OPEN_BY_NUMBER,
 };
 
@@ -1987,9 +1986,6 @@ static int gpiod_Chip_init(gpiod_ChipObject *self,
 	case gpiod_OPEN_BY_PATH:
 		self->chip = gpiod_chip_open(descr);
 		break;
-	case gpiod_OPEN_BY_LABEL:
-		self->chip = gpiod_chip_open_by_label(descr);
-		break;
 	case gpiod_OPEN_BY_NUMBER:
 		self->chip = gpiod_chip_open_by_number(atoi(descr));
 		break;
@@ -2503,10 +2499,10 @@ PyDoc_STRVAR(gpiod_ChipType_doc,
 "The Chip object's constructor takes a description string as argument the\n"
 "meaning of which depends on the second, optional parameter which defines\n"
 "the way the description string should be interpreted. The available\n"
-"options are: OPEN_BY_LABEL, OPEN_BY_NAME, OPEN_BY_NUMBER, OPEN_BY_PATH,\n"
-"and OPEN_LOOKUP. The last option means that libgpiod should open the chip\n"
-"based on the best guess what the path is. This is also the default if the\n"
-"second argument is missing.\n"
+"options are: OPEN_BY_NAME, OPEN_BY_NUMBER, OPEN_BY_PATH and OPEN_LOOKUP.\n"
+"The last option means that libgpiod should open the chip based on the best\n"
+"guess what the path is. This is also the default if the second argument is\n"
+"missing.\n"
 "\n"
 "Callers must close the chip by calling the close() method when it's no\n"
 "longer used.\n"
@@ -2786,11 +2782,6 @@ static gpiod_ConstDescr gpiod_ConstList[] = {
 		.name = "OPEN_BY_NAME",
 		.val = gpiod_OPEN_BY_NAME,
 	},
-	{
-		.typeobj = &gpiod_ChipType,
-		.name = "OPEN_BY_LABEL",
-		.val = gpiod_OPEN_BY_LABEL,
-	},
 	{
 		.typeobj = &gpiod_ChipType,
 		.name = "OPEN_BY_NUMBER",
diff --git a/bindings/python/tests/gpiod_py_test.py b/bindings/python/tests/gpiod_py_test.py
index cb15fdc..e4aaadc 100755
--- a/bindings/python/tests/gpiod_py_test.py
+++ b/bindings/python/tests/gpiod_py_test.py
@@ -96,10 +96,6 @@ class ChipOpen(MockupTestCase):
                         gpiod.Chip.OPEN_BY_NUMBER) as chip:
             self.assertEqual(chip.name(), mockup.chip_name(1))
 
-    def test_open_chip_by_label(self):
-        with gpiod.Chip('gpio-mockup-B', gpiod.Chip.OPEN_BY_LABEL) as chip:
-            self.assertEqual(chip.name(), mockup.chip_name(1))
-
     def test_lookup_chip_by_name(self):
         with gpiod.Chip(mockup.chip_name(1)) as chip:
             self.assertEqual(chip.name(), mockup.chip_name(1))
@@ -112,10 +108,6 @@ class ChipOpen(MockupTestCase):
         with gpiod.Chip('{}'.format(mockup.chip_num(1))) as chip:
             self.assertEqual(chip.name(), mockup.chip_name(1))
 
-    def test_lookup_chip_by_label(self):
-        with gpiod.Chip('gpio-mockup-B') as chip:
-            self.assertEqual(chip.name(), mockup.chip_name(1))
-
     def test_nonexistent_chip(self):
         with self.assertRaises(FileNotFoundError):
             chip = gpiod.Chip('nonexistent-chip')
diff --git a/include/gpiod.h b/include/gpiod.h
index b5965ed..b28cc92 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -103,24 +103,14 @@ struct gpiod_chip *gpiod_chip_open_by_name(const char *name) GPIOD_API;
  */
 struct gpiod_chip *gpiod_chip_open_by_number(unsigned int num) GPIOD_API;
 
-/**
- * @brief Open a gpiochip by label.
- * @param label Label of the gpiochip to open.
- * @return GPIO chip handle or NULL if the chip with given label was not found
- *         or an error occured.
- * @note If the chip cannot be found but no other error occurred, errno is set
- *       to ENOENT.
- */
-struct gpiod_chip *gpiod_chip_open_by_label(const char *label) GPIOD_API;
-
 /**
  * @brief Open a gpiochip based on the best guess what the path is.
  * @param descr String describing the gpiochip.
  * @return GPIO chip handle or NULL if an error occurred.
  *
  * This routine tries to figure out whether the user passed it the path to the
- * GPIO chip, its name, label or number as a string. Then it tries to open it
- * using one of the gpiod_chip_open** variants.
+ * GPIO chip, its name or number as a string. Then it tries to open it using
+ * one of the gpiod_chip_open** variants.
  */
 struct gpiod_chip *gpiod_chip_open_lookup(const char *descr) GPIOD_API;
 
diff --git a/lib/helpers.c b/lib/helpers.c
index 3b7428b..3ec6c96 100644
--- a/lib/helpers.c
+++ b/lib/helpers.c
@@ -56,28 +56,6 @@ struct gpiod_chip *gpiod_chip_open_by_number(unsigned int num)
 	return chip;
 }
 
-struct gpiod_chip *gpiod_chip_open_by_label(const char *label)
-{
-	struct gpiod_chip_iter *iter;
-	struct gpiod_chip *chip;
-
-	iter = gpiod_chip_iter_new();
-	if (!iter)
-		return NULL;
-
-	gpiod_foreach_chip(iter, chip) {
-		if (strcmp(label, gpiod_chip_label(chip)) == 0) {
-			gpiod_chip_iter_free_noclose(iter);
-			return chip;
-		}
-	}
-
-	errno = ENOENT;
-	gpiod_chip_iter_free(iter);
-
-	return NULL;
-}
-
 struct gpiod_chip *gpiod_chip_open_lookup(const char *descr)
 {
 	struct gpiod_chip *chip;
@@ -85,13 +63,10 @@ struct gpiod_chip *gpiod_chip_open_lookup(const char *descr)
 	if (isuint(descr)) {
 		chip = gpiod_chip_open_by_number(strtoul(descr, NULL, 10));
 	} else {
-		chip = gpiod_chip_open_by_label(descr);
-		if (!chip) {
-			if (strncmp(descr, "/dev/", 5))
-				chip = gpiod_chip_open_by_name(descr);
-			else
-				chip = gpiod_chip_open(descr);
-		}
+		if (strncmp(descr, "/dev/", 5))
+			chip = gpiod_chip_open_by_name(descr);
+		else
+			chip = gpiod_chip_open(descr);
 	}
 
 	return chip;
diff --git a/tests/tests-chip.c b/tests/tests-chip.c
index 2f19c49..0c2948a 100644
--- a/tests/tests-chip.c
+++ b/tests/tests-chip.c
@@ -68,28 +68,8 @@ GPIOD_TEST_CASE(open_by_number_good, 0, { 8 })
 	g_assert_nonnull(chip);
 }
 
-GPIOD_TEST_CASE(open_by_label_good, 0, { 4, 4, 4, 4, 4 })
-{
-	g_autoptr(gpiod_chip_struct) chip = NULL;
-
-	chip = gpiod_chip_open_by_label("gpio-mockup-D");
-	g_assert_nonnull(chip);
-	gpiod_test_return_if_failed();
-	g_assert_cmpstr(gpiod_chip_name(chip), ==, gpiod_test_chip_name(3));
-}
-
-GPIOD_TEST_CASE(open_by_label_bad, 0, { 4, 4, 4, 4, 4 })
-{
-	struct gpiod_chip *chip;
-
-	chip = gpiod_chip_open_by_label("nonexistent_gpio_chip");
-	g_assert_null(chip);
-	g_assert_cmpint(errno, ==, ENOENT);
-}
-
 GPIOD_TEST_CASE(open_lookup_good, 0, { 8, 8, 8})
 {
-	g_autoptr(gpiod_chip_struct) chip_by_label = NULL;
 	g_autoptr(gpiod_chip_struct) chip_by_name = NULL;
 	g_autoptr(gpiod_chip_struct) chip_by_path = NULL;
 	g_autoptr(gpiod_chip_struct) chip_by_num = NULL;
@@ -99,12 +79,10 @@ GPIOD_TEST_CASE(open_lookup_good, 0, { 8, 8, 8})
 	chip_by_name = gpiod_chip_open_lookup(gpiod_test_chip_name(1));
 	chip_by_path = gpiod_chip_open_lookup(gpiod_test_chip_path(1));
 	chip_by_num = gpiod_chip_open_lookup(chip_num_str);
-	chip_by_label = gpiod_chip_open_lookup("gpio-mockup-B");
 
 	g_assert_nonnull(chip_by_name);
 	g_assert_nonnull(chip_by_path);
 	g_assert_nonnull(chip_by_num);
-	g_assert_nonnull(chip_by_label);
 	gpiod_test_return_if_failed();
 
 	g_assert_cmpstr(gpiod_chip_name(chip_by_name),
@@ -113,8 +91,6 @@ GPIOD_TEST_CASE(open_lookup_good, 0, { 8, 8, 8})
 			==, gpiod_test_chip_name(1));
 	g_assert_cmpstr(gpiod_chip_name(chip_by_num),
 			==, gpiod_test_chip_name(1));
-	g_assert_cmpstr(gpiod_chip_name(chip_by_label),
-			==, gpiod_test_chip_name(1));
 }
 
 GPIOD_TEST_CASE(get_name, 0, { 8, 8, 8})
-- 
2.29.1


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

* [libgpiod][PATCH 07/14] API: move gpiod_line_get_chip() to line attributes section
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (5 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 06/14] treewide: kill opening chips by label Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 08/14] core: kill gpiod_line_close_chip() Bartosz Golaszewski
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

This routine should logically be part of line attributes. Move it out
of the misc line section.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 include/gpiod.h | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/gpiod.h b/include/gpiod.h
index b28cc92..c6e0b65 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -431,6 +431,13 @@ bool gpiod_line_is_open_source(struct gpiod_line *line) GPIOD_API;
  */
 int gpiod_line_update(struct gpiod_line *line) GPIOD_API;
 
+/**
+ * @brief Get the handle to the GPIO chip controlling this line.
+ * @param line The GPIO line object.
+ * @return Pointer to the GPIO chip handle controlling this line.
+ */
+struct gpiod_chip *gpiod_line_get_chip(struct gpiod_line *line) GPIOD_API;
+
 /**
  * @}
  *
@@ -1093,13 +1100,6 @@ struct gpiod_line *gpiod_line_find(const char *name) GPIOD_API;
  */
 void gpiod_line_close_chip(struct gpiod_line *line) GPIOD_API;
 
-/**
- * @brief Get the handle to the GPIO chip controlling this line.
- * @param line The GPIO line object.
- * @return Pointer to the GPIO chip handle controlling this line.
- */
-struct gpiod_chip *gpiod_line_get_chip(struct gpiod_line *line) GPIOD_API;
-
 /**
  * @}
  *
-- 
2.29.1


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

* [libgpiod][PATCH 08/14] core: kill gpiod_line_close_chip()
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (6 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 07/14] API: move gpiod_line_get_chip() to line attributes section Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 09/14] core: kill gpiod_line_get() Bartosz Golaszewski
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

This helper was supposed to be used together with global line lookup
which will soon be removed so drop this one too.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 include/gpiod.h | 8 --------
 lib/helpers.c   | 7 -------
 2 files changed, 15 deletions(-)

diff --git a/include/gpiod.h b/include/gpiod.h
index c6e0b65..2e8323a 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -1092,14 +1092,6 @@ gpiod_line_get(const char *device, unsigned int offset) GPIOD_API;
  */
 struct gpiod_line *gpiod_line_find(const char *name) GPIOD_API;
 
-/**
- * @brief Close a GPIO chip owning this line and release all resources.
- * @param line GPIO line object
- *
- * After this function returns, the line must no longer be used.
- */
-void gpiod_line_close_chip(struct gpiod_line *line) GPIOD_API;
-
 /**
  * @}
  *
diff --git a/lib/helpers.c b/lib/helpers.c
index 3ec6c96..b3050ca 100644
--- a/lib/helpers.c
+++ b/lib/helpers.c
@@ -424,10 +424,3 @@ out:
 
 	return NULL;
 }
-
-void gpiod_line_close_chip(struct gpiod_line *line)
-{
-	struct gpiod_chip *chip = gpiod_line_get_chip(line);
-
-	gpiod_chip_close(chip);
-}
-- 
2.29.1


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

* [libgpiod][PATCH 09/14] core: kill gpiod_line_get()
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (7 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 08/14] core: kill gpiod_line_close_chip() Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 10/14] treewide: kill global line lookup Bartosz Golaszewski
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

We're dropping all interfaces for global line lookup and accessing. Lines
should be always accessed via their owning chip object.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 include/gpiod.h    | 15 ---------------
 lib/helpers.c      | 18 ------------------
 tests/tests-line.c | 21 ---------------------
 3 files changed, 54 deletions(-)

diff --git a/include/gpiod.h b/include/gpiod.h
index 2e8323a..c1113bf 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -1062,21 +1062,6 @@ int gpiod_line_event_read_fd_multiple(int fd, struct gpiod_line_event *events,
  * Functions that didn't fit anywhere else.
  */
 
-/**
- * @brief Get a GPIO line handle by GPIO chip description and offset.
- * @param device String describing the gpiochip.
- * @param offset The offset of the GPIO line.
- * @return GPIO line handle or NULL if an error occurred.
- *
- * This routine provides a shorter alternative to calling
- * ::gpiod_chip_open_lookup and ::gpiod_chip_get_line.
- *
- * If this function succeeds, the caller is responsible for closing the
- * associated GPIO chip.
- */
-struct gpiod_line *
-gpiod_line_get(const char *device, unsigned int offset) GPIOD_API;
-
 /**
  * @brief Find a GPIO line by its name.
  * @param name Name of the GPIO line.
diff --git a/lib/helpers.c b/lib/helpers.c
index b3050ca..2063c3f 100644
--- a/lib/helpers.c
+++ b/lib/helpers.c
@@ -378,24 +378,6 @@ int gpiod_line_request_bulk_both_edges_events_flags(
 					GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES);
 }
 
-struct gpiod_line *gpiod_line_get(const char *device, unsigned int offset)
-{
-	struct gpiod_chip *chip;
-	struct gpiod_line *line;
-
-	chip = gpiod_chip_open_lookup(device);
-	if (!chip)
-		return NULL;
-
-	line = gpiod_chip_get_line(chip, offset);
-	if (!line) {
-		gpiod_chip_close(chip);
-		return NULL;
-	}
-
-	return line;
-}
-
 struct gpiod_line *gpiod_line_find(const char *name)
 {
 	struct gpiod_chip_iter *iter;
diff --git a/tests/tests-line.c b/tests/tests-line.c
index 4bb5f0f..235df0f 100644
--- a/tests/tests-line.c
+++ b/tests/tests-line.c
@@ -716,27 +716,6 @@ GPIOD_TEST_CASE(output_value_caching, 0, { 8 })
 	g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0);
 }
 
-GPIOD_TEST_CASE(get_line_helper, 0, { 16, 16, 32, 16 })
-{
-	g_autoptr(gpiod_chip_struct) chip = NULL;
-	struct gpiod_line *line;
-
-	line = gpiod_line_get(gpiod_test_chip_name(2), 18);
-	g_assert_nonnull(line);
-	gpiod_test_return_if_failed();
-	chip = gpiod_line_get_chip(line);
-	g_assert_cmpint(gpiod_line_offset(line), ==, 18);
-}
-
-GPIOD_TEST_CASE(get_line_helper_invalid_offset, 0, { 16, 16, 32, 16 })
-{
-	struct gpiod_line *line;
-
-	line = gpiod_line_get(gpiod_test_chip_name(3), 18);
-	g_assert_null(line);
-	g_assert_cmpint(errno, ==, EINVAL);
-}
-
 GPIOD_TEST_CASE(find_good, GPIOD_TEST_FLAG_NAMED_LINES, { 16, 16, 32, 16 })
 {
 	g_autoptr(gpiod_chip_struct) chip = NULL;
-- 
2.29.1


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

* [libgpiod][PATCH 10/14] treewide: kill global line lookup
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (8 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 09/14] core: kill gpiod_line_get() Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 11/14] treewide: kill find_lines() Bartosz Golaszewski
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Global line lookup doesn't really work correctly because GPIO line names
are not unique. We'd have to return a list of matching lines. Also: not
all chips may be accessible by user in which case the chip iterator will
fail. We'll soon be removing chip iterators entirely so for now drop the
global line lookup and let users iterate over chips themselves.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/examples/gpiofindcxx.cpp  | 14 ++---
 bindings/cxx/gpiod.hpp                 |  9 ----
 bindings/cxx/line.cpp                  | 15 ------
 bindings/cxx/tests/tests-line.cpp      | 19 -------
 bindings/python/gpiodmodule.c          | 75 --------------------------
 bindings/python/tests/gpiod_py_test.py | 18 -------
 include/gpiod.h                        | 24 ---------
 lib/helpers.c                          | 29 ----------
 tests/tests-line.c                     | 31 -----------
 tools/gpiofind.c                       | 31 ++++++-----
 10 files changed, 26 insertions(+), 239 deletions(-)

diff --git a/bindings/cxx/examples/gpiofindcxx.cpp b/bindings/cxx/examples/gpiofindcxx.cpp
index aeba29d..e9ab64a 100644
--- a/bindings/cxx/examples/gpiofindcxx.cpp
+++ b/bindings/cxx/examples/gpiofindcxx.cpp
@@ -19,11 +19,13 @@ int main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	auto ret = ::gpiod::find_line(argv[1]);
-	if (!ret.first)
-		return EXIT_FAILURE;
-
-	::std::cout << ret.second.name() << " " << ret.first.offset() << ::std::endl;
+	for (auto& chip: ::gpiod::make_chip_iter()) {
+		auto line = chip.find_line(argv[1]);
+		if (line) {
+			::std::cout << line.name() << " " << line.offset() << ::std::endl;
+			return EXIT_SUCCESS;
+		}
+	}
 
-	return EXIT_SUCCESS;
+	return EXIT_FAILURE;
 }
diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
index 0d443b0..b258730 100644
--- a/bindings/cxx/gpiod.hpp
+++ b/bindings/cxx/gpiod.hpp
@@ -548,15 +548,6 @@ private:
 	friend line_iter;
 };
 
-/**
- * @brief Find a GPIO line by name. Search all GPIO chips present on the system.
- * @param name Name of the line.
- * @return Returns a <line, chip> pair where line is the line with given name
- *         and chip is the line's owner. Both objects are empty if the line was
- *         not found.
- */
-GPIOD_API ::std::pair<line, chip> find_line(const ::std::string& name);
-
 /**
  * @brief Describes a single GPIO line event.
  */
diff --git a/bindings/cxx/line.cpp b/bindings/cxx/line.cpp
index 5589875..54382e2 100644
--- a/bindings/cxx/line.cpp
+++ b/bindings/cxx/line.cpp
@@ -343,19 +343,4 @@ line::chip_guard::chip_guard(const line& line)
 	
 }
 
-::std::pair<line, chip> find_line(const ::std::string& name)
-{
-	::std::pair<line, chip> ret;
-
-	for (auto& it: make_chip_iter()) {
-		ret.first = it.find_line(name);
-		if (ret.first) {
-			ret.second = it;
-			break;
-		}
-	}
-
-	return ret;
-}
-
 } /* namespace gpiod */
diff --git a/bindings/cxx/tests/tests-line.cpp b/bindings/cxx/tests/tests-line.cpp
index 9841bea..a5499ac 100644
--- a/bindings/cxx/tests/tests-line.cpp
+++ b/bindings/cxx/tests/tests-line.cpp
@@ -18,25 +18,6 @@ const ::std::string consumer = "line-test";
 
 } /* namespace */
 
-TEST_CASE("Global find_line() function works", "[line]")
-{
-	mockup::probe_guard mockup_chips({ 8, 8, 8, 8, 8 }, mockup::FLAG_NAMED_LINES);
-
-	SECTION("line found")
-	{
-		auto ret = ::gpiod::find_line("gpio-mockup-C-5");
-		REQUIRE(ret.first.offset() == 5);
-		REQUIRE(ret.first.name() == "gpio-mockup-C-5");
-		REQUIRE(ret.second.label() == "gpio-mockup-C");
-	}
-
-	SECTION("line not found")
-	{
-		auto ret = ::gpiod::find_line("nonexistent-line");
-		REQUIRE_FALSE(ret.first);
-	}
-}
-
 TEST_CASE("Line information can be correctly retrieved", "[line]")
 {
 	mockup::probe_guard mockup_chips({ 8 }, mockup::FLAG_NAMED_LINES);
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index 17a58b1..bcaae92 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -2671,80 +2671,6 @@ static PyTypeObject gpiod_LineIterType = {
 	.tp_iternext = (iternextfunc)gpiod_LineIter_next,
 };
 
-PyDoc_STRVAR(gpiod_Module_find_line_doc,
-"find_line(name) -> gpiod.Line object or None\n"
-"\n"
-"Lookup a GPIO line by name. Search all gpiochips. Returns a gpiod.Line\n"
-"or None if a line with given name doesn't exist in the system.\n"
-"\n"
-"NOTE: the gpiod.Chip object owning the returned line must be closed\n"
-"by the caller.\n"
-"\n"
-"  name\n"
-"    Name of the line to find (string).");
-
-static gpiod_LineObject *gpiod_Module_find_line(PyObject *Py_UNUSED(self),
-						PyObject *args)
-{
-	gpiod_LineObject *line_obj;
-	gpiod_ChipObject *chip_obj;
-	struct gpiod_chip *chip;
-	struct gpiod_line *line;
-	const char *name;
-	int rv;
-
-	rv = PyArg_ParseTuple(args, "s", &name);
-	if (!rv)
-		return NULL;
-
-	Py_BEGIN_ALLOW_THREADS;
-	line = gpiod_line_find(name);
-	Py_END_ALLOW_THREADS;
-	if (!line) {
-		if (errno == ENOENT) {
-			Py_INCREF(Py_None);
-			return (gpiod_LineObject *)Py_None;
-		}
-
-		return (gpiod_LineObject *)PyErr_SetFromErrno(PyExc_OSError);
-	}
-
-	chip = gpiod_line_get_chip(line);
-
-	chip_obj = PyObject_New(gpiod_ChipObject, &gpiod_ChipType);
-	if (!chip_obj) {
-		gpiod_chip_close(chip);
-		return NULL;
-	}
-
-	chip_obj->chip = chip;
-
-	line_obj = gpiod_MakeLineObject(chip_obj, line);
-	if (!line_obj)
-		return NULL;
-
-	/*
-	 * PyObject_New() set the reference count for the chip object at 1 and
-	 * the call to gpiod_MakeLineObject() increased it to 2. However when
-	 * we return the object to the line object to the python interpreter,
-	 * there'll be only a single reference holder to the chip - the line
-	 * object itself. Decrease the chip reference here manually.
-	 */
-	Py_DECREF(line_obj->owner);
-
-	return line_obj;
-}
-
-static PyMethodDef gpiod_module_methods[] = {
-	{
-		.ml_name = "find_line",
-		.ml_meth = (PyCFunction)gpiod_Module_find_line,
-		.ml_flags = METH_VARARGS,
-		.ml_doc = gpiod_Module_find_line_doc,
-	},
-	{ }
-};
-
 typedef struct {
 	const char *name;
 	PyTypeObject *typeobj;
@@ -2850,7 +2776,6 @@ static PyModuleDef gpiod_Module = {
 	.m_name = "gpiod",
 	.m_doc = gpiod_Module_doc,
 	.m_size = -1,
-	.m_methods = gpiod_module_methods,
 };
 
 typedef struct {
diff --git a/bindings/python/tests/gpiod_py_test.py b/bindings/python/tests/gpiod_py_test.py
index e4aaadc..8534ce9 100755
--- a/bindings/python/tests/gpiod_py_test.py
+++ b/bindings/python/tests/gpiod_py_test.py
@@ -234,24 +234,6 @@ class ChipGetLines(MockupTestCase):
 # Line test cases
 #
 
-class LineGlobalFindLine(MockupTestCase):
-
-    chip_sizes = ( 4, 8, 16 )
-    flags = gpiomockup.Mockup.FLAG_NAMED_LINES
-
-    def test_global_find_line_function(self):
-        line = gpiod.find_line('gpio-mockup-B-4')
-        self.assertNotEqual(line, None)
-        try:
-            self.assertEqual(line.owner().label(), 'gpio-mockup-B')
-            self.assertEqual(line.offset(), 4)
-        finally:
-            line.owner().close()
-
-    def test_global_find_line_function_nonexistent(self):
-        line = gpiod.find_line('nonexistent-line')
-        self.assertEqual(line, None)
-
 class LineInfo(MockupTestCase):
 
     chip_sizes = ( 8, )
diff --git a/include/gpiod.h b/include/gpiod.h
index c1113bf..5aeb7cc 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -1053,30 +1053,6 @@ int gpiod_line_event_read_fd(int fd, struct gpiod_line_event *event) GPIOD_API;
 int gpiod_line_event_read_fd_multiple(int fd, struct gpiod_line_event *events,
 				      unsigned int num_events) GPIOD_API;
 
-/**
- * @}
- *
- * @defgroup line_misc Misc line functions
- * @{
- *
- * Functions that didn't fit anywhere else.
- */
-
-/**
- * @brief Find a GPIO line by its name.
- * @param name Name of the GPIO line.
- * @return Returns the GPIO line handle if the line exists in the system or
- *         NULL if it couldn't be located or an error occurred.
- * @attention GPIO lines are not unique in the linux kernel, neither globally
- *            nor within a single chip. This function finds the first line with
- *            given name.
- *
- * If this routine succeeds, the user must manually close the GPIO chip owning
- * this line to avoid memory leaks. If the line could not be found, this
- * functions sets errno to ENOENT.
- */
-struct gpiod_line *gpiod_line_find(const char *name) GPIOD_API;
-
 /**
  * @}
  *
diff --git a/lib/helpers.c b/lib/helpers.c
index 2063c3f..5a73736 100644
--- a/lib/helpers.c
+++ b/lib/helpers.c
@@ -377,32 +377,3 @@ int gpiod_line_request_bulk_both_edges_events_flags(
 	return line_event_request_type_bulk(bulk, consumer, flags,
 					GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES);
 }
-
-struct gpiod_line *gpiod_line_find(const char *name)
-{
-	struct gpiod_chip_iter *iter;
-	struct gpiod_chip *chip;
-	struct gpiod_line *line;
-
-	iter = gpiod_chip_iter_new();
-	if (!iter)
-		return NULL;
-
-	gpiod_foreach_chip(iter, chip) {
-		line = gpiod_chip_find_line(chip, name);
-		if (line) {
-			gpiod_chip_iter_free_noclose(iter);
-			return line;
-		}
-
-		if (errno != ENOENT)
-			goto out;
-	}
-
-	errno = ENOENT;
-
-out:
-	gpiod_chip_iter_free(iter);
-
-	return NULL;
-}
diff --git a/tests/tests-line.c b/tests/tests-line.c
index 235df0f..aee85fe 100644
--- a/tests/tests-line.c
+++ b/tests/tests-line.c
@@ -716,37 +716,6 @@ GPIOD_TEST_CASE(output_value_caching, 0, { 8 })
 	g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0);
 }
 
-GPIOD_TEST_CASE(find_good, GPIOD_TEST_FLAG_NAMED_LINES, { 16, 16, 32, 16 })
-{
-	g_autoptr(gpiod_chip_struct) chip = NULL;
-	struct gpiod_line *line;
-
-	line = gpiod_line_find("gpio-mockup-C-12");
-	g_assert_nonnull(line);
-	gpiod_test_return_if_failed();
-	chip = gpiod_line_get_chip(line);
-	g_assert_cmpint(gpiod_line_offset(line), ==, 12);
-}
-
-GPIOD_TEST_CASE(find_not_found,
-		GPIOD_TEST_FLAG_NAMED_LINES, { 16, 16, 32, 16 })
-{
-	struct gpiod_line *line;
-
-	line = gpiod_line_find("nonexistent");
-	g_assert_null(line);
-	g_assert_cmpint(errno, ==, ENOENT);
-}
-
-GPIOD_TEST_CASE(find_unnamed_lines, 0, { 16, 16, 32, 16 })
-{
-	struct gpiod_line *line;
-
-	line = gpiod_line_find("gpio-mockup-C-12");
-	g_assert_null(line);
-	g_assert_cmpint(errno, ==, ENOENT);
-}
-
 GPIOD_TEST_CASE(direction, 0, { 8 })
 {
 	g_autoptr(gpiod_chip_struct) chip = NULL;
diff --git a/tools/gpiofind.c b/tools/gpiofind.c
index 2138ebf..489cf33 100644
--- a/tools/gpiofind.c
+++ b/tools/gpiofind.c
@@ -34,9 +34,10 @@ static void print_help(void)
 
 int main(int argc, char **argv)
 {
-	int optc, opti, ret = EXIT_SUCCESS;
+	struct gpiod_chip_iter *iter;
 	struct gpiod_chip *chip;
 	struct gpiod_line *line;
+	int optc, opti;
 
 	for (;;) {
 		optc = getopt_long(argc, argv, shortopts, longopts, &opti);
@@ -63,19 +64,23 @@ int main(int argc, char **argv)
 	if (argc != 1)
 		die("exactly one GPIO line name must be specified");
 
-	line = gpiod_line_find(argv[0]);
-	if (!line) {
-		if (errno == ENOENT)
-			return EXIT_FAILURE;
+	iter = gpiod_chip_iter_new();
+	if (!iter)
+		die_perror("unable to access GPIO chips");
 
-		die_perror("error performing the line lookup");
-	}
-
-	chip = gpiod_line_get_chip(line);
-
-	printf("%s %u\n", gpiod_chip_name(chip), gpiod_line_offset(line));
+	gpiod_foreach_chip(iter, chip) {
+		line = gpiod_chip_find_line(chip, argv[0]);
+		if (line) {
+			printf("%s %u\n",
+			       gpiod_chip_name(chip), gpiod_line_offset(line));
+			gpiod_chip_iter_free(iter);
+			return EXIT_SUCCESS;
+		}
 
-	gpiod_chip_close(chip);
+		if (errno != ENOENT)
+			die_perror("error performing the line lookup");
+	}
 
-	return ret;
+	gpiod_chip_iter_free(iter);
+	return EXIT_FAILURE;
 }
-- 
2.29.1


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

* [libgpiod][PATCH 11/14] treewide: kill find_lines()
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (9 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 10/14] treewide: kill global line lookup Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 12/14] core: rework gpiod_chip_find_line() Bartosz Golaszewski
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

GPIO line names are not unique. Looking up multiple lines by names would
require us to return a list of matching lines for every name. We're
simplifying the library API so drop this interface treewide.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/chip.cpp                  | 18 ------
 bindings/cxx/gpiod.hpp                 |  7 ---
 bindings/cxx/tests/tests-chip.cpp      | 18 ------
 bindings/python/gpiodmodule.c          | 86 --------------------------
 bindings/python/tests/gpiod_py_test.py | 32 ----------
 include/gpiod.h                        | 15 -----
 lib/helpers.c                          | 28 ---------
 tests/tests-chip.c                     | 49 ---------------
 8 files changed, 253 deletions(-)

diff --git a/bindings/cxx/chip.cpp b/bindings/cxx/chip.cpp
index dffa7a2..ff35e53 100644
--- a/bindings/cxx/chip.cpp
+++ b/bindings/cxx/chip.cpp
@@ -154,24 +154,6 @@ line_bulk chip::get_all_lines(void) const
 	return lines;
 }
 
-line_bulk chip::find_lines(const ::std::vector<::std::string>& names) const
-{
-	line_bulk lines;
-	line line;
-
-	for (auto& it: names) {
-		line = this->find_line(it);
-		if (!line) {
-			lines.clear();
-			return lines;
-		}
-
-		lines.append(line);
-	}
-
-	return lines;
-}
-
 bool chip::operator==(const chip& rhs) const noexcept
 {
 	return this->_m_chip.get() == rhs._m_chip.get();
diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
index b258730..a16a27c 100644
--- a/bindings/cxx/gpiod.hpp
+++ b/bindings/cxx/gpiod.hpp
@@ -146,13 +146,6 @@ public:
 	 */
 	GPIOD_API line_bulk get_all_lines(void) const;
 
-	/**
-	 * @brief Get a set of lines exposed by this chip by their names.
-	 * @param names Vector of line names.
-	 * @return Set of lines held by a line_bulk object.
-	 */
-	GPIOD_API line_bulk find_lines(const ::std::vector<::std::string>& names) const;
-
 	/**
 	 * @brief Equality operator.
 	 * @param rhs Right-hand side of the equation.
diff --git a/bindings/cxx/tests/tests-chip.cpp b/bindings/cxx/tests/tests-chip.cpp
index 4c9f113..90ebc1b 100644
--- a/bindings/cxx/tests/tests-chip.cpp
+++ b/bindings/cxx/tests/tests-chip.cpp
@@ -191,17 +191,6 @@ TEST_CASE("Lines can be retrieved from chip objects", "[chip]")
 		REQUIRE(lines.get(2).name() == "gpio-mockup-B-3");
 		REQUIRE(lines.get(3).name() == "gpio-mockup-B-2");
 	}
-
-	SECTION("find multiple lines by names")
-	{
-		auto lines = chip.find_lines({ "gpio-mockup-B-2",
-					       "gpio-mockup-B-5",
-					       "gpio-mockup-B-6"});
-		REQUIRE(lines.size() == 3);
-		REQUIRE(lines.get(0).offset() == 2);
-		REQUIRE(lines.get(1).offset() == 5);
-		REQUIRE(lines.get(2).offset() == 6);
-	}
 }
 
 TEST_CASE("All lines can be retrieved from a chip at once", "[chip]")
@@ -236,11 +225,4 @@ TEST_CASE("Errors occurring when retrieving lines are correctly reported", "[chi
 	{
 		REQUIRE_FALSE(chip.find_line("nonexistent-line"));
 	}
-
-	SECTION("line not found by name (multiple lines)")
-	{
-		REQUIRE_FALSE(chip.find_lines({ "gpio-mockup-B-2",
-						"nonexistent-line",
-						"gpio-mockup-B-6"}));
-	}
 }
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index bcaae92..4948d5d 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -2339,86 +2339,6 @@ gpiod_Chip_get_all_lines(gpiod_ChipObject *self, PyObject *Py_UNUSED(ignored))
 	return bulk_obj;
 }
 
-PyDoc_STRVAR(gpiod_Chip_find_lines_doc,
-"find_lines(names) -> gpiod.LineBulk object\n"
-"\n"
-"Look up a set of lines by their names.\n"
-"\n"
-"  names\n"
-"    Sequence of line names.\n"
-"\n"
-"Unlike find_line(), this method raises an exception if at least one line\n"
-"from the list doesn't exist.");
-
-static gpiod_LineBulkObject *
-gpiod_Chip_find_lines(gpiod_ChipObject *self, PyObject *args)
-{
-	PyObject *names, *lines, *iter, *next, *arg;
-	gpiod_LineBulkObject *bulk;
-	Py_ssize_t num_names, i;
-	gpiod_LineObject *line;
-	int rv;
-
-	rv = PyArg_ParseTuple(args, "O", &names);
-	if (!rv)
-		return NULL;
-
-	num_names = PyObject_Size(names);
-	if (num_names < 1) {
-		PyErr_SetString(PyExc_TypeError,
-				"Argument must be a non-empty sequence of names");
-		return NULL;
-	}
-
-	lines = PyList_New(num_names);
-	if (!lines)
-		return NULL;
-
-	iter = PyObject_GetIter(names);
-	if (!iter) {
-		Py_DECREF(lines);
-		return NULL;
-	}
-
-	for (i = 0;;) {
-		next = PyIter_Next(iter);
-		if (!next) {
-			Py_DECREF(iter);
-			break;
-		}
-
-		arg = PyTuple_Pack(1, next);
-		if (!arg) {
-			Py_DECREF(iter);
-			Py_DECREF(lines);
-			return NULL;
-		}
-
-		line = gpiod_Chip_find_line(self, arg);
-		Py_DECREF(arg);
-		if (!line || (PyObject *)line == Py_None) {
-			Py_DECREF(iter);
-			Py_DECREF(lines);
-			if ((PyObject *)line == Py_None)
-				PyErr_SetString(PyExc_TypeError,
-						"Unable to find all lines from the list");
-			return NULL;
-		}
-
-		rv = PyList_SetItem(lines, i++, (PyObject *)line);
-		if (rv < 0) {
-			Py_DECREF(line);
-			Py_DECREF(iter);
-			Py_DECREF(lines);
-			return NULL;
-		}
-	}
-
-	bulk = gpiod_ListToLineBulk(lines);
-	Py_DECREF(lines);
-	return bulk;
-}
-
 static PyMethodDef gpiod_Chip_methods[] = {
 	{
 		.ml_name = "close",
@@ -2480,12 +2400,6 @@ static PyMethodDef gpiod_Chip_methods[] = {
 		.ml_flags = METH_NOARGS,
 		.ml_doc = gpiod_Chip_get_all_lines_doc,
 	},
-	{
-		.ml_name = "find_lines",
-		.ml_meth = (PyCFunction)gpiod_Chip_find_lines,
-		.ml_flags = METH_VARARGS,
-		.ml_doc = gpiod_Chip_find_lines_doc,
-	},
 	{ }
 };
 
diff --git a/bindings/python/tests/gpiod_py_test.py b/bindings/python/tests/gpiod_py_test.py
index 8534ce9..6ee72a9 100755
--- a/bindings/python/tests/gpiod_py_test.py
+++ b/bindings/python/tests/gpiod_py_test.py
@@ -182,30 +182,6 @@ class ChipGetLines(MockupTestCase):
             self.assertEqual(lines[2].name(), 'gpio-mockup-B-6')
             self.assertEqual(lines[3].name(), 'gpio-mockup-B-7')
 
-    def test_find_multiple_lines_by_names_in_tuple(self):
-        with gpiod.Chip(mockup.chip_name(1)) as chip:
-            lines = chip.find_lines(( 'gpio-mockup-B-0',
-                                      'gpio-mockup-B-3',
-                                      'gpio-mockup-B-4',
-                                      'gpio-mockup-B-6' )).to_list()
-            self.assertEqual(len(lines), 4)
-            self.assertEqual(lines[0].offset(), 0)
-            self.assertEqual(lines[1].offset(), 3)
-            self.assertEqual(lines[2].offset(), 4)
-            self.assertEqual(lines[3].offset(), 6)
-
-    def test_find_multiple_lines_by_names_in_list(self):
-        with gpiod.Chip(mockup.chip_name(1)) as chip:
-            lines = chip.find_lines([ 'gpio-mockup-B-0',
-                                      'gpio-mockup-B-3',
-                                      'gpio-mockup-B-4',
-                                      'gpio-mockup-B-6' ]).to_list()
-            self.assertEqual(len(lines), 4)
-            self.assertEqual(lines[0].offset(), 0)
-            self.assertEqual(lines[1].offset(), 3)
-            self.assertEqual(lines[2].offset(), 4)
-            self.assertEqual(lines[3].offset(), 6)
-
     def test_get_multiple_lines_invalid_offset(self):
         with gpiod.Chip(mockup.chip_name(1)) as chip:
             with self.assertRaises(OSError) as err_ctx:
@@ -213,14 +189,6 @@ class ChipGetLines(MockupTestCase):
 
             self.assertEqual(err_ctx.exception.errno, errno.EINVAL)
 
-    def test_find_multiple_lines_nonexistent(self):
-        with gpiod.Chip(mockup.chip_name(1)) as chip:
-            with self.assertRaises(TypeError):
-                lines = chip.find_lines(( 'gpio-mockup-B-0',
-                                          'nonexistent-line',
-                                          'gpio-mockup-B-4',
-                                          'gpio-mockup-B-6' )).to_list()
-
     def test_get_all_lines(self):
         with gpiod.Chip(mockup.chip_name(2)) as chip:
             lines = chip.get_all_lines().to_list()
diff --git a/include/gpiod.h b/include/gpiod.h
index 5aeb7cc..34313ed 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -184,21 +184,6 @@ gpiod_chip_get_all_lines(struct gpiod_chip *chip) GPIOD_API;
 struct gpiod_line *
 gpiod_chip_find_line(struct gpiod_chip *chip, const char *name) GPIOD_API;
 
-/**
- * @brief Find a set of GPIO lines by names among lines exposed by this chip.
- * @param chip The GPIO chip object.
- * @param names Array of pointers to C-strings containing the names of the
- *              lines to lookup. Must end with a NULL-pointer.
- * @return New line bulk object or NULL on error.
- * @note If at least one line from the list could not be found among the lines
- *       exposed by this chip, the function sets errno to ENOENT.
- * @attention GPIO line names are not unique in the linux kernel, neither
- *            globally nor within a single chip. This function finds the first
- *            line with given name.
- */
-struct gpiod_line_bulk *
-gpiod_chip_find_lines(struct gpiod_chip *chip, const char **names) GPIOD_API;
-
 /**
  * @}
  *
diff --git a/lib/helpers.c b/lib/helpers.c
index 5a73736..509a1c8 100644
--- a/lib/helpers.c
+++ b/lib/helpers.c
@@ -142,34 +142,6 @@ gpiod_chip_find_line(struct gpiod_chip *chip, const char *name)
 	return NULL;
 }
 
-struct gpiod_line_bulk *
-gpiod_chip_find_lines(struct gpiod_chip *chip, const char **names)
-{
-	struct gpiod_line_bulk *bulk;
-	struct gpiod_line *line;
-	unsigned int num_names;
-	int i;
-
-	for (i = 0; names[i]; i++);
-	num_names = i;
-
-	bulk = gpiod_line_bulk_new(num_names);
-	if (!bulk)
-		return NULL;
-
-	for (i = 0; names[i]; i++) {
-		line = gpiod_chip_find_line(chip, names[i]);
-		if (!line) {
-			gpiod_line_bulk_free(bulk);
-			return NULL;
-		}
-
-		gpiod_line_bulk_add_line(bulk, line);
-	}
-
-	return bulk;
-}
-
 int gpiod_line_request_input(struct gpiod_line *line, const char *consumer)
 {
 	struct gpiod_line_request_config config = {
diff --git a/tests/tests-chip.c b/tests/tests-chip.c
index 0c2948a..543c103 100644
--- a/tests/tests-chip.c
+++ b/tests/tests-chip.c
@@ -264,52 +264,3 @@ GPIOD_TEST_CASE(find_line_not_found, GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
 	g_assert_null(line);
 	g_assert_cmpint(errno, ==, ENOENT);
 }
-
-GPIOD_TEST_CASE(find_lines_good, GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
-{
-	static const gchar *names[] = { "gpio-mockup-B-3",
-					"gpio-mockup-B-6",
-					"gpio-mockup-B-7",
-					NULL };
-
-	g_autoptr(gpiod_line_bulk_struct) bulk = NULL;
-	g_autoptr(gpiod_chip_struct) chip = NULL;
-	struct gpiod_line *line0, *line1, *line2;
-
-	chip = gpiod_chip_open(gpiod_test_chip_path(1));
-	g_assert_nonnull(chip);
-	gpiod_test_return_if_failed();
-
-	bulk = gpiod_chip_find_lines(chip, names);
-	g_assert_nonnull(bulk);
-	gpiod_test_return_if_failed();
-	g_assert_cmpuint(gpiod_line_bulk_num_lines(bulk), ==, 3);
-	gpiod_test_return_if_failed();
-
-	line0 = gpiod_line_bulk_get_line(bulk, 0);
-	line1 = gpiod_line_bulk_get_line(bulk, 1);
-	line2 = gpiod_line_bulk_get_line(bulk, 2);
-
-	g_assert_cmpuint(gpiod_line_offset(line0), ==, 3);
-	g_assert_cmpuint(gpiod_line_offset(line1), ==, 6);
-	g_assert_cmpuint(gpiod_line_offset(line2), ==, 7);
-}
-
-GPIOD_TEST_CASE(fine_lines_not_found, GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
-{
-	static const gchar *names[] = { "gpio-mockup-B-3",
-					"nonexistent",
-					"gpio-mockup-B-7",
-					NULL };
-
-	g_autoptr(gpiod_chip_struct) chip = NULL;
-	struct gpiod_line_bulk *bulk;
-
-	chip = gpiod_chip_open(gpiod_test_chip_path(1));
-	g_assert_nonnull(chip);
-	gpiod_test_return_if_failed();
-
-	bulk = gpiod_chip_find_lines(chip, names);
-	g_assert_null(bulk);
-	g_assert_cmpint(errno, ==, ENOENT);
-}
-- 
2.29.1


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

* [libgpiod][PATCH 12/14] core: rework gpiod_chip_find_line()
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (10 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 11/14] treewide: kill find_lines() Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 13/14] build: add a configure switch for building examples Bartosz Golaszewski
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

GPIO line names are not unique and the library has been incorrectly
making such assumption in v1.x series. We've already dropped interfaces
that would be too complicated to maintain when taking this into account.

Let's now rework the remaming API. This introduces a new function to the
C API: gpiod_chip_find_line_unique() which assumes that the line name is
unique and signals an error if it's not. The previous
gpiod_chip_find_line() function now returns a bulk object containing all
matching lines.

Python and C++ bindings are updated: their find_line() functions return
bulk objects (or an ::std::vector> too now and they take an additional
argument specifying whether we're looking for a unique line or not.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/chip.cpp                  |  18 ++-
 bindings/cxx/examples/gpiofindcxx.cpp  |   6 +-
 bindings/cxx/gpiod.hpp                 |  10 +-
 bindings/cxx/tests/tests-chip.cpp      |   4 +-
 bindings/python/gpiodmodule.c          | 150 ++++++++++++++-----------
 bindings/python/tests/gpiod_py_test.py |   9 +-
 include/gpiod.h                        |  28 +++--
 lib/helpers.c                          |  57 +++++++++-
 tests/tests-chip.c                     |   9 +-
 tools/gpiofind.c                       |   2 +-
 10 files changed, 193 insertions(+), 100 deletions(-)

diff --git a/bindings/cxx/chip.cpp b/bindings/cxx/chip.cpp
index ff35e53..82ba559 100644
--- a/bindings/cxx/chip.cpp
+++ b/bindings/cxx/chip.cpp
@@ -122,16 +122,22 @@ line chip::get_line(unsigned int offset) const
 	return line(line_handle, *this);
 }
 
-line chip::find_line(const ::std::string& name) const
+::std::vector<line> chip::find_line(const ::std::string& name, bool unique) const
 {
 	this->throw_if_noref();
 
-	::gpiod_line* handle = ::gpiod_chip_find_line(this->_m_chip.get(), name.c_str());
-	if (!handle && errno != ENOENT)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error looking up GPIO line by name");
+	::std::vector<line> lines;
+
+	for (auto& line: ::gpiod::line_iter(*this)) {
+		if (line.name() == name)
+			lines.push_back(line);
+	}
 
-	return handle ? line(handle, *this) : line();
+	if (unique && lines.size() > 1)
+		throw ::std::system_error(ERANGE, ::std::system_category(),
+					  "multiple lines with the same name found");
+
+	return lines;
 }
 
 line_bulk chip::get_lines(const ::std::vector<unsigned int>& offsets) const
diff --git a/bindings/cxx/examples/gpiofindcxx.cpp b/bindings/cxx/examples/gpiofindcxx.cpp
index e9ab64a..c817378 100644
--- a/bindings/cxx/examples/gpiofindcxx.cpp
+++ b/bindings/cxx/examples/gpiofindcxx.cpp
@@ -20,9 +20,9 @@ int main(int argc, char **argv)
 	}
 
 	for (auto& chip: ::gpiod::make_chip_iter()) {
-		auto line = chip.find_line(argv[1]);
-		if (line) {
-			::std::cout << line.name() << " " << line.offset() << ::std::endl;
+		auto lines = chip.find_line(argv[1], true);
+		if (!lines.empty()) {
+			::std::cout << lines.front().name() << " " << lines.front().offset() << ::std::endl;
 			return EXIT_SUCCESS;
 		}
 	}
diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
index a16a27c..9d081fe 100644
--- a/bindings/cxx/gpiod.hpp
+++ b/bindings/cxx/gpiod.hpp
@@ -127,11 +127,15 @@ public:
 	GPIOD_API line get_line(unsigned int offset) const;
 
 	/**
-	 * @brief Get the line exposed by this chip by name.
+	 * @brief Find all GPIO lines by name among lines exposed by this GPIO
+	 *        chip.
 	 * @param name Line name.
-	 * @return Line object.
+	 * @param unique If set to true: throw an error if multiple lines match
+	 *               the name.
+	 * @return Vector of all matching lines.
 	 */
-	GPIOD_API line find_line(const ::std::string& name) const;
+	GPIOD_API ::std::vector<line> find_line(const ::std::string& name,
+						bool unique = false) const;
 
 	/**
 	 * @brief Get a set of lines exposed by this chip at given offsets.
diff --git a/bindings/cxx/tests/tests-chip.cpp b/bindings/cxx/tests/tests-chip.cpp
index 90ebc1b..c45f2df 100644
--- a/bindings/cxx/tests/tests-chip.cpp
+++ b/bindings/cxx/tests/tests-chip.cpp
@@ -168,7 +168,7 @@ TEST_CASE("Lines can be retrieved from chip objects", "[chip]")
 
 	SECTION("find single line by name")
 	{
-		auto line = chip.find_line("gpio-mockup-B-3");
+		auto line = chip.find_line("gpio-mockup-B-3", true).front();
 		REQUIRE(line.offset() == 3);
 	}
 
@@ -223,6 +223,6 @@ TEST_CASE("Errors occurring when retrieving lines are correctly reported", "[chi
 
 	SECTION("line not found by name")
 	{
-		REQUIRE_FALSE(chip.find_line("nonexistent-line"));
+		REQUIRE(chip.find_line("nonexistent-line").empty());
 	}
 }
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index 4948d5d..d183e6f 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -2148,61 +2148,115 @@ gpiod_Chip_get_line(gpiod_ChipObject *self, PyObject *args)
 	return gpiod_MakeLineObject(self, line);
 }
 
+static gpiod_LineBulkObject *gpiod_ListToLineBulk(PyObject *lines)
+{
+	gpiod_LineBulkObject *bulk;
+	PyObject *arg;
+
+	arg = PyTuple_Pack(1, lines);
+	if (!arg)
+		return NULL;
+
+	bulk = (gpiod_LineBulkObject *)PyObject_CallObject(
+					(PyObject *)&gpiod_LineBulkType,
+					arg);
+	Py_DECREF(arg);
+
+	return bulk;
+}
+
+static gpiod_LineBulkObject *
+gpiod_LineBulkObjectFromBulk(gpiod_ChipObject *chip, struct gpiod_line_bulk *bulk)
+{
+	gpiod_LineBulkObject *bulk_obj;
+	gpiod_LineObject *line_obj;
+	struct gpiod_line *line;
+	unsigned int idx;
+	PyObject *list;
+	int rv;
+
+	list = PyList_New(gpiod_line_bulk_num_lines(bulk));
+	if (!list)
+		return NULL;
+
+	for (idx = 0; idx < gpiod_line_bulk_num_lines(bulk); idx++) {
+		line = gpiod_line_bulk_get_line(bulk, idx);
+		line_obj = gpiod_MakeLineObject(chip, line);
+		if (!line_obj) {
+			Py_DECREF(list);
+			return NULL;
+		}
+
+		rv = PyList_SetItem(list, idx, (PyObject *)line_obj);
+		if (rv < 0) {
+			Py_DECREF(line_obj);
+			Py_DECREF(list);
+			return NULL;
+		}
+	}
+
+	bulk_obj = gpiod_ListToLineBulk(list);
+	Py_DECREF(list);
+	if (!bulk_obj)
+		return NULL;
+
+	return bulk_obj;
+}
+
 PyDoc_STRVAR(gpiod_Chip_find_line_doc,
-"find_line(name) -> gpiod.Line object or None\n"
+"find_line(name) -> gpiod.LineBulk object or None\n"
 "\n"
-"Get the GPIO line by name.\n"
+"Find all GPIO lines by name among lines exposed by this GPIO chip..\n"
 "\n"
 "  name\n"
 "    Line name (string)\n"
+"  unique\n"
+"    Indicates whether an exception should be raised if more than one lines\n"
+"    matches the name\n"
 "\n"
-"Returns a gpiod.Line object or None if line with given name is not\n"
-"associated with this chip.");
+"Returns a gpiod.LineBulk object containing all matching lines or None if\n"
+"line with given name is not associated with this chip.");
 
-static gpiod_LineObject *
-gpiod_Chip_find_line(gpiod_ChipObject *self, PyObject *args)
+static gpiod_LineBulkObject *
+gpiod_Chip_find_line(gpiod_ChipObject *self, PyObject *args, PyObject *kwds)
 {
-	struct gpiod_line *line;
+	static char *kwlist[] = { "unique", NULL };
+
+	gpiod_LineBulkObject *bulk_obj;
+	struct gpiod_line_bulk *bulk;
+	int rv, unique = 0;
 	const char *name;
-	int rv;
 
 	if (gpiod_ChipIsClosed(self))
 		return NULL;
 
-	rv = PyArg_ParseTuple(args, "s", &name);
+	rv = PyArg_ParseTupleAndKeywords(args, kwds, "s|p",
+					 kwlist, &name, &unique);
 	if (!rv)
 		return NULL;
 
 	Py_BEGIN_ALLOW_THREADS;
-	line = gpiod_chip_find_line(self->chip, name);
+	bulk = gpiod_chip_find_line(self->chip, name);
 	Py_END_ALLOW_THREADS;
-	if (!line) {
+	if (!bulk) {
 		if (errno == ENOENT) {
 			Py_INCREF(Py_None);
-			return (gpiod_LineObject *)Py_None;
+			return (gpiod_LineBulkObject *)Py_None;
 		}
 
-		return (gpiod_LineObject *)PyErr_SetFromErrno(PyExc_OSError);
+		return (gpiod_LineBulkObject *)PyErr_SetFromErrno(
+							PyExc_OSError);
 	}
 
-	return gpiod_MakeLineObject(self, line);
-}
-
-static gpiod_LineBulkObject *gpiod_ListToLineBulk(PyObject *lines)
-{
-	gpiod_LineBulkObject *bulk;
-	PyObject *arg;
-
-	arg = PyTuple_Pack(1, lines);
-	if (!arg)
+	if (unique && gpiod_line_bulk_num_lines(bulk) > 1) {
+		gpiod_line_bulk_free(bulk);
+		PyErr_SetString(PyExc_RuntimeError, "line not unique");
 		return NULL;
+	}
 
-	bulk = (gpiod_LineBulkObject *)PyObject_CallObject(
-					(PyObject *)&gpiod_LineBulkType,
-					arg);
-	Py_DECREF(arg);
-
-	return bulk;
+	bulk_obj = gpiod_LineBulkObjectFromBulk(self, bulk);
+	gpiod_line_bulk_free(bulk);
+	return bulk_obj;
 }
 
 PyDoc_STRVAR(gpiod_Chip_get_lines_doc,
@@ -2293,10 +2347,6 @@ gpiod_Chip_get_all_lines(gpiod_ChipObject *self, PyObject *Py_UNUSED(ignored))
 {
 	gpiod_LineBulkObject *bulk_obj;
 	struct gpiod_line_bulk *bulk;
-	gpiod_LineObject *line_obj;
-	unsigned int idx;
-	PyObject *list;
-	int rv;
 
 	if (gpiod_ChipIsClosed(self))
 		return NULL;
@@ -2306,36 +2356,8 @@ gpiod_Chip_get_all_lines(gpiod_ChipObject *self, PyObject *Py_UNUSED(ignored))
 		return (gpiod_LineBulkObject *)PyErr_SetFromErrno(
 							PyExc_OSError);
 
-	list = PyList_New(gpiod_line_bulk_num_lines(bulk));
-	if (!list) {
-		gpiod_line_bulk_free(bulk);
-		return NULL;
-	}
-
-	for (idx = 0; idx < gpiod_line_bulk_num_lines(bulk); idx++) {
-		line_obj = gpiod_MakeLineObject(self, gpiod_line_bulk_get_line(bulk, idx));
-		if (!line_obj) {
-			gpiod_line_bulk_free(bulk);
-			Py_DECREF(list);
-			return NULL;
-		}
-
-		rv = PyList_SetItem(list, idx, (PyObject *)line_obj);
-		if (rv < 0) {
-			gpiod_line_bulk_free(bulk);
-			Py_DECREF(line_obj);
-			Py_DECREF(list);
-			return NULL;
-		}
-	}
-
+	bulk_obj = gpiod_LineBulkObjectFromBulk(self, bulk);
 	gpiod_line_bulk_free(bulk);
-
-	bulk_obj = gpiod_ListToLineBulk(list);
-	Py_DECREF(list);
-	if (!bulk_obj)
-		return NULL;
-
 	return bulk_obj;
 }
 
@@ -2384,8 +2406,8 @@ static PyMethodDef gpiod_Chip_methods[] = {
 	},
 	{
 		.ml_name = "find_line",
-		.ml_meth = (PyCFunction)gpiod_Chip_find_line,
-		.ml_flags = METH_VARARGS,
+		.ml_meth = (PyCFunction)(void (*)(void))gpiod_Chip_find_line,
+		.ml_flags = METH_VARARGS | METH_KEYWORDS,
 		.ml_doc = gpiod_Chip_find_line_doc,
 	},
 	{
diff --git a/bindings/python/tests/gpiod_py_test.py b/bindings/python/tests/gpiod_py_test.py
index 6ee72a9..c490933 100755
--- a/bindings/python/tests/gpiod_py_test.py
+++ b/bindings/python/tests/gpiod_py_test.py
@@ -149,8 +149,9 @@ class ChipGetLines(MockupTestCase):
 
     def test_find_single_line_by_name(self):
         with gpiod.Chip(mockup.chip_name(1)) as chip:
-            line = chip.find_line('gpio-mockup-B-4')
-            self.assertEqual(line.offset(), 4)
+            lines = chip.find_line('gpio-mockup-B-4').to_list()
+            self.assertEqual(len(lines), 1)
+            self.assertEqual(lines[0].offset(), 4)
 
     def test_get_single_line_invalid_offset(self):
         with gpiod.Chip(mockup.chip_name(1)) as chip:
@@ -161,8 +162,8 @@ class ChipGetLines(MockupTestCase):
 
     def test_find_single_line_nonexistent(self):
         with gpiod.Chip(mockup.chip_name(1)) as chip:
-            line = chip.find_line('nonexistent-line')
-            self.assertEqual(line, None)
+            lines = chip.find_line('nonexistent-line')
+            self.assertEqual(lines, None)
 
     def test_get_multiple_lines_by_offsets_in_tuple(self):
         with gpiod.Chip(mockup.chip_name(1)) as chip:
diff --git a/include/gpiod.h b/include/gpiod.h
index 34313ed..fc50fe8 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -170,19 +170,31 @@ struct gpiod_line_bulk *
 gpiod_chip_get_all_lines(struct gpiod_chip *chip) GPIOD_API;
 
 /**
- * @brief Find a GPIO line by name among lines associated with given GPIO chip.
+ * @brief Find all GPIO lines by name among lines exposed by this GPIO chip.
  * @param chip The GPIO chip object.
- * @param name The name of the GPIO line.
+ * @param name GPIO line name to look for.
+ * @return New line bulk object containing all matching lines or NULL on error.
+ *
+ * If no line with given name is associated with this chip, the function sets
+ * errno to ENOENT.
+ */
+struct gpiod_line_bulk *
+gpiod_chip_find_line(struct gpiod_chip *chip, const char *name) GPIOD_API;
+
+/**
+ * @brief Find a unique line by name among lines exposed by this GPIO chip.
+ * @param chip The GPIO chip object.
+ * @param name Name of the GPIO line.
  * @return Pointer to the GPIO line handle or NULL if the line could not be
  *         found or an error occurred.
- * @note In case a line with given name is not associated with given chip, the
- *       function sets errno to ENOENT.
- * @attention GPIO line names are not unique in the linux kernel, neither
- *            globally nor within a single chip. This function finds the first
- *            line with given name.
+ *
+ * If no line with given name is associated with this chip, the function sets
+ * errno to ENOENT. If more than one line with given name is associated with
+ * this chip, the function sets errno to ERANGE.
  */
 struct gpiod_line *
-gpiod_chip_find_line(struct gpiod_chip *chip, const char *name) GPIOD_API;
+gpiod_chip_find_line_unique(struct gpiod_chip *chip,
+			    const char *name) GPIOD_API;
 
 /**
  * @}
diff --git a/lib/helpers.c b/lib/helpers.c
index 509a1c8..ec2575d 100644
--- a/lib/helpers.c
+++ b/lib/helpers.c
@@ -120,11 +120,48 @@ struct gpiod_line_bulk *gpiod_chip_get_all_lines(struct gpiod_chip *chip)
 	return bulk;
 }
 
-struct gpiod_line *
+struct gpiod_line_bulk *
 gpiod_chip_find_line(struct gpiod_chip *chip, const char *name)
 {
+	struct gpiod_line_bulk *bulk = NULL;
+	unsigned int offset, num_lines;
 	struct gpiod_line *line;
-	unsigned int offset;
+	const char *tmp;
+
+	num_lines = gpiod_chip_num_lines(chip);
+
+	for (offset = 0; offset < num_lines; offset++) {
+		line = gpiod_chip_get_line(chip, offset);
+		if (!line) {
+			if (bulk)
+				gpiod_line_bulk_free(bulk);
+
+			return NULL;
+		}
+
+		tmp = gpiod_line_name(line);
+		if (tmp && strcmp(tmp, name) == 0) {
+			if (!bulk) {
+				bulk = gpiod_line_bulk_new(num_lines);
+				if (!bulk)
+					return NULL;
+			}
+
+			gpiod_line_bulk_add_line(bulk, line);
+		}
+	}
+
+	if (!bulk)
+		errno = ENOENT;
+
+	return bulk;
+}
+
+struct gpiod_line *
+gpiod_chip_find_line_unique(struct gpiod_chip *chip, const char *name)
+{
+	struct gpiod_line *line, *matching = NULL;
+	unsigned int offset, num_found = 0;
 	const char *tmp;
 
 	for (offset = 0; offset < gpiod_chip_num_lines(chip); offset++) {
@@ -133,12 +170,22 @@ gpiod_chip_find_line(struct gpiod_chip *chip, const char *name)
 			return NULL;
 
 		tmp = gpiod_line_name(line);
-		if (tmp && strcmp(tmp, name) == 0)
-			return line;
+		if (tmp && strcmp(tmp, name) == 0) {
+			matching = line;
+			num_found++;
+		}
 	}
 
-	errno = ENOENT;
+	if (matching) {
+		if (num_found > 1) {
+			errno = ERANGE;
+			return NULL;
+		}
 
+		return matching;
+	}
+
+	errno = ENOENT;
 	return NULL;
 }
 
diff --git a/tests/tests-chip.c b/tests/tests-chip.c
index 543c103..1c365b9 100644
--- a/tests/tests-chip.c
+++ b/tests/tests-chip.c
@@ -235,7 +235,7 @@ GPIOD_TEST_CASE(get_all_lines, 0, { 4 })
 	g_assert_cmpuint(gpiod_line_offset(line3), ==, 3);
 }
 
-GPIOD_TEST_CASE(find_line_good, GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
+GPIOD_TEST_CASE(find_line_good_unique, GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
 {
 	g_autoptr(gpiod_chip_struct) chip = NULL;
 	struct gpiod_line *line;
@@ -244,14 +244,15 @@ GPIOD_TEST_CASE(find_line_good, GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
 	g_assert_nonnull(chip);
 	gpiod_test_return_if_failed();
 
-	line = gpiod_chip_find_line(chip, "gpio-mockup-B-4");
+	line = gpiod_chip_find_line_unique(chip, "gpio-mockup-B-4");
 	g_assert_nonnull(line);
 	gpiod_test_return_if_failed();
 	g_assert_cmpuint(gpiod_line_offset(line), ==, 4);
 	g_assert_cmpstr(gpiod_line_name(line), ==, "gpio-mockup-B-4");
 }
 
-GPIOD_TEST_CASE(find_line_not_found, GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
+GPIOD_TEST_CASE(find_line_unique_not_found,
+		GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
 {
 	g_autoptr(gpiod_chip_struct) chip = NULL;
 	struct gpiod_line *line;
@@ -260,7 +261,7 @@ GPIOD_TEST_CASE(find_line_not_found, GPIOD_TEST_FLAG_NAMED_LINES, { 8, 8, 8 })
 	g_assert_nonnull(chip);
 	gpiod_test_return_if_failed();
 
-	line = gpiod_chip_find_line(chip, "nonexistent");
+	line = gpiod_chip_find_line_unique(chip, "nonexistent");
 	g_assert_null(line);
 	g_assert_cmpint(errno, ==, ENOENT);
 }
diff --git a/tools/gpiofind.c b/tools/gpiofind.c
index 489cf33..ffb8fc0 100644
--- a/tools/gpiofind.c
+++ b/tools/gpiofind.c
@@ -69,7 +69,7 @@ int main(int argc, char **argv)
 		die_perror("unable to access GPIO chips");
 
 	gpiod_foreach_chip(iter, chip) {
-		line = gpiod_chip_find_line(chip, argv[0]);
+		line = gpiod_chip_find_line_unique(chip, argv[0]);
 		if (line) {
 			printf("%s %u\n",
 			       gpiod_chip_name(chip), gpiod_line_offset(line));
-- 
2.29.1


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

* [libgpiod][PATCH 13/14] build: add a configure switch for building examples
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (11 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 12/14] core: rework gpiod_chip_find_line() Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:23 ` [libgpiod][PATCH 14/14] core: kill chip iterators Bartosz Golaszewski
  2020-12-10 13:56 ` [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Andy Shevchenko
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Example code for bindings is currently always built if bindings are
enabled. Make it conditional with a new configure switch.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/Makefile.am    |  8 +++++++-
 bindings/python/Makefile.am | 10 ++++++++--
 configure.ac                |  6 ++++++
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/bindings/cxx/Makefile.am b/bindings/cxx/Makefile.am
index 5c40ceb..87463b0 100644
--- a/bindings/cxx/Makefile.am
+++ b/bindings/cxx/Makefile.am
@@ -18,10 +18,16 @@ include_HEADERS = gpiod.hpp
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libgpiodcxx.pc
 
-SUBDIRS = . examples
+SUBDIRS = .
 
 if WITH_TESTS
 
 SUBDIRS += tests
 
 endif
+
+if WITH_EXAMPLES
+
+SUBDIRS += examples
+
+endif
diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am
index 124f152..5403bcb 100644
--- a/bindings/python/Makefile.am
+++ b/bindings/python/Makefile.am
@@ -6,8 +6,6 @@
 # Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
 #
 
-SUBDIRS = . examples
-
 pyexec_LTLIBRARIES = gpiod.la
 
 gpiod_la_SOURCES = gpiodmodule.c
@@ -17,8 +15,16 @@ gpiod_la_CFLAGS += -Wall -Wextra -g -std=gnu89 $(PYTHON_CPPFLAGS)
 gpiod_la_LDFLAGS = -module -avoid-version
 gpiod_la_LIBADD = $(top_builddir)/lib/libgpiod.la $(PYTHON_LIBS)
 
+SUBDIRS = .
+
 if WITH_TESTS
 
 SUBDIRS += tests
 
 endif
+
+if WITH_EXAMPLES
+
+SUBDIRS += examples
+
+endif
diff --git a/configure.ac b/configure.ac
index 57c99a8..90a6324 100644
--- a/configure.ac
+++ b/configure.ac
@@ -155,6 +155,12 @@ then
 	fi
 fi
 
+AC_ARG_ENABLE([examples],
+	[AS_HELP_STRING([--enable-examples], [enable building code examples[default=no]])],
+	[if test "x$enableval" = xyes; then with_examples=true; fi],
+	[with_examples=false])
+AM_CONDITIONAL([WITH_EXAMPLES], [test "x$with_examples" = xtrue])
+
 AC_ARG_ENABLE([bindings-cxx],
 	[AS_HELP_STRING([--enable-bindings-cxx],[enable C++ bindings [default=no]])],
 	[if test "x$enableval" = xyes; then with_bindings_cxx=true; fi],
-- 
2.29.1


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

* [libgpiod][PATCH 14/14] core: kill chip iterators
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (12 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 13/14] build: add a configure switch for building examples Bartosz Golaszewski
@ 2020-12-10 13:23 ` Bartosz Golaszewski
  2020-12-10 13:56 ` [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Andy Shevchenko
  14 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-10 13:23 UTC (permalink / raw)
  To: Kent Gibson, Andy Shevchenko, Geert Uytterhoeven, Jack Winch,
	Helmut Grohne, Linus Walleij
  Cc: linux-gpio, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Chip iterators require the user to have permission to access all GPIO
chips. They also don't take into account symbolic links. In general
they're badly designed so remove them treewide in favor of scanning /dev
manually using the provided gpiod_is_gpiochip_device() helper.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/chip.cpp                   |   5 +
 bindings/cxx/examples/Makefile.am       |   4 +-
 bindings/cxx/examples/gpiodetectcxx.cpp |  13 ++-
 bindings/cxx/examples/gpiofindcxx.cpp   |  16 ++-
 bindings/cxx/examples/gpioinfocxx.cpp   |  43 +++++----
 bindings/cxx/gpiod.hpp                  | 117 ++--------------------
 bindings/cxx/iter.cpp                   |  67 -------------
 bindings/cxx/tests/tests-chip.cpp       |  20 ++++
 bindings/cxx/tests/tests-iter.cpp       |  37 -------
 bindings/python/examples/gpiodetect.py  |  12 ++-
 bindings/python/examples/gpiofind.py    |  15 ++-
 bindings/python/examples/gpioinfo.py    |  33 ++++---
 bindings/python/gpiodmodule.c           | 114 +++++++---------------
 bindings/python/tests/gpiod_py_test.py  |  39 +++-----
 configure.ac                            |   6 ++
 include/gpiod.h                         |  93 +-----------------
 lib/Makefile.am                         |   2 +-
 lib/iter.c                              | 123 ------------------------
 tests/Makefile.am                       |   1 -
 tests/gpiod-test.h                      |   2 -
 tests/tests-iter.c                      | 100 -------------------
 tools/gpiodetect.c                      |  29 ++++--
 tools/gpiofind.c                        |  27 +++---
 tools/gpioinfo.c                        |  27 ++++--
 tools/tools-common.c                    |  15 +++
 tools/tools-common.h                    |   3 +
 26 files changed, 250 insertions(+), 713 deletions(-)
 delete mode 100644 lib/iter.c
 delete mode 100644 tests/tests-iter.c

diff --git a/bindings/cxx/chip.cpp b/bindings/cxx/chip.cpp
index 82ba559..107088e 100644
--- a/bindings/cxx/chip.cpp
+++ b/bindings/cxx/chip.cpp
@@ -51,6 +51,11 @@ void chip_deleter(::gpiod_chip* chip)
 
 } /* namespace */
 
+bool is_gpiochip_device(const ::std::string& path)
+{
+	return ::gpiod_is_gpiochip_device(path.c_str());
+}
+
 chip::chip(const ::std::string& device, int how)
 	: _m_chip()
 {
diff --git a/bindings/cxx/examples/Makefile.am b/bindings/cxx/examples/Makefile.am
index 8d39be2..43e9875 100644
--- a/bindings/cxx/examples/Makefile.am
+++ b/bindings/cxx/examples/Makefile.am
@@ -7,8 +7,8 @@
 #
 
 AM_CPPFLAGS = -I$(top_srcdir)/bindings/cxx/ -I$(top_srcdir)/include
-AM_CPPFLAGS += -Wall -Wextra -g -std=gnu++11
-AM_LDFLAGS = -lgpiodcxx -L$(top_builddir)/bindings/cxx/
+AM_CPPFLAGS += -Wall -Wextra -g -std=gnu++17
+AM_LDFLAGS = -lgpiodcxx -L$(top_builddir)/bindings/cxx/ -lstdc++fs
 
 noinst_PROGRAMS =				\
 		gpiodetectcxx			\
diff --git a/bindings/cxx/examples/gpiodetectcxx.cpp b/bindings/cxx/examples/gpiodetectcxx.cpp
index 6da5573..76d367d 100644
--- a/bindings/cxx/examples/gpiodetectcxx.cpp
+++ b/bindings/cxx/examples/gpiodetectcxx.cpp
@@ -10,6 +10,7 @@
 #include <gpiod.hpp>
 
 #include <cstdlib>
+#include <filesystem>
 #include <iostream>
 
 int main(int argc, char **argv)
@@ -19,10 +20,14 @@ int main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	for (auto& it: ::gpiod::make_chip_iter()) {
-	        ::std::cout << it.name() << " ["
-			  << it.label() << "] ("
-			  << it.num_lines() << " lines)" << ::std::endl;
+	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
+		if (::gpiod::is_gpiochip_device(entry.path())) {
+			::gpiod::chip chip(entry.path());
+
+			::std::cout << chip.name() << " ["
+				    << chip.label() << "] ("
+				    << chip.num_lines() << " lines)" << ::std::endl;
+		}
 	}
 
 	return EXIT_SUCCESS;
diff --git a/bindings/cxx/examples/gpiofindcxx.cpp b/bindings/cxx/examples/gpiofindcxx.cpp
index c817378..f8b771c 100644
--- a/bindings/cxx/examples/gpiofindcxx.cpp
+++ b/bindings/cxx/examples/gpiofindcxx.cpp
@@ -10,6 +10,7 @@
 #include <gpiod.hpp>
 
 #include <cstdlib>
+#include <filesystem>
 #include <iostream>
 
 int main(int argc, char **argv)
@@ -19,11 +20,16 @@ int main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	for (auto& chip: ::gpiod::make_chip_iter()) {
-		auto lines = chip.find_line(argv[1], true);
-		if (!lines.empty()) {
-			::std::cout << lines.front().name() << " " << lines.front().offset() << ::std::endl;
-			return EXIT_SUCCESS;
+	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
+		if (::gpiod::is_gpiochip_device(entry.path())) {
+			::gpiod::chip chip(entry.path());
+
+			auto lines = chip.find_line(argv[1], true);
+			if (!lines.empty()) {
+				::std::cout << lines.front().name() << " " <<
+					       lines.front().offset() << ::std::endl;
+				return EXIT_SUCCESS;
+			}
 		}
 	}
 
diff --git a/bindings/cxx/examples/gpioinfocxx.cpp b/bindings/cxx/examples/gpioinfocxx.cpp
index 02d69b6..2490abd 100644
--- a/bindings/cxx/examples/gpioinfocxx.cpp
+++ b/bindings/cxx/examples/gpioinfocxx.cpp
@@ -10,6 +10,7 @@
 #include <gpiod.hpp>
 
 #include <cstdlib>
+#include <filesystem>
 #include <iostream>
 
 int main(int argc, char **argv)
@@ -19,31 +20,35 @@ int main(int argc, char **argv)
 		return EXIT_FAILURE;
 	}
 
-	for (auto& cit: ::gpiod::make_chip_iter()) {
-		::std::cout << cit.name() << " - " << cit.num_lines() << " lines:" << ::std::endl;
+	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
+		if (::gpiod::is_gpiochip_device(entry.path())) {
+			::gpiod::chip chip(entry.path());
 
-		for (auto& lit: ::gpiod::line_iter(cit)) {
-			::std::cout << "\tline ";
-			::std::cout.width(3);
-			::std::cout << lit.offset() << ": ";
+			::std::cout << chip.name() << " - " << chip.num_lines() << " lines:" << ::std::endl;
 
-			::std::cout.width(12);
-			::std::cout << (lit.name().empty() ? "unnamed" : lit.name());
-			::std::cout << " ";
+			for (auto& lit: ::gpiod::line_iter(chip)) {
+				::std::cout << "\tline ";
+				::std::cout.width(3);
+				::std::cout << lit.offset() << ": ";
 
-			::std::cout.width(12);
-			::std::cout << (lit.consumer().empty() ? "unused" : lit.consumer());
-			::std::cout << " ";
+				::std::cout.width(12);
+				::std::cout << (lit.name().empty() ? "unnamed" : lit.name());
+				::std::cout << " ";
 
-			::std::cout.width(8);
-			::std::cout << (lit.direction() == ::gpiod::line::DIRECTION_INPUT ? "input" : "output");
-			::std::cout << " ";
+				::std::cout.width(12);
+				::std::cout << (lit.consumer().empty() ? "unused" : lit.consumer());
+				::std::cout << " ";
 
-			::std::cout.width(10);
-			::std::cout << (lit.active_state() == ::gpiod::line::ACTIVE_LOW
-								? "active-low" : "active-high");
+				::std::cout.width(8);
+				::std::cout << (lit.direction() == ::gpiod::line::DIRECTION_INPUT ? "input" : "output");
+				::std::cout << " ";
 
-			::std::cout << ::std::endl;
+				::std::cout.width(10);
+				::std::cout << (lit.active_state() == ::gpiod::line::ACTIVE_LOW
+									? "active-low" : "active-high");
+
+				::std::cout << ::std::endl;
+			}
 		}
 	}
 
diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
index 9d081fe..d81ee30 100644
--- a/bindings/cxx/gpiod.hpp
+++ b/bindings/cxx/gpiod.hpp
@@ -32,6 +32,14 @@ struct line_event;
  * @{
  */
 
+/**
+ * @brief Check if the file pointed to by path is a GPIO chip character device.
+ * @param path Path to check.
+ * @return True if the file exists and is a GPIO chip character device or a
+ *         symbolic link to it.
+ */
+bool is_gpiochip_device(const ::std::string& path) GPIOD_API;
+
 /**
  * @brief Represents a GPIO chip.
  *
@@ -861,115 +869,6 @@ private:
 	::std::vector<line> _m_bulk;
 };
 
-/**
- * @brief Create a new chip_iter.
- * @return New chip iterator object pointing to the first GPIO chip on the system.
- * @note This function is needed as we already use the default constructor of
- *       gpiod::chip_iter as the return value of gpiod::end.
- */
-GPIOD_API chip_iter make_chip_iter(void);
-
-/**
- * @brief Support for range-based loops for chip iterators.
- * @param iter A chip iterator.
- * @return Iterator unchanged.
- */
-GPIOD_API chip_iter begin(chip_iter iter) noexcept;
-
-/**
- * @brief Support for range-based loops for chip iterators.
- * @param iter A chip iterator.
- * @return New end iterator.
- */
-GPIOD_API chip_iter end(const chip_iter& iter) noexcept;
-
-/**
- * @brief Allows to iterate over all GPIO chips present on the system.
- */
-class chip_iter
-{
-public:
-
-	/**
-	 * @brief Default constructor. Creates the end iterator.
-	 */
-	GPIOD_API chip_iter(void) = default;
-
-	/**
-	 * @brief Copy constructor.
-	 * @param other Other chip_iter.
-	 */
-	GPIOD_API chip_iter(const chip_iter& other) = default;
-
-	/**
-	 * @brief Move constructor.
-	 * @param other Other chip_iter.
-	 */
-	GPIOD_API chip_iter(chip_iter&& other) = default;
-
-	/**
-	 * @brief Assignment operator.
-	 * @param other Other chip_iter.
-	 * @return Reference to this iterator.
-	 */
-	GPIOD_API chip_iter& operator=(const chip_iter& other) = default;
-
-	/**
-	 * @brief Move assignment operator.
-	 * @param other Other chip_iter.
-	 * @return Reference to this iterator.
-	 */
-	GPIOD_API chip_iter& operator=(chip_iter&& other) = default;
-
-	/**
-	 * @brief Destructor.
-	 */
-	GPIOD_API ~chip_iter(void) = default;
-
-	/**
-	 * @brief Advance the iterator by one element.
-	 * @return Reference to this iterator.
-	 */
-	GPIOD_API chip_iter& operator++(void);
-
-	/**
-	 * @brief Dereference current element.
-	 * @return Current GPIO chip by reference.
-	 */
-	GPIOD_API const chip& operator*(void) const;
-
-	/**
-	 * @brief Member access operator.
-	 * @return Current GPIO chip by pointer.
-	 */
-	GPIOD_API const chip* operator->(void) const;
-
-	/**
-	 * @brief Check if this operator points to the same element.
-	 * @param rhs Right-hand side of the equation.
-	 * @return True if this iterator points to the same chip_iter,
-	 *         false otherwise.
-	 */
-	GPIOD_API bool operator==(const chip_iter& rhs) const noexcept;
-
-	/**
-	 * @brief Check if this operator doesn't point to the same element.
-	 * @param rhs Right-hand side of the equation.
-	 * @return True if this iterator doesn't point to the same chip_iter,
-	 *         false otherwise.
-	 */
-	GPIOD_API bool operator!=(const chip_iter& rhs) const noexcept;
-
-private:
-
-	chip_iter(::gpiod_chip_iter* iter);
-
-	::std::shared_ptr<::gpiod_chip_iter> _m_iter;
-	chip _m_current;
-
-	friend chip_iter make_chip_iter(void);
-};
-
 /**
  * @brief Support for range-based loops for line iterators.
  * @param iter A line iterator.
diff --git a/bindings/cxx/iter.cpp b/bindings/cxx/iter.cpp
index 15c3925..846d36b 100644
--- a/bindings/cxx/iter.cpp
+++ b/bindings/cxx/iter.cpp
@@ -10,73 +10,6 @@
 
 namespace gpiod {
 
-namespace {
-
-void chip_iter_deleter(::gpiod_chip_iter* iter)
-{
-	::gpiod_chip_iter_free_noclose(iter);
-}
-
-} /* namespace */
-
-chip_iter make_chip_iter(void)
-{
-	::gpiod_chip_iter* iter = ::gpiod_chip_iter_new();
-	if (!iter)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error creating GPIO chip iterator");
-
-	return chip_iter(iter);
-}
-
-bool chip_iter::operator==(const chip_iter& rhs) const noexcept
-{
-	return this->_m_current == rhs._m_current;
-}
-
-bool chip_iter::operator!=(const chip_iter& rhs) const noexcept
-{
-	return this->_m_current != rhs._m_current;
-}
-
-chip_iter::chip_iter(::gpiod_chip_iter *iter)
-	: _m_iter(iter, chip_iter_deleter)
-{
-	::gpiod_chip* first = ::gpiod_chip_iter_next_noclose(this->_m_iter.get());
-
-	if (first != nullptr)
-		this->_m_current = chip(first);
-}
-
-chip_iter& chip_iter::operator++(void)
-{
-	::gpiod_chip* next = ::gpiod_chip_iter_next_noclose(this->_m_iter.get());
-
-	this->_m_current = next ? chip(next) : chip();
-
-	return *this;
-}
-
-const chip& chip_iter::operator*(void) const
-{
-	return this->_m_current;
-}
-
-const chip* chip_iter::operator->(void) const
-{
-	return ::std::addressof(this->_m_current);
-}
-
-chip_iter begin(chip_iter iter) noexcept
-{
-	return iter;
-}
-
-chip_iter end(const chip_iter&) noexcept
-{
-	return chip_iter();
-}
-
 line_iter begin(line_iter iter) noexcept
 {
 	return iter;
diff --git a/bindings/cxx/tests/tests-chip.cpp b/bindings/cxx/tests/tests-chip.cpp
index c45f2df..2492b42 100644
--- a/bindings/cxx/tests/tests-chip.cpp
+++ b/bindings/cxx/tests/tests-chip.cpp
@@ -12,6 +12,26 @@
 
 using ::gpiod::test::mockup;
 
+TEST_CASE("GPIO chip device can be verified with is_gpiochip_device()", "[chip]")
+{
+	mockup::probe_guard mockup_chips({ 8 });
+
+	SECTION("good chip")
+	{
+		REQUIRE(::gpiod::is_gpiochip_device(mockup::instance().chip_path(0)));
+	}
+
+	SECTION("not a chip")
+	{
+		REQUIRE_FALSE(::gpiod::is_gpiochip_device("/dev/null"));
+	}
+
+	SECTION("nonexistent file")
+	{
+		REQUIRE_FALSE(::gpiod::is_gpiochip_device("/dev/nonexistent_device"));
+	}
+}
+
 TEST_CASE("GPIO chip device can be opened in different modes", "[chip]")
 {
 	mockup::probe_guard mockup_chips({ 8, 8, 8 });
diff --git a/bindings/cxx/tests/tests-iter.cpp b/bindings/cxx/tests/tests-iter.cpp
index 4c07613..708709c 100644
--- a/bindings/cxx/tests/tests-iter.cpp
+++ b/bindings/cxx/tests/tests-iter.cpp
@@ -12,43 +12,6 @@
 
 using ::gpiod::test::mockup;
 
-TEST_CASE("Chip iterator works", "[iter][chip]")
-{
-	mockup::probe_guard mockup_chips({ 8, 8, 8 });
-	bool gotA = false, gotB = false, gotC = false;
-
-	for (auto& it: ::gpiod::make_chip_iter()) {
-		if (it.label() == "gpio-mockup-A")
-			gotA = true;
-		if (it.label() == "gpio-mockup-B")
-			gotB = true;
-		if (it.label() == "gpio-mockup-C")
-			gotC = true;
-	}
-
-	REQUIRE(gotA);
-	REQUIRE(gotB);
-	REQUIRE(gotC);
-}
-
-TEST_CASE("Chip iterator loop can be broken out of", "[iter][chip]")
-{
-	mockup::probe_guard mockup_chips({ 8, 8, 8, 8, 8, 8 });
-	int count_chips = 0;
-
-	for (auto& it: ::gpiod::make_chip_iter()) {
-		if (it.label() == "gpio-mockup-A" ||
-		    it.label() == "gpio-mockup-B" ||
-		    it.label() == "gpio-mockup-C")
-			count_chips++;
-
-		if (count_chips == 3)
-			break;
-	}
-
-	REQUIRE(count_chips == 3);
-}
-
 TEST_CASE("Line iterator works", "[iter][line]")
 {
 	mockup::probe_guard mockup_chips({ 4 });
diff --git a/bindings/python/examples/gpiodetect.py b/bindings/python/examples/gpiodetect.py
index 9318f51..781939b 100755
--- a/bindings/python/examples/gpiodetect.py
+++ b/bindings/python/examples/gpiodetect.py
@@ -10,10 +10,12 @@
 '''Reimplementation of the gpiodetect tool in Python.'''
 
 import gpiod
+import os
 
 if __name__ == '__main__':
-    for chip in gpiod.ChipIter():
-        print('{} [{}] ({} lines)'.format(chip.name(),
-                                          chip.label(),
-                                          chip.num_lines()))
-        chip.close()
+    for entry in os.scandir('/dev/'):
+        if gpiod.is_gpiochip_device(entry.path):
+            with gpiod.Chip(entry.path) as chip:
+                print('{} [{}] ({} lines)'.format(chip.name(),
+                                                  chip.label(),
+                                                  chip.num_lines()))
diff --git a/bindings/python/examples/gpiofind.py b/bindings/python/examples/gpiofind.py
index 8505ba0..2655742 100755
--- a/bindings/python/examples/gpiofind.py
+++ b/bindings/python/examples/gpiofind.py
@@ -10,12 +10,17 @@
 '''Reimplementation of the gpiofind tool in Python.'''
 
 import gpiod
+import os
 import sys
 
 if __name__ == '__main__':
-    line = gpiod.find_line(sys.argv[1])
-    if line is None:
-        sys.exit(1)
+    for entry in os.scandir('/dev/'):
+        if gpiod.is_gpiochip_device(entry.path):
+            with gpiod.Chip(entry.path) as chip:
+                lines = chip.find_line(sys.argv[1], unique=True)
+                if lines is not None:
+                     line = lines.to_list()[0]
+                     print('{} {}'.format(line.owner().name(), line.offset()))
+                     sys.exit(0)
 
-    print('{} {}'.format(line.owner().name(), line.offset()))
-    line.owner().close()
+    sys.exit(1)
diff --git a/bindings/python/examples/gpioinfo.py b/bindings/python/examples/gpioinfo.py
index de4b6f3..6a47b66 100755
--- a/bindings/python/examples/gpioinfo.py
+++ b/bindings/python/examples/gpioinfo.py
@@ -10,23 +10,24 @@
 '''Simplified reimplementation of the gpioinfo tool in Python.'''
 
 import gpiod
+import os
 
 if __name__ == '__main__':
-    for chip in gpiod.ChipIter():
-        print('{} - {} lines:'.format(chip.name(), chip.num_lines()))
+    for entry in os.scandir('/dev/'):
+        if gpiod.is_gpiochip_device(entry.path):
+            with gpiod.Chip(entry.path) as chip:
+                print('{} - {} lines:'.format(chip.name(), chip.num_lines()))
 
-        for line in gpiod.LineIter(chip):
-            offset = line.offset()
-            name = line.name()
-            consumer = line.consumer()
-            direction = line.direction()
-            active_state = line.active_state()
+                for line in gpiod.LineIter(chip):
+                    offset = line.offset()
+                    name = line.name()
+                    consumer = line.consumer()
+                    direction = line.direction()
+                    active_state = line.active_state()
 
-            print('\tline {:>3}: {:>18} {:>12} {:>8} {:>10}'.format(
-                    offset,
-                    'unnamed' if name is None else name,
-                    'unused' if consumer is None else consumer,
-                    'input' if direction == gpiod.Line.DIRECTION_INPUT else 'output',
-                    'active-low' if active_state == gpiod.Line.ACTIVE_LOW else 'active-high'))
-
-        chip.close()
+                    print('\tline {:>3}: {:>18} {:>12} {:>8} {:>10}'.format(
+                          offset,
+                          'unnamed' if name is None else name,
+                          'unused' if consumer is None else consumer,
+                          'input' if direction == gpiod.Line.DIRECTION_INPUT else 'output',
+                          'active-low' if active_state == gpiod.Line.ACTIVE_LOW else 'active-high'))
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index d183e6f..af37df2 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -34,11 +34,6 @@ typedef struct {
 	Py_ssize_t iter_idx;
 } gpiod_LineBulkObject;
 
-typedef struct {
-	PyObject_HEAD
-	struct gpiod_chip_iter *iter;
-} gpiod_ChipIterObject;
-
 typedef struct {
 	PyObject_HEAD
 	unsigned int offset;
@@ -2220,7 +2215,7 @@ PyDoc_STRVAR(gpiod_Chip_find_line_doc,
 static gpiod_LineBulkObject *
 gpiod_Chip_find_line(gpiod_ChipObject *self, PyObject *args, PyObject *kwds)
 {
-	static char *kwlist[] = { "unique", NULL };
+	static char *kwlist[] = { "", "unique", NULL };
 
 	gpiod_LineBulkObject *bulk_obj;
 	struct gpiod_line_bulk *bulk;
@@ -2469,76 +2464,6 @@ static PyTypeObject gpiod_ChipType = {
 	.tp_methods = gpiod_Chip_methods,
 };
 
-static int gpiod_ChipIter_init(gpiod_ChipIterObject *self,
-			       PyObject *Py_UNUSED(ignored0),
-			       PyObject *Py_UNUSED(ignored1))
-{
-	self->iter = gpiod_chip_iter_new();
-	if (!self->iter) {
-		PyErr_SetFromErrno(PyExc_OSError);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void gpiod_ChipIter_dealloc(gpiod_ChipIterObject *self)
-{
-	if (self->iter)
-		gpiod_chip_iter_free_noclose(self->iter);
-
-	PyObject_Del(self);
-}
-
-static gpiod_ChipObject *gpiod_ChipIter_next(gpiod_ChipIterObject *self)
-{
-	gpiod_ChipObject *chip_obj;
-	struct gpiod_chip *chip;
-
-	Py_BEGIN_ALLOW_THREADS;
-	chip = gpiod_chip_iter_next_noclose(self->iter);
-	Py_END_ALLOW_THREADS;
-	if (!chip)
-		return NULL; /* Last element. */
-
-	chip_obj = PyObject_New(gpiod_ChipObject, &gpiod_ChipType);
-	if (!chip_obj) {
-		gpiod_chip_close(chip);
-		return NULL;
-	}
-
-	chip_obj->chip = chip;
-
-	return chip_obj;
-}
-
-PyDoc_STRVAR(gpiod_ChipIterType_doc,
-"Allows to iterate over all GPIO chips in the system.\n"
-"\n"
-"The ChipIter's constructor takes no arguments.\n"
-"\n"
-"Each iteration yields the next open GPIO chip handle. The caller is\n"
-"responsible for closing each chip\n"
-"\n"
-"Example:\n"
-"\n"
-"    for chip in gpiod.ChipIter():\n"
-"        do_something_with_chip(chip)\n"
-"        chip.close()");
-
-static PyTypeObject gpiod_ChipIterType = {
-	PyVarObject_HEAD_INIT(NULL, 0)
-	.tp_name = "gpiod.ChipIter",
-	.tp_basicsize = sizeof(gpiod_ChipIterObject),
-	.tp_flags = Py_TPFLAGS_DEFAULT,
-	.tp_doc = gpiod_ChipIterType_doc,
-	.tp_new = PyType_GenericNew,
-	.tp_init = (initproc)gpiod_ChipIter_init,
-	.tp_dealloc = (destructor)gpiod_ChipIter_dealloc,
-	.tp_iter = PyObject_SelfIter,
-	.tp_iternext = (iternextfunc)gpiod_ChipIter_next,
-};
-
 static int gpiod_LineIter_init(gpiod_LineIterObject *self,
 			       PyObject *args, PyObject *Py_UNUSED(ignored))
 {
@@ -2618,7 +2543,6 @@ static gpiod_PyType gpiod_PyType_list[] = {
 	{ .name = "LineEvent",	.typeobj = &gpiod_LineEventType,	},
 	{ .name = "LineBulk",	.typeobj = &gpiod_LineBulkType,		},
 	{ .name = "LineIter",	.typeobj = &gpiod_LineIterType,		},
-	{ .name = "ChipIter",	.typeobj = &gpiod_ChipIterType		},
 	{ }
 };
 
@@ -2702,6 +2626,41 @@ static gpiod_ConstDescr gpiod_ConstList[] = {
 	{ }
 };
 
+PyDoc_STRVAR(gpiod_Module_is_gpiochip_device_doc,
+"is_gpiochip_device(path) -> boolean\n"
+"\n"
+"Check if the file pointed to by path is a GPIO chip character device.\n"
+"Returns true if so, False otherwise.\n"
+"\n"
+"  path\n"
+"    Path to the file that should be checked.\n");
+
+static PyObject *
+gpiod_Module_is_gpiochip_device(PyObject *Py_UNUSED(self), PyObject *args)
+{
+	const char *path;
+	int ret;
+
+	ret = PyArg_ParseTuple(args, "s", &path);
+	if (!ret)
+		return NULL;
+
+	if (gpiod_is_gpiochip_device(path))
+		Py_RETURN_TRUE;
+
+	Py_RETURN_FALSE;
+}
+
+static PyMethodDef gpiod_module_methods[] = {
+	{
+		.ml_name = "is_gpiochip_device",
+		.ml_meth = (PyCFunction)gpiod_Module_is_gpiochip_device,
+		.ml_flags = METH_VARARGS,
+		.ml_doc = gpiod_Module_is_gpiochip_device_doc,
+	},
+	{ }
+};
+
 PyDoc_STRVAR(gpiod_Module_doc,
 "Python bindings for libgpiod.\n\
 \n\
@@ -2712,6 +2671,7 @@ static PyModuleDef gpiod_Module = {
 	.m_name = "gpiod",
 	.m_doc = gpiod_Module_doc,
 	.m_size = -1,
+	.m_methods = gpiod_module_methods,
 };
 
 typedef struct {
diff --git a/bindings/python/tests/gpiod_py_test.py b/bindings/python/tests/gpiod_py_test.py
index c490933..f116657 100755
--- a/bindings/python/tests/gpiod_py_test.py
+++ b/bindings/python/tests/gpiod_py_test.py
@@ -79,6 +79,19 @@ def check_kernel(major, minor, release):
 # Chip test cases
 #
 
+class IsGpioDevice(MockupTestCase):
+
+    chip_sizes = ( 8, )
+
+    def test_is_gpiochip_device_good(self):
+        self.assertTrue(gpiod.is_gpiochip_device(mockup.chip_path(0)))
+
+    def test_is_gpiochip_device_bad(self):
+        self.assertFalse(gpiod.is_gpiochip_device('/dev/null'))
+
+    def test_is_gpiochip_device_nonexistent(self):
+        self.assertFalse(gpiod.is_gpiochip_device('/dev/nonexistent_device'))
+
 class ChipOpen(MockupTestCase):
 
     chip_sizes = ( 8, 8, 8 )
@@ -149,8 +162,7 @@ class ChipGetLines(MockupTestCase):
 
     def test_find_single_line_by_name(self):
         with gpiod.Chip(mockup.chip_name(1)) as chip:
-            lines = chip.find_line('gpio-mockup-B-4').to_list()
-            self.assertEqual(len(lines), 1)
+            lines = chip.find_line('gpio-mockup-B-4', unique=True).to_list()
             self.assertEqual(lines[0].offset(), 4)
 
     def test_get_single_line_invalid_offset(self):
@@ -162,7 +174,7 @@ class ChipGetLines(MockupTestCase):
 
     def test_find_single_line_nonexistent(self):
         with gpiod.Chip(mockup.chip_name(1)) as chip:
-            lines = chip.find_line('nonexistent-line')
+            lines = chip.find_line('nonexistent-line', unique=True)
             self.assertEqual(lines, None)
 
     def test_get_multiple_lines_by_offsets_in_tuple(self):
@@ -675,27 +687,6 @@ class LineRequestBehavior(MockupTestCase):
 # Iterator test cases
 #
 
-class ChipIterator(MockupTestCase):
-
-    chip_sizes = ( 4, 8, 16 )
-
-    def test_iterate_over_chips(self):
-        gotA = False
-        gotB = False
-        gotC = False
-
-        for chip in gpiod.ChipIter():
-            if chip.label() == 'gpio-mockup-A':
-                gotA = True
-            elif chip.label() == 'gpio-mockup-B':
-                gotB = True
-            elif chip.label() == 'gpio-mockup-C':
-                gotC = True
-
-        self.assertTrue(gotA)
-        self.assertTrue(gotB)
-        self.assertTrue(gotC)
-
 class LineIterator(MockupTestCase):
 
     chip_sizes = ( 4, )
diff --git a/configure.ac b/configure.ac
index 90a6324..ddb9dc2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -181,6 +181,12 @@ then
 			AC_LANG_POP([C++])
 		])
 	fi
+
+	if test "x$with_examples" = xtrue
+	then
+		# Examples use C++17 features
+		AX_CXX_COMPILE_STDCXX([17], [ext], [mandatory])
+	fi
 fi
 
 AC_ARG_ENABLE([bindings-python],
diff --git a/include/gpiod.h b/include/gpiod.h
index fc50fe8..a7e7348 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -8,6 +8,7 @@
 #ifndef __LIBGPIOD_GPIOD_H__
 #define __LIBGPIOD_GPIOD_H__
 
+#include <dirent.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <time.h>
@@ -27,7 +28,7 @@ extern "C" {
  * users of libgpiod.
  *
  * <p>The API is logically split into several parts such as: GPIO chip & line
- * operators, iterators, GPIO events handling etc.
+ * operators, GPIO events handling etc.
  *
  * <p>General note on error handling: all routines exported by libgpiod  set
  * errno to one of the error values defined in errno.h upon failure. The way
@@ -39,7 +40,6 @@ extern "C" {
 
 struct gpiod_chip;
 struct gpiod_line;
-struct gpiod_chip_iter;
 struct gpiod_line_bulk;
 
 /**
@@ -1053,95 +1053,6 @@ int gpiod_line_event_read_fd_multiple(int fd, struct gpiod_line_event *events,
 /**
  * @}
  *
- * @}
- *
- * @defgroup iterators Iterators for GPIO chips and lines
- * @{
- *
- * These functions and data structures allow easy iterating over GPIO
- * chips and lines.
- */
-
-/**
- * @brief Create a new gpiochip iterator.
- * @return Pointer to a new chip iterator object or NULL if an error occurred.
- *
- * Internally this routine scans the /dev/ directory for GPIO chip device
- * files, opens them and stores their the handles until ::gpiod_chip_iter_free
- * or ::gpiod_chip_iter_free_noclose is called.
- */
-struct gpiod_chip_iter *gpiod_chip_iter_new(void) GPIOD_API;
-
-/**
- * @brief Release all resources allocated for the gpiochip iterator and close
- *        the most recently opened gpiochip (if any).
- * @param iter The gpiochip iterator object.
- */
-void gpiod_chip_iter_free(struct gpiod_chip_iter *iter) GPIOD_API;
-
-/**
- * @brief Release all resources allocated for the gpiochip iterator but
- *        don't close the most recently opened gpiochip (if any).
- * @param iter The gpiochip iterator object.
- *
- * Users may want to break the loop when iterating over gpiochips and keep
- * the most recently opened chip active while freeing the iterator data.
- * This routine enables that.
- */
-void gpiod_chip_iter_free_noclose(struct gpiod_chip_iter *iter) GPIOD_API;
-
-/**
- * @brief Get the next gpiochip handle.
- * @param iter The gpiochip iterator object.
- * @return Pointer to the next open gpiochip handle or NULL if no more chips
- *         are present in the system.
- * @note The previous chip handle will be closed using ::gpiod_chip_iter_free.
- */
-struct gpiod_chip *
-gpiod_chip_iter_next(struct gpiod_chip_iter *iter) GPIOD_API;
-
-/**
- * @brief Get the next gpiochip handle without closing the previous one.
- * @param iter The gpiochip iterator object.
- * @return Pointer to the next open gpiochip handle or NULL if no more chips
- *         are present in the system.
- * @note This function works just like ::gpiod_chip_iter_next but doesn't
- *       close the most recently opened chip handle.
- */
-struct gpiod_chip *
-gpiod_chip_iter_next_noclose(struct gpiod_chip_iter *iter) GPIOD_API;
-
-/**
- * @brief Iterate over all GPIO chips present in the system.
- * @param iter An initialized GPIO chip iterator.
- * @param chip Pointer to a GPIO chip handle. On each iteration the newly
- *             opened chip handle is assigned to this argument.
- *
- * The user must not close the GPIO chip manually - instead the previous chip
- * handle is closed automatically on the next iteration. The last chip to be
- * opened is closed internally by ::gpiod_chip_iter_free.
- */
-#define gpiod_foreach_chip(iter, chip)					\
-	for ((chip) = gpiod_chip_iter_next(iter);			\
-	     (chip);							\
-	     (chip) = gpiod_chip_iter_next(iter))
-
-/**
- * @brief Iterate over all chips present in the system without closing them.
- * @param iter An initialized GPIO chip iterator.
- * @param chip Pointer to a GPIO chip handle. On each iteration the newly
- *             opened chip handle is assigned to this argument.
- *
- * The user must close all the GPIO chips manually after use, until then, the
- * chips remain open. Free the iterator by calling
- * ::gpiod_chip_iter_free_noclose to avoid closing the last chip automatically.
- */
-#define gpiod_foreach_chip_noclose(iter, chip)				\
-	for ((chip) = gpiod_chip_iter_next_noclose(iter);		\
-	     (chip);							\
-	     (chip) = gpiod_chip_iter_next_noclose(iter))
-
-/**
  * @}
  *
  * @defgroup misc Stuff that didn't fit anywhere else
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c5277ce..43ebf76 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -7,7 +7,7 @@
 #
 
 lib_LTLIBRARIES = libgpiod.la
-libgpiod_la_SOURCES = core.c helpers.c iter.c misc.c
+libgpiod_la_SOURCES = core.c helpers.c misc.c
 libgpiod_la_CFLAGS = -Wall -Wextra -g -std=gnu89
 libgpiod_la_CFLAGS += -fvisibility=hidden -I$(top_srcdir)/include/
 libgpiod_la_CFLAGS += -include $(top_builddir)/config.h
diff --git a/lib/iter.c b/lib/iter.c
deleted file mode 100644
index 2ff767c..0000000
--- a/lib/iter.c
+++ /dev/null
@@ -1,123 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-or-later
-/*
- * This file is part of libgpiod.
- *
- * Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
- */
-
-/* GPIO chip and line iterators. */
-
-#include <dirent.h>
-#include <gpiod.h>
-#include <string.h>
-
-struct gpiod_chip_iter {
-	struct gpiod_chip **chips;
-	unsigned int num_chips;
-	unsigned int offset;
-};
-
-static int dir_filter(const struct dirent *dir)
-{
-	return !strncmp(dir->d_name, "gpiochip", 8);
-}
-
-static void free_dirs(struct dirent **dirs, unsigned int num_dirs)
-{
-	unsigned int i;
-
-	for (i = 0; i < num_dirs; i++)
-		free(dirs[i]);
-	free(dirs);
-}
-
-struct gpiod_chip_iter *gpiod_chip_iter_new(void)
-{
-	struct gpiod_chip_iter *iter;
-	struct dirent **dirs;
-	int i, num_chips;
-
-	num_chips = scandir("/dev", &dirs, dir_filter, alphasort);
-	if (num_chips < 0)
-		return NULL;
-
-	iter = malloc(sizeof(*iter));
-	if (!iter)
-		goto err_free_dirs;
-
-	iter->num_chips = num_chips;
-	iter->offset = 0;
-
-	if (num_chips == 0) {
-		iter->chips = NULL;
-		return iter;
-	}
-
-	iter->chips = calloc(num_chips, sizeof(*iter->chips));
-	if (!iter->chips)
-		goto err_free_iter;
-
-	for (i = 0; i < num_chips; i++) {
-		iter->chips[i] = gpiod_chip_open_by_name(dirs[i]->d_name);
-		if (!iter->chips[i])
-			goto err_close_chips;
-	}
-
-	free_dirs(dirs, num_chips);
-
-	return iter;
-
-err_close_chips:
-	for (i = 0; i < num_chips; i++) {
-		if (iter->chips[i])
-			gpiod_chip_close(iter->chips[i]);
-	}
-
-	free(iter->chips);
-
-err_free_iter:
-	free(iter);
-
-err_free_dirs:
-	free_dirs(dirs, num_chips);
-
-	return NULL;
-}
-
-void gpiod_chip_iter_free(struct gpiod_chip_iter *iter)
-{
-	if (iter->offset > 0 && iter->offset < iter->num_chips)
-		gpiod_chip_close(iter->chips[iter->offset - 1]);
-	gpiod_chip_iter_free_noclose(iter);
-}
-
-void gpiod_chip_iter_free_noclose(struct gpiod_chip_iter *iter)
-{
-	unsigned int i;
-
-	for (i = iter->offset; i < iter->num_chips; i++) {
-		if (iter->chips[i])
-			gpiod_chip_close(iter->chips[i]);
-	}
-
-	if (iter->chips)
-		free(iter->chips);
-
-	free(iter);
-}
-
-struct gpiod_chip *gpiod_chip_iter_next(struct gpiod_chip_iter *iter)
-{
-	if (iter->offset > 0) {
-		gpiod_chip_close(iter->chips[iter->offset - 1]);
-		iter->chips[iter->offset - 1] = NULL;
-	}
-
-	return gpiod_chip_iter_next_noclose(iter);
-}
-
-struct gpiod_chip *gpiod_chip_iter_next_noclose(struct gpiod_chip_iter *iter)
-{
-	return iter->offset < (iter->num_chips)
-					? iter->chips[iter->offset++] : NULL;
-}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2d3b959..91798f7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -25,6 +25,5 @@ gpiod_test_SOURCES =			\
 		tests-bulk.c		\
 		tests-chip.c		\
 		tests-event.c		\
-		tests-iter.c		\
 		tests-line.c		\
 		tests-misc.c
diff --git a/tests/gpiod-test.h b/tests/gpiod-test.h
index df9f0c7..7ed4d23 100644
--- a/tests/gpiod-test.h
+++ b/tests/gpiod-test.h
@@ -25,11 +25,9 @@
  */
 typedef struct gpiod_chip gpiod_chip_struct;
 typedef struct gpiod_line_bulk gpiod_line_bulk_struct;
-typedef struct gpiod_chip_iter gpiod_chip_iter_struct;
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_struct, gpiod_chip_close);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_bulk_struct, gpiod_line_bulk_free);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_iter_struct, gpiod_chip_iter_free);
 
 /* These are private definitions and should not be used directly. */
 typedef void (*_gpiod_test_func)(void);
diff --git a/tests/tests-iter.c b/tests/tests-iter.c
deleted file mode 100644
index 163a820..0000000
--- a/tests/tests-iter.c
+++ /dev/null
@@ -1,100 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-or-later
-/*
- * This file is part of libgpiod.
- *
- * Copyright (C) 2019 Bartosz Golaszewski <bgolaszewski@baylibre.com>
- */
-
-#include <string.h>
-
-#include "gpiod-test.h"
-
-#define GPIOD_TEST_GROUP "iter"
-
-GPIOD_TEST_CASE(chip_iter, 0, { 8, 8, 8 })
-{
-	g_autoptr(gpiod_chip_iter_struct) iter = NULL;
-	struct gpiod_chip *chip;
-	gboolean A, B, C;
-
-	A = B = C = FALSE;
-
-	iter = gpiod_chip_iter_new();
-	g_assert_nonnull(iter);
-	gpiod_test_return_if_failed();
-
-	gpiod_foreach_chip(iter, chip) {
-		if (strcmp(gpiod_chip_label(chip), "gpio-mockup-A") == 0)
-			A = TRUE;
-		else if (strcmp(gpiod_chip_label(chip), "gpio-mockup-B") == 0)
-			B = TRUE;
-		else if (strcmp(gpiod_chip_label(chip), "gpio-mockup-C") == 0)
-			C = TRUE;
-	}
-
-	g_assert_true(A);
-	g_assert_true(B);
-	g_assert_true(C);
-}
-
-GPIOD_TEST_CASE(chip_iter_no_close, 0, { 8, 8, 8 })
-{
-	g_autoptr(gpiod_chip_iter_struct) iter = NULL;
-	g_autoptr(gpiod_chip_struct) chipA = NULL;
-	g_autoptr(gpiod_chip_struct) chipB = NULL;
-	g_autoptr(gpiod_chip_struct) chipC = NULL;
-	struct gpiod_chip *chip;
-
-	iter = gpiod_chip_iter_new();
-	g_assert_nonnull(iter);
-	gpiod_test_return_if_failed();
-
-	gpiod_foreach_chip_noclose(iter, chip) {
-		if (strcmp(gpiod_chip_label(chip), "gpio-mockup-A") == 0)
-			chipA = chip;
-		else if (strcmp(gpiod_chip_label(chip), "gpio-mockup-B") == 0)
-			chipB = chip;
-		else if (strcmp(gpiod_chip_label(chip), "gpio-mockup-C") == 0)
-			chipC = chip;
-		else
-			gpiod_chip_close(chip);
-	}
-
-	g_assert_nonnull(chipA);
-	g_assert_nonnull(chipB);
-	g_assert_nonnull(chipC);
-
-	gpiod_chip_iter_free_noclose(iter);
-	iter = NULL;
-
-	/* See if the chips are still open and usable. */
-	g_assert_cmpstr(gpiod_chip_label(chipA), ==, "gpio-mockup-A");
-	g_assert_cmpstr(gpiod_chip_label(chipB), ==, "gpio-mockup-B");
-	g_assert_cmpstr(gpiod_chip_label(chipC), ==, "gpio-mockup-C");
-}
-
-GPIOD_TEST_CASE(chip_iter_break, 0, { 8, 8, 8, 8, 8 })
-{
-	g_autoptr(gpiod_chip_iter_struct) iter = NULL;
-	struct gpiod_chip *chip;
-	guint i = 0;
-
-	iter = gpiod_chip_iter_new();
-	g_assert_nonnull(iter);
-	gpiod_test_return_if_failed();
-
-	gpiod_foreach_chip(iter, chip) {
-		if ((strcmp(gpiod_chip_label(chip), "gpio-mockup-A") == 0) ||
-		    (strcmp(gpiod_chip_label(chip), "gpio-mockup-B") == 0) ||
-		    (strcmp(gpiod_chip_label(chip), "gpio-mockup-C") == 0))
-			i++;
-
-		if (i == 3)
-			break;
-	}
-
-	gpiod_chip_iter_free(iter);
-	iter = NULL;
-
-	g_assert_cmpuint(i, ==, 3);
-}
diff --git a/tools/gpiodetect.c b/tools/gpiodetect.c
index 1c992a4..8e067f7 100644
--- a/tools/gpiodetect.c
+++ b/tools/gpiodetect.c
@@ -5,6 +5,8 @@
  * Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
  */
 
+#include <dirent.h>
+#include <errno.h>
 #include <getopt.h>
 #include <gpiod.h>
 #include <stdio.h>
@@ -33,9 +35,9 @@ static void print_help(void)
 
 int main(int argc, char **argv)
 {
-	struct gpiod_chip_iter *iter;
+	int optc, opti, num_chips, i;
 	struct gpiod_chip *chip;
-	int optc, opti;
+	struct dirent **entries;
 
 	for (;;) {
 		optc = getopt_long(argc, argv, shortopts, longopts, &opti);
@@ -62,18 +64,31 @@ int main(int argc, char **argv)
 	if (argc > 0)
 		die("unrecognized argument: %s", argv[0]);
 
-	iter = gpiod_chip_iter_new();
-	if (!iter)
-		die_perror("unable to access GPIO chips");
+	num_chips = scandir("/dev/", &entries, chip_dir_filter, alphasort);
+	if (num_chips < 0)
+		die_perror("unable to scan /dev");
+
+	for (i = 0; i < num_chips; i++) {
+		chip = gpiod_chip_open_by_name(entries[i]->d_name);
+		if (!chip) {
+			if (errno == EACCES)
+				printf("%s Permission denied\n",
+				       entries[i]->d_name);
+			else
+				die_perror("unable to open %s",
+					   entries[i]->d_name);
+		}
 
-	gpiod_foreach_chip(iter, chip) {
 		printf("%s [%s] (%u lines)\n",
 		       gpiod_chip_name(chip),
 		       gpiod_chip_label(chip),
 		       gpiod_chip_num_lines(chip));
+
+		gpiod_chip_close(chip);
+		free(entries[i]);
 	}
 
-	gpiod_chip_iter_free(iter);
+	free(entries);
 
 	return EXIT_SUCCESS;
 }
diff --git a/tools/gpiofind.c b/tools/gpiofind.c
index ffb8fc0..4acf621 100644
--- a/tools/gpiofind.c
+++ b/tools/gpiofind.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
  */
 
+#include <dirent.h>
 #include <errno.h>
 #include <getopt.h>
 #include <gpiod.h>
@@ -34,10 +35,10 @@ static void print_help(void)
 
 int main(int argc, char **argv)
 {
-	struct gpiod_chip_iter *iter;
+	int i, num_chips, optc, opti;
 	struct gpiod_chip *chip;
 	struct gpiod_line *line;
-	int optc, opti;
+	struct dirent **entries;
 
 	for (;;) {
 		optc = getopt_long(argc, argv, shortopts, longopts, &opti);
@@ -64,23 +65,27 @@ int main(int argc, char **argv)
 	if (argc != 1)
 		die("exactly one GPIO line name must be specified");
 
-	iter = gpiod_chip_iter_new();
-	if (!iter)
-		die_perror("unable to access GPIO chips");
+	num_chips = scandir("/dev/", &entries, chip_dir_filter, alphasort);
+	if (num_chips < 0)
+		die_perror("unable to scan /dev");
+
+	for (i = 0; i < num_chips; i++) {
+		chip = gpiod_chip_open_by_name(entries[i]->d_name);
+		if (!chip) {
+			if (errno == EACCES)
+				continue;
+
+			die_perror("unable to open %s", entries[i]->d_name);
+		}
 
-	gpiod_foreach_chip(iter, chip) {
 		line = gpiod_chip_find_line_unique(chip, argv[0]);
 		if (line) {
 			printf("%s %u\n",
 			       gpiod_chip_name(chip), gpiod_line_offset(line));
-			gpiod_chip_iter_free(iter);
+			gpiod_chip_close(chip);
 			return EXIT_SUCCESS;
 		}
-
-		if (errno != ENOENT)
-			die_perror("error performing the line lookup");
 	}
 
-	gpiod_chip_iter_free(iter);
 	return EXIT_FAILURE;
 }
diff --git a/tools/gpioinfo.c b/tools/gpioinfo.c
index dd4a388..e3dbde7 100644
--- a/tools/gpioinfo.c
+++ b/tools/gpioinfo.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
  */
 
+#include <dirent.h>
 #include <errno.h>
 #include <getopt.h>
 #include <gpiod.h>
@@ -180,9 +181,9 @@ static void list_lines(struct gpiod_chip *chip)
 
 int main(int argc, char **argv)
 {
-	struct gpiod_chip_iter *chip_iter;
+	int num_chips, i, optc, opti;
 	struct gpiod_chip *chip;
-	int i, optc, opti;
+	struct dirent **entries;
 
 	for (;;) {
 		optc = getopt_long(argc, argv, shortopts, longopts, &opti);
@@ -207,14 +208,26 @@ int main(int argc, char **argv)
 	argv += optind;
 
 	if (argc == 0) {
-		chip_iter = gpiod_chip_iter_new();
-		if (!chip_iter)
-			die_perror("error accessing GPIO chips");
+		num_chips = scandir("/dev/", &entries,
+				    chip_dir_filter, alphasort);
+		if (num_chips < 0)
+			die_perror("unable to scan /dev");
+
+		for (i = 0; i < num_chips; i++) {
+			chip = gpiod_chip_open_by_name(entries[i]->d_name);
+			if (!chip) {
+				if (errno == EACCES)
+					printf("%s Permission denied\n",
+					       entries[i]->d_name);
+				else
+					die_perror("unable to open %s",
+						   entries[i]->d_name);
+			}
 
-		gpiod_foreach_chip(chip_iter, chip)
 			list_lines(chip);
 
-		gpiod_chip_iter_free(chip_iter);
+			gpiod_chip_close(chip);
+		}
 	} else {
 		for (i = 0; i < argc; i++) {
 			chip = gpiod_chip_open_lookup(argv[i]);
diff --git a/tools/tools-common.c b/tools/tools-common.c
index af05102..b64ef93 100644
--- a/tools/tools-common.c
+++ b/tools/tools-common.c
@@ -101,3 +101,18 @@ int make_signalfd(void)
 
 	return sigfd;
 }
+
+int chip_dir_filter(const struct dirent *entry)
+{
+	bool is_chip;
+	char *path;
+	int ret;
+
+	ret = asprintf(&path, "/dev/%s", entry->d_name);
+	if (ret < 0)
+		return 0;
+
+	is_chip = gpiod_is_gpiochip_device(path);
+	free(path);
+	return !!is_chip;
+}
diff --git a/tools/tools-common.h b/tools/tools-common.h
index 8ccde62..4148dd8 100644
--- a/tools/tools-common.h
+++ b/tools/tools-common.h
@@ -8,6 +8,8 @@
 #ifndef __GPIOD_TOOLS_COMMON_H__
 #define __GPIOD_TOOLS_COMMON_H__
 
+#include <dirent.h>
+
 /*
  * Various helpers for the GPIO tools.
  *
@@ -29,5 +31,6 @@ void print_version(void);
 int bias_flags(const char *option);
 void print_bias_help(void);
 int make_signalfd(void);
+int chip_dir_filter(const struct dirent *entry);
 
 #endif /* __GPIOD_TOOLS_COMMON_H__ */
-- 
2.29.1


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

* Re: [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0
  2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
                   ` (13 preceding siblings ...)
  2020-12-10 13:23 ` [libgpiod][PATCH 14/14] core: kill chip iterators Bartosz Golaszewski
@ 2020-12-10 13:56 ` Andy Shevchenko
  2020-12-11  8:38   ` Bartosz Golaszewski
  2020-12-14 15:02   ` Bartosz Golaszewski
  14 siblings, 2 replies; 22+ messages in thread
From: Andy Shevchenko @ 2020-12-10 13:56 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Kent Gibson, Geert Uytterhoeven, Jack Winch, Helmut Grohne,
	Linus Walleij, linux-gpio, Bartosz Golaszewski

On Thu, Dec 10, 2020 at 02:23:01PM +0100, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> 
> The following series removes a lot of interfaces that were deemed overkill
> in libgpiod and the removal of which was suggested to me before proceeding
> with the new API.
> 
> This leaves a couple holes in the library but we'll follow them up with
> more improvements all over the tree. We'll create a new object called
> gpiod_request for dealing with line requests of arbitrary size. We'll
> probably remove the the bulk objects from bindings and eventually we'll
> switch to using the v2 kernel uAPI.
> 
> Andy - a note for you: I know you're always very thorough in your reviews
> but in this case let's consider this series preparing a construction zone
> for the new API. Please don't nitpick too much. :)

I don't know what you are talking about. The series looks nice, esp. taking
into account statistics! FWIW,

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

One side note, though. Are you already plan to support autotools-2.70?

> Bartosz Golaszewski (14):
>   bindings: cxx: check for error from gpiod_line_bulk_new()
>   build: drop the message about tests having been built successfully
>   core: export gpiod_is_gpiochip_device()
>   bulk: drop the limit on the max number of lines
>   core: drop line iterators
>   treewide: kill opening chips by label
>   API: move gpiod_line_get_chip() to line attributes section
>   core: kill gpiod_line_close_chip()
>   core: kill gpiod_line_get()
>   treewide: kill global line lookup
>   treewide: kill find_lines()
>   core: rework gpiod_chip_find_line()
>   build: add a configure switch for building examples
>   core: kill chip iterators
> 
>  bindings/cxx/Makefile.am                |   8 +-
>  bindings/cxx/chip.cpp                   |  47 +--
>  bindings/cxx/examples/Makefile.am       |   4 +-
>  bindings/cxx/examples/gpiodetectcxx.cpp |  13 +-
>  bindings/cxx/examples/gpiofindcxx.cpp   |  18 +-
>  bindings/cxx/examples/gpioinfocxx.cpp   |  43 ++-
>  bindings/cxx/gpiod.hpp                  | 147 +-------
>  bindings/cxx/iter.cpp                   |  95 +----
>  bindings/cxx/line.cpp                   |  15 -
>  bindings/cxx/line_bulk.cpp              |  24 +-
>  bindings/cxx/tests/tests-chip.cpp       |  62 ++--
>  bindings/cxx/tests/tests-iter.cpp       |  37 --
>  bindings/cxx/tests/tests-line.cpp       |  19 -
>  bindings/python/Makefile.am             |  10 +-
>  bindings/python/examples/gpiodetect.py  |  12 +-
>  bindings/python/examples/gpiofind.py    |  15 +-
>  bindings/python/examples/gpioinfo.py    |  33 +-
>  bindings/python/gpiodmodule.c           | 473 +++++++-----------------
>  bindings/python/tests/gpiod_py_test.py  | 100 +----
>  configure.ac                            |  12 +
>  include/gpiod.h                         | 258 ++-----------
>  lib/Makefile.am                         |   2 +-
>  lib/core.c                              |  12 +-
>  lib/helpers.c                           | 176 +++------
>  lib/iter.c                              | 171 ---------
>  tests/Makefile.am                       |  13 -
>  tests/gpiod-test.h                      |   4 -
>  tests/tests-bulk.c                      |   9 -
>  tests/tests-chip.c                      |  97 +----
>  tests/tests-iter.c                      | 123 ------
>  tests/tests-line.c                      |  52 ---
>  tools/gpiodetect.c                      |  29 +-
>  tools/gpiofind.c                        |  34 +-
>  tools/gpioinfo.c                        |  41 +-
>  tools/gpiomon.c                         |   5 +-
>  tools/tools-common.c                    |  15 +
>  tools/tools-common.h                    |   3 +
>  37 files changed, 557 insertions(+), 1674 deletions(-)
>  delete mode 100644 lib/iter.c
>  delete mode 100644 tests/tests-iter.c
> 
> -- 
> 2.29.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0
  2020-12-10 13:56 ` [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Andy Shevchenko
@ 2020-12-11  8:38   ` Bartosz Golaszewski
  2020-12-11 14:31     ` Andy Shevchenko
  2020-12-14 15:02   ` Bartosz Golaszewski
  1 sibling, 1 reply; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-11  8:38 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Kent Gibson, Geert Uytterhoeven, Jack Winch, Helmut Grohne,
	Linus Walleij, open list:GPIO SUBSYSTEM, Bartosz Golaszewski

On Thu, Dec 10, 2020 at 2:55 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> On Thu, Dec 10, 2020 at 02:23:01PM +0100, Bartosz Golaszewski wrote:
> > From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> >
> > The following series removes a lot of interfaces that were deemed overkill
> > in libgpiod and the removal of which was suggested to me before proceeding
> > with the new API.
> >
> > This leaves a couple holes in the library but we'll follow them up with
> > more improvements all over the tree. We'll create a new object called
> > gpiod_request for dealing with line requests of arbitrary size. We'll
> > probably remove the the bulk objects from bindings and eventually we'll
> > switch to using the v2 kernel uAPI.
> >
> > Andy - a note for you: I know you're always very thorough in your reviews
> > but in this case let's consider this series preparing a construction zone
> > for the new API. Please don't nitpick too much. :)
>
> I don't know what you are talking about. The series looks nice, esp. taking
> into account statistics! FWIW,
>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>
> One side note, though. Are you already plan to support autotools-2.70?
>

Isn't it already supported? 2.69 is the minimum version, 2.70 should just work.

Bartosz

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

* Re: [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0
  2020-12-11  8:38   ` Bartosz Golaszewski
@ 2020-12-11 14:31     ` Andy Shevchenko
  2020-12-11 14:33       ` Bartosz Golaszewski
  0 siblings, 1 reply; 22+ messages in thread
From: Andy Shevchenko @ 2020-12-11 14:31 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Kent Gibson, Geert Uytterhoeven, Jack Winch, Helmut Grohne,
	Linus Walleij, open list:GPIO SUBSYSTEM, Bartosz Golaszewski

On Fri, Dec 11, 2020 at 09:38:44AM +0100, Bartosz Golaszewski wrote:
> On Thu, Dec 10, 2020 at 2:55 PM Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:
> >
> > On Thu, Dec 10, 2020 at 02:23:01PM +0100, Bartosz Golaszewski wrote:
> > > From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> > >
> > > The following series removes a lot of interfaces that were deemed overkill
> > > in libgpiod and the removal of which was suggested to me before proceeding
> > > with the new API.
> > >
> > > This leaves a couple holes in the library but we'll follow them up with
> > > more improvements all over the tree. We'll create a new object called
> > > gpiod_request for dealing with line requests of arbitrary size. We'll
> > > probably remove the the bulk objects from bindings and eventually we'll
> > > switch to using the v2 kernel uAPI.
> > >
> > > Andy - a note for you: I know you're always very thorough in your reviews
> > > but in this case let's consider this series preparing a construction zone
> > > for the new API. Please don't nitpick too much. :)
> >
> > I don't know what you are talking about. The series looks nice, esp. taking
> > into account statistics! FWIW,
> >
> > Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> >
> > One side note, though. Are you already plan to support autotools-2.70?
> >
> 
> Isn't it already supported? 2.69 is the minimum version, 2.70 should just work.

Have you read an article on LWN about changes [1]? There are a lot of
incompatibilities (note between 2.69 and 2.70 _8_ years passed).

[1]: https://lwn.net/Articles/839395/

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0
  2020-12-11 14:31     ` Andy Shevchenko
@ 2020-12-11 14:33       ` Bartosz Golaszewski
  2020-12-11 14:58         ` Andy Shevchenko
  0 siblings, 1 reply; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-11 14:33 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Kent Gibson, Geert Uytterhoeven, Jack Winch, Helmut Grohne,
	Linus Walleij, open list:GPIO SUBSYSTEM, Bartosz Golaszewski

On Fri, Dec 11, 2020 at 3:30 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> On Fri, Dec 11, 2020 at 09:38:44AM +0100, Bartosz Golaszewski wrote:
> > On Thu, Dec 10, 2020 at 2:55 PM Andy Shevchenko
> > <andriy.shevchenko@linux.intel.com> wrote:
> > >
> > > On Thu, Dec 10, 2020 at 02:23:01PM +0100, Bartosz Golaszewski wrote:
> > > > From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> > > >
> > > > The following series removes a lot of interfaces that were deemed overkill
> > > > in libgpiod and the removal of which was suggested to me before proceeding
> > > > with the new API.
> > > >
> > > > This leaves a couple holes in the library but we'll follow them up with
> > > > more improvements all over the tree. We'll create a new object called
> > > > gpiod_request for dealing with line requests of arbitrary size. We'll
> > > > probably remove the the bulk objects from bindings and eventually we'll
> > > > switch to using the v2 kernel uAPI.
> > > >
> > > > Andy - a note for you: I know you're always very thorough in your reviews
> > > > but in this case let's consider this series preparing a construction zone
> > > > for the new API. Please don't nitpick too much. :)
> > >
> > > I don't know what you are talking about. The series looks nice, esp. taking
> > > into account statistics! FWIW,
> > >
> > > Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > >
> > > One side note, though. Are you already plan to support autotools-2.70?
> > >
> >
> > Isn't it already supported? 2.69 is the minimum version, 2.70 should just work.
>
> Have you read an article on LWN about changes [1]? There are a lot of
> incompatibilities (note between 2.69 and 2.70 _8_ years passed).
>
> [1]: https://lwn.net/Articles/839395/
>
> --
> With Best Regards,
> Andy Shevchenko
>
>

How will distros handle the incompatibilities? I don't think all
projects - many no longer even supported - will suddenly switch to new
autoconf.

Bartosz

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

* Re: [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0
  2020-12-11 14:33       ` Bartosz Golaszewski
@ 2020-12-11 14:58         ` Andy Shevchenko
  2020-12-11 15:06           ` Bartosz Golaszewski
  0 siblings, 1 reply; 22+ messages in thread
From: Andy Shevchenko @ 2020-12-11 14:58 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Kent Gibson, Geert Uytterhoeven, Jack Winch, Helmut Grohne,
	Linus Walleij, open list:GPIO SUBSYSTEM, Bartosz Golaszewski

On Fri, Dec 11, 2020 at 03:33:41PM +0100, Bartosz Golaszewski wrote:
> On Fri, Dec 11, 2020 at 3:30 PM Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:
> > On Fri, Dec 11, 2020 at 09:38:44AM +0100, Bartosz Golaszewski wrote:
> > > On Thu, Dec 10, 2020 at 2:55 PM Andy Shevchenko
> > > <andriy.shevchenko@linux.intel.com> wrote:
> > > > On Thu, Dec 10, 2020 at 02:23:01PM +0100, Bartosz Golaszewski wrote:

...

> > > > One side note, though. Are you already plan to support autotools-2.70?
> > >
> > > Isn't it already supported? 2.69 is the minimum version, 2.70 should just work.
> >
> > Have you read an article on LWN about changes [1]? There are a lot of
> > incompatibilities (note between 2.69 and 2.70 _8_ years passed).
> >
> > [1]: https://lwn.net/Articles/839395/
> 
> How will distros handle the incompatibilities? I don't think all
> projects - many no longer even supported - will suddenly switch to new
> autoconf.

It's PITA for distributions. Last time I remember that nice jump from 2.13 to 2.50.
However, 2.69 should be closer to 2.70. I believe the distributions will patch
all broken packages one-by-one. I think there is no need to keep two autoconf
packages together in this case, but who knows, it might be a last resort.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0
  2020-12-11 14:58         ` Andy Shevchenko
@ 2020-12-11 15:06           ` Bartosz Golaszewski
  0 siblings, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-11 15:06 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Kent Gibson, Geert Uytterhoeven, Jack Winch, Helmut Grohne,
	Linus Walleij, open list:GPIO SUBSYSTEM, Bartosz Golaszewski

On Fri, Dec 11, 2020 at 3:57 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> On Fri, Dec 11, 2020 at 03:33:41PM +0100, Bartosz Golaszewski wrote:
> > On Fri, Dec 11, 2020 at 3:30 PM Andy Shevchenko
> > <andriy.shevchenko@linux.intel.com> wrote:
> > > On Fri, Dec 11, 2020 at 09:38:44AM +0100, Bartosz Golaszewski wrote:
> > > > On Thu, Dec 10, 2020 at 2:55 PM Andy Shevchenko
> > > > <andriy.shevchenko@linux.intel.com> wrote:
> > > > > On Thu, Dec 10, 2020 at 02:23:01PM +0100, Bartosz Golaszewski wrote:
>
> ...
>
> > > > > One side note, though. Are you already plan to support autotools-2.70?
> > > >
> > > > Isn't it already supported? 2.69 is the minimum version, 2.70 should just work.
> > >
> > > Have you read an article on LWN about changes [1]? There are a lot of
> > > incompatibilities (note between 2.69 and 2.70 _8_ years passed).
> > >
> > > [1]: https://lwn.net/Articles/839395/
> >
> > How will distros handle the incompatibilities? I don't think all
> > projects - many no longer even supported - will suddenly switch to new
> > autoconf.
>
> It's PITA for distributions. Last time I remember that nice jump from 2.13 to 2.50.
> However, 2.69 should be closer to 2.70. I believe the distributions will patch
> all broken packages one-by-one. I think there is no need to keep two autoconf
> packages together in this case, but who knows, it might be a last resort.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>

Ok, so responding to your question: I'll upgrade to 2.70 once it's necessary. :)

Bart

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

* Re: [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0
  2020-12-10 13:56 ` [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Andy Shevchenko
  2020-12-11  8:38   ` Bartosz Golaszewski
@ 2020-12-14 15:02   ` Bartosz Golaszewski
  1 sibling, 0 replies; 22+ messages in thread
From: Bartosz Golaszewski @ 2020-12-14 15:02 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Kent Gibson, Geert Uytterhoeven, Jack Winch, Helmut Grohne,
	Linus Walleij, open list:GPIO SUBSYSTEM, Bartosz Golaszewski

On Thu, Dec 10, 2020 at 2:55 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> On Thu, Dec 10, 2020 at 02:23:01PM +0100, Bartosz Golaszewski wrote:
> > From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> >
> > The following series removes a lot of interfaces that were deemed overkill
> > in libgpiod and the removal of which was suggested to me before proceeding
> > with the new API.
> >
> > This leaves a couple holes in the library but we'll follow them up with
> > more improvements all over the tree. We'll create a new object called
> > gpiod_request for dealing with line requests of arbitrary size. We'll
> > probably remove the the bulk objects from bindings and eventually we'll
> > switch to using the v2 kernel uAPI.
> >
> > Andy - a note for you: I know you're always very thorough in your reviews
> > but in this case let's consider this series preparing a construction zone
> > for the new API. Please don't nitpick too much. :)
>
> I don't know what you are talking about. The series looks nice, esp. taking
> into account statistics! FWIW,
>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>

I applied the series so that we can move on. Since we're now getting
per-chip unique lines, we'll probably have to redesign line lookup
again but that's alright.

Bartosz

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

end of thread, other threads:[~2020-12-14 15:03 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 01/14] bindings: cxx: check for error from gpiod_line_bulk_new() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 02/14] build: drop the message about tests having been built successfully Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 03/14] core: export gpiod_is_gpiochip_device() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 04/14] bulk: drop the limit on the max number of lines Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 05/14] core: drop line iterators Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 06/14] treewide: kill opening chips by label Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 07/14] API: move gpiod_line_get_chip() to line attributes section Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 08/14] core: kill gpiod_line_close_chip() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 09/14] core: kill gpiod_line_get() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 10/14] treewide: kill global line lookup Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 11/14] treewide: kill find_lines() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 12/14] core: rework gpiod_chip_find_line() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 13/14] build: add a configure switch for building examples Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 14/14] core: kill chip iterators Bartosz Golaszewski
2020-12-10 13:56 ` [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Andy Shevchenko
2020-12-11  8:38   ` Bartosz Golaszewski
2020-12-11 14:31     ` Andy Shevchenko
2020-12-11 14:33       ` Bartosz Golaszewski
2020-12-11 14:58         ` Andy Shevchenko
2020-12-11 15:06           ` Bartosz Golaszewski
2020-12-14 15:02   ` Bartosz Golaszewski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.