core: add gpiod_request_lines
Subsystems (2)
v2 cover core: add gpiod_request_lines
In my review of the CXX bindings I suggested a top-level version of Chip.request_lines(), and possibly a C API version as well, so here is the C version, plus a couple of semi-related tweaks I made along the way.
The first patch adds the gpiod_request_lines().
Patch 3 migrates the appropriate tools.
Patch 4 minimizes the lifetimes of objects in the tools as I've previously seen confusion over how long lived objects need to be. Patch 2 is just a rename cos "inexistent" looks weird to me. Strictly speaking it is fine, but unless there is a problem with using "nonexistent" I would go with the latter.
This series may be require my unsigned values patch.
Cheers,
Kent.
Kent Gibson (4):
core: add gpiod_request_lines
tools: rename inexistent to nonexistent
tools: migrate to gpiod_request_lines
tools: minimize object lifetimes
include/gpiod.h | 15 ++++++++ lib/line-request.c | 17 +++++++++ tests/tests-line-request.c | 73 ++++++++++++++++++++++++++++++++++++++ tools/gpio-tools-test.bats | 4 +-- tools/gpiodetect.c | 2 +- tools/gpiofind.c | 2 +- tools/gpioget.c | 25 +++++++------ tools/gpioinfo.c | 4 +-- tools/gpiomon.c | 16 ++++----- tools/gpioset.c | 18 +++++----- tools/tools-common.c | 50 ++++++++++---------------- tools/tools-common.h | 5 +-- 12 files changed, 164 insertions(+), 67 deletions(-)
Signature · 1 line
2.35.1
PATCH v2 1/4 core: add gpiod_request_lines
Add a wrapper around gpiod_chip_open() and gpiod_chip_request_lines() for the common use case of only requesting a single set of lines from a chip. The chip itself is only required for the request so hide it from the user.
--- include/gpiod.h | 15 ++++++++ lib/line-request.c | 17 +++++++++ tests/tests-line-request.c | 73 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+)
include/gpiod.h +15 -0
@@ -50,6 +50,21 @@ struct gpiod_info_event;struct gpiod_edge_event ;struct gpiod_edge_event_buffer ; +/** +* @brief Request a set of lines for exclusive usage. +* @param path GPIO chip path. +* @param req_cfg Request config object. +* @param line_cfg Line config object. +* @return New line request object or NULL if an error occurred. The request +* must be released by the caller using ::gpiod_line_request_release. +* @note Line configuration overrides for lines that are not requested are +* silently ignored. +*/ +struct gpiod_line_request * +gpiod_request_lines (const char *path, +struct gpiod_request_config *req_cfg, +struct gpiod_line_config *line_cfg); +/** * @defgroup chips GPIO chips * @{
lib/line-request.c +17 -0
@@ -16,6 +16,23 @@ struct gpiod_line_request {int fd; }; +GPIOD_API struct gpiod_line_request * +gpiod_request_lines (const char *path, +struct gpiod_request_config *req_cfg, +struct gpiod_line_config *line_cfg) +{ +struct gpiod_chip *chip; +struct gpiod_line_request *request; + + chip =gpiod_chip_open (path); +if (chip ==NULL ) +return NULL ; + + request =gpiod_chip_request_lines (chip, req_cfg, line_cfg); +gpiod_chip_close (chip); +return request; +} +struct gpiod_line_request *gpiod_line_request_from_uapi (struct gpio_v2_line_request *uapi_req) {
tests/tests-line-request.c +73 -0
79 lines not on this page · raw message
Signature · 1 line
2.35.1
PATCH v2 2/4 tools: rename inexistent to nonexistent
In reply to Kent GibsonThe use of inexistent is virtually nonexistent, so switch to the more usual form.
--- tools/gpio-tools-test.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/gpio-tools-test.bats +2 -2
@@ -309,8 +309,8 @@ teardown() { assert_fail output_regex_match "\\s+line\\s+7:\\s+unnamed\\s+unused\\s+input\\s+active-high" } -@test "gpioinfo: inexistent chip" { - run_tool gpioinfo "inexistent" +@test "gpioinfo: nonexistent chip" { + run_tool gpioinfo "nonexistent" test "$status" -eq 1 }
Signature · 1 line
2.35.1
PATCH v2 3/4 tools: migrate to gpiod_request_lines
In reply to Kent GibsonSwitch to gpiod_request_lines() for tools that only use the chip to request lines.
--- tools/gpiodetect.c | 2 +- tools/gpiofind.c | 2 +- tools/gpioget.c | 11 +++++----- tools/gpioinfo.c | 4 ++-- tools/gpiomon.c | 11 +++++----- tools/gpioset.c | 11 +++++----- tools/tools-common.c | 50 +++++++++++++++++--------------------------- tools/tools-common.h | 5 +++-- 8 files changed, 41 insertions(+), 55 deletions(-)
tools/gpiodetect.c +1 -1
@@ -67,7 +67,7 @@ int main(int argc, char **argv)die_perror ("unable to scan /dev" );for (i =0 ; i < num_chips; i++) { - chip =chip_open_by_name (entries[i]->d_name); + chip =chip_open (chip_path_from_name (entries[i]->d_name));if (!chip)die_perror ("unable to open %s" , entries[i]->d_name);
tools/gpiofind.c +1 -1
@@ -67,7 +67,7 @@ int main(int argc, char **argv)die_perror ("unable to scan /dev" );for (i =0 ; i < num_chips; i++) { - chip =chip_open_by_name (entries[i]->d_name); + chip =chip_open (chip_path_from_name (entries[i]->d_name));if (!chip) {if (errno ==EACCES )continue ;
tools/gpioget.c +5 -6
@@ -46,11 +46,10 @@ int main(int argc, char **argv)struct gpiod_request_config *req_cfg;struct gpiod_line_request *request;struct gpiod_line_config *line_cfg; -struct gpiod_chip *chip;bool active_low = false;unsigned int *offsets, *values;size_t i, num_lines; -char *device, *end; +char *device, *end, *path;for (;;) { optc =getopt_long (argc, argv, shortopts, longopts, &opti);
@@ -103,8 +102,8 @@ int main(int argc, char **argv)die ("invalid GPIO offset: %s" , argv[i +1 ]); } - chip =chip_open_lookup (device); -if (!chip) + path =chip_path_lookup (device); +if (!path)die_perror ("unable to open %s" , device); line_cfg =gpiod_line_config_new ();
@@ -126,7 +125,7 @@ int main(int argc, char **argv)gpiod_request_config_set_consumer (req_cfg,"gpioget" );gpiod_request_config_set_offsets (req_cfg, num_lines, offsets); - request =gpiod_chip_request_lines (chip, req_cfg, line_cfg); + request =gpiod_request_lines (path, req_cfg, line_cfg);if (!request)die_perror ("unable to request lines" );
@@ -144,7 +143,7 @@ int main(int argc, char **argv)gpiod_line_request_release (request);gpiod_request_config_free (req_cfg);gpiod_line_config_free (line_cfg); -gpiod_chip_close (chip); +free (path);free (offsets);free (values);
tools/gpioinfo.c +2 -2
@@ -227,7 +227,7 @@ int main(int argc, char **argv)die_perror ("unable to scan /dev" );for (i =0 ; i < num_chips; i++) { - chip =chip_open_by_name (entries[i]->d_name); + chip =chip_open (chip_path_from_name (entries[i]->d_name));if (!chip)die_perror ("unable to open %s" , entries[i]->d_name);
@@ -240,7 +240,7 @@ int main(int argc, char **argv)free (entries); }else {for (i =0 ; i < argc; i++) { - chip =chip_open_lookup (argv[i]); + chip =chip_open (chip_path_lookup (argv[i]));if (!chip)die_perror ("looking up chip %s" , argv[i]);
tools/gpiomon.c +5 -6
@@ -164,9 +164,8 @@ int main(int argc, char **argv)struct gpiod_line_config *line_cfg;unsigned int offsets[64 ], offset;struct gpiod_edge_event *event; -struct gpiod_chip *chip;struct mon_ctx ctx; -char *end; +char *end, *path;/* * FIXME: use signalfd once the API has been converted to using a single file
@@ -250,8 +249,8 @@ int main(int argc, char **argv) num_lines++; } - chip =chip_open_lookup (argv[0 ]); -if (!chip) + path =chip_path_lookup (argv[0 ]); +if (!path)die_perror ("unable to open %s" , argv[0 ]); line_cfg =gpiod_line_config_new ();
@@ -271,7 +270,7 @@ int main(int argc, char **argv)gpiod_request_config_set_consumer (req_cfg,"gpiomon" );gpiod_request_config_set_offsets (req_cfg, num_lines, offsets); - request =gpiod_chip_request_lines (chip, req_cfg, line_cfg); + request =gpiod_request_lines (path, req_cfg, line_cfg);if (!request)die_perror ("unable to request lines" );
@@ -314,7 +313,7 @@ done:gpiod_line_request_release (request);gpiod_request_config_free (req_cfg);gpiod_line_config_free (line_cfg); -gpiod_chip_close (chip); +free (path);return EXIT_SUCCESS ; }
tools/gpioset.c +5 -6
@@ -195,11 +195,10 @@ int main(int argc, char **argv)struct gpiod_line_request *request;struct gpiod_line_config *line_cfg;struct callback_data cbdata; -struct gpiod_chip *chip;bool active_low = false;unsigned int *offsets, *values;size_t i, num_lines; -char *device, *end; +char *device, *end, *path;memset (&cbdata,0 ,sizeof (cbdata));
@@ -288,8 +287,8 @@ int main(int argc, char **argv)die ("invalid offset: %s" , argv[i +1 ]); } - chip =chip_open_lookup (device); -if (!chip) + path =chip_path_lookup (device); +if (!path)die_perror ("unable to open %s" , device); line_cfg =gpiod_line_config_new ();
@@ -314,7 +313,7 @@ int main(int argc, char **argv)gpiod_request_config_set_consumer (req_cfg,"gpioset" );gpiod_request_config_set_offsets (req_cfg, num_lines, offsets); - request =gpiod_chip_request_lines (chip, req_cfg, line_cfg); + request =gpiod_request_lines (path, req_cfg, line_cfg);if (!request)die_perror ("unable to request lines" );
@@ -324,7 +323,7 @@ int main(int argc, char **argv)gpiod_line_request_release (request);gpiod_request_config_free (req_cfg);gpiod_line_config_free (line_cfg); -gpiod_chip_close (chip); +free (path);free (offsets);return EXIT_SUCCESS ;
tools/tools-common.c +19 -31
73 lines not on this page · raw message
tools/tools-common.h +3 -2
@@ -29,7 +29,8 @@ int parse_bias(const char *option);void print_bias_help (void );int make_signalfd (void );int chip_dir_filter (const struct dirent *entry); -struct gpiod_chip *chip_open_by_name (const char *name); -struct gpiod_chip *chip_open_lookup (const char *device); +struct gpiod_chip *chip_open (const char *path); +char *chip_path_from_name (const char *name); +char *chip_path_lookup (const char *device);#endif /* __GPIOD_TOOLS_COMMON_H__ */
Signature · 1 line
2.35.1
PATCH v2 4/4 tools: minimize object lifetimes
In reply to Kent GibsonThe tools double as examples of API usage, so keep object lifetimes to a minimum to highlight where transient objects are no longer required and may be discarded.
--- tools/gpioget.c | 16 ++++++++++------ tools/gpiomon.c | 7 ++++--- tools/gpioset.c | 9 +++++---- 3 files changed, 19 insertions(+), 13 deletions(-)
tools/gpioget.c +10 -6
@@ -92,8 +92,7 @@ int main(int argc, char **argv) num_lines = argc -1 ; offsets =calloc (num_lines,sizeof (*offsets)); - values =calloc (num_lines,sizeof (*values)); -if (!offsets || ! values) +if (!offsets)die ("out of memory" );for (i =0 ; i < num_lines; i++) {
@@ -124,11 +123,20 @@ int main(int argc, char **argv)gpiod_request_config_set_consumer (req_cfg,"gpioget" );gpiod_request_config_set_offsets (req_cfg, num_lines, offsets); +free (offsets); request =gpiod_request_lines (path, req_cfg, line_cfg);if (!request)die_perror ("unable to request lines" ); +free (path); +gpiod_request_config_free (req_cfg); +gpiod_line_config_free (line_cfg); + + values =calloc (num_lines,sizeof (*values)); +if (!values) +die ("out of memory" ); + ret =gpiod_line_request_get_values (request, values);if (ret)die_perror ("unable to read GPIO line values" );
@@ -141,10 +149,6 @@ int main(int argc, char **argv)printf ("\n" );gpiod_line_request_release (request); -gpiod_request_config_free (req_cfg); -gpiod_line_config_free (line_cfg); -free (path); -free (offsets);free (values);return EXIT_SUCCESS ;
tools/gpiomon.c +4 -3
@@ -274,6 +274,10 @@ int main(int argc, char **argv)if (!request)die_perror ("unable to request lines" ); +free (path); +gpiod_request_config_free (req_cfg); +gpiod_line_config_free (line_cfg); + event_buffer =gpiod_edge_event_buffer_new (EVENT_BUF_SIZE );if (!event_buffer)die_perror ("unable to allocate the line event buffer" );
@@ -311,9 +315,6 @@ int main(int argc, char **argv) done:gpiod_edge_event_buffer_free (event_buffer);gpiod_line_request_release (request); -gpiod_request_config_free (req_cfg); -gpiod_line_config_free (line_cfg); -free (path);return EXIT_SUCCESS ; }
tools/gpioset.c +5 -4
@@ -312,19 +312,20 @@ int main(int argc, char **argv)gpiod_request_config_set_consumer (req_cfg,"gpioset" );gpiod_request_config_set_offsets (req_cfg, num_lines, offsets); +free (offsets); request =gpiod_request_lines (path, req_cfg, line_cfg);if (!request)die_perror ("unable to request lines" ); +free (path); +gpiod_request_config_free (req_cfg); +gpiod_line_config_free (line_cfg); +if (mode->callback) mode->callback (&cbdata);gpiod_line_request_release (request); -gpiod_request_config_free (req_cfg); -gpiod_line_config_free (line_cfg); -free (path); -free (offsets);return EXIT_SUCCESS ; }
Signature · 1 line
2.35.1
Quoted 39 lines · Kent Gibson
In my review of the CXX bindings I suggested a top-level version of
Chip.request_lines(), and possibly a C API version as well, so here is the C version, plus a couple of semi-related tweaks I made along the way.The first patch adds the
gpiod_request_lines().
Patch 3 migrates the appropriate tools.
Patch 4 minimizes the lifetimes of objects in the tools as I've previously seen confusion over how long lived objects need to be. Patch 2 is just a rename cos "inexistent" looks weird to me. Strictly speaking it is fine, but unless there is a problem with using "nonexistent" I would go with the latter.This series may be require my unsigned values patch.
Cheers,
Kent.Kent Gibson (4):
core: addgpiod_request_lines
tools: rename inexistent to nonexistent
tools: migrate togpiod_request_lines
tools: minimize object lifetimesinclude/gpiod.h | 15 ++++++++ lib/line-request.c | 17 +++++++++ tests/tests-line-request.c | 73 ++++++++++++++++++++++++++++++++++++++ tools/gpio-tools-test.bats | 4 +-- tools/gpiodetect.c | 2 +- tools/gpiofind.c | 2 +- tools/gpioget.c | 25 +++++++------ tools/gpioinfo.c | 4 +-- tools/gpiomon.c | 16 ++++----- tools/gpioset.c | 18 +++++----- tools/tools-common.c | 50 ++++++++++---------------- tools/tools-common.h | 5 +-- 12 files changed, 164 insertions(+), 67 deletions(-)
Quoted 3 lines
--
2.35.1
Ugh, I didn't respond under the C++ review in time before you spent time on this. :/
I don't agree with this change. For C API I think the intention for v2 was to avoid having all kinds of high-level helpers and limit the number of functions to only those that are necessary to fully leverage the kernel uAPI and this one isn't necessary. I think we discussed it multiple times and agreed that the C library needs to be minimal this time.
For C++ and Python the issue is irrelevant because you can do:
auto request = gpiod::Chip("/dev/gpiochip0").request_lines(req_cfg, line_cfg);
or
request = gpiod.Chip("/dev/gpiochip0").request_lines(req_cfg, line_cfg)
respectively and achieve the same result while still using a one-liner.
Unless there's a *really* good reason to do this, it's a NAK from my side.
Bart
Quoted 40 lines · Bartosz Golaszewski
Quoted 39 lines · Kent Gibson
In my review of the CXX bindings I suggested a top-level version of
Chip.request_lines(), and possibly a C API version as well, so here is the C version, plus a couple of semi-related tweaks I made along the way.The first patch adds the
gpiod_request_lines().
Patch 3 migrates the appropriate tools.
Patch 4 minimizes the lifetimes of objects in the tools as I've previously seen confusion over how long lived objects need to be. Patch 2 is just a rename cos "inexistent" looks weird to me. Strictly speaking it is fine, but unless there is a problem with using "nonexistent" I would go with the latter.This series may be require my unsigned values patch.
Cheers,
Kent.Kent Gibson (4):
core: addgpiod_request_lines
tools: rename inexistent to nonexistent
tools: migrate togpiod_request_lines
tools: minimize object lifetimesinclude/gpiod.h | 15 ++++++++ lib/line-request.c | 17 +++++++++ tests/tests-line-request.c | 73 ++++++++++++++++++++++++++++++++++++++ tools/gpio-tools-test.bats | 4 +-- tools/gpiodetect.c | 2 +- tools/gpiofind.c | 2 +- tools/gpioget.c | 25 +++++++------ tools/gpioinfo.c | 4 +-- tools/gpiomon.c | 16 ++++----- tools/gpioset.c | 18 +++++----- tools/tools-common.c | 50 ++++++++++---------------- tools/tools-common.h | 5 +-- 12 files changed, 164 insertions(+), 67 deletions(-)
Quoted 7 lines
Quoted 3 lines
--
2.35.1Ugh, I didn't respond under the C++ review in time before you spent time on this. :/
Not a problem - it was just something to fill in time.
Quoted 7 lines
I don't agree with this change. For C API I think the intention for v2 was to avoid having all kinds of high-level helpers and limit the number of functions to only those that are necessary to fully leverage the kernel uAPI and this one isn't necessary. I think we discussed it multiple times and agreed that the C library needs to be minimal this time.
Quoted 8 lines
For C++ and Python the issue is irrelevant because you can do:
auto request = gpiod::Chip("/dev/gpiochip0").request_lines(req_cfg,
line_cfg);or
request = gpiod.Chip("/dev/gpiochip0").request_lines(req_cfg,
line_cfg)
The point isn't being able to do a one liner, the point is to remove the chip object from the set of concerns for the basic use case, and so provide an easier on-ramp for the casual user.
Quoted 4 lines
respectively and achieve the same result while still using a one-liner.
Unless there's a *really* good reason to do this, it's a NAK from my side.
That's fine.
Cheers,
Kent.