From: Kent Gibson <warthog618@gmail.com>
To: Bartosz Golaszewski <brgl@bgdev.pl>
Cc: linux-gpio@vger.kernel.org
Subject: Re: [libgpiod v2][PATCH v3 2/5] tools: line name focussed rework
Date: Tue, 8 Nov 2022 23:33:15 +0800 [thread overview]
Message-ID: <Y2p2u7oCQ/fToeLw@sol> (raw)
In-Reply-To: <CAMRc=Mf=x3iKyvzj63CX1Jgj4fsQKXbHHwcSpLbsvF-teb8Rag@mail.gmail.com>
On Tue, Nov 08, 2022 at 02:13:20PM +0100, Bartosz Golaszewski wrote:
> On Tue, Oct 11, 2022 at 2:29 AM Kent Gibson <warthog618@gmail.com> wrote:
> >
> > Rework the tool suite to support identifying lines by name and to
> > support operating on the GPIO lines available to the user at once, rather
> > than on one particular GPIO chip.
> >
> > All tools, other than gpiodetect, now provide the name to (chip,offset)
> > mapping that was previously only performed by gpiofind. As names are not
> > guaranteed to be unique, a --strict option is provided for all tools to
> > either abort the operation or report all lines with the matching name, as
> > appropriate.
> > By default the tools operate on the first line found with a matching name.
> >
> > Selection of line by (chip,offset) is still supported with a --chip
> > option, though it restricts the scope of the operation to an individual
> > chip. When the --chip option is specified, the lines are assumed to be
> > identified by offset where they parse as an integer, else by name.
> > To cater for the unusual case where a line name parses as an integer,
> > but is different from the offset, the --by-name option forces the lines
> > to be identified by name.
> >
> > The updated tools are intentionally NOT backwardly compatible with the
> > previous tools. Using old command lines with the updated tools will
> > almost certainly fail, though migrating old command lines is generally as
> > simple as adding a '-c' before the chip.
> >
>
> While at it: how about adding the --consumer/-C switch to specify a
> consumer string other than the name of the program?
>
Ironically I added that to the Rust version, for the long lived
commands anyway, so it could better emulate the C version for testing
purposes.
But could be generally useful, so ok.
I only used the long form there to avoid confusion with -c (as they are
visually very similar) and following the principle that rarely used
options only get a long form, so I will omit the short -C option - unless
you insist.
> > In addition the individual tools are modified as follows:
> >
> > gpiodetect:
> >
> > Add the option to select individual chips.
> >
> > gpioinfo:
> >
> > Change the focus from chips to lines, so the scope can be
> > an individual line, a subset of lines, all lines on a particular chip,
> > or all the lines available to the user. For line scope a single line
> > summary is output for each line. For chip scope the existing format
> > displaying a summary of the chip and each of its lines is retained.
> >
> > Line attributes are consolidated into a list format, and are extended
> > to cover all attributes supported by uAPI v2.
> >
>
> One change in the output that bothers me is the removal of quotation
> marks around the line name and consumer. I did that in v1 to visually
> distinguish between unnamed/unused lines and those that are named. I
> know it's highly unlikely that a line would be named "unnamed" (sic!)
> but still:
>
> line 0: "foo"
> line 1: unnamed
>
> looks more intuitive to me.
I disagree on this one. In the longer term all lines should be named
and then the quotes just become pointless noise, and require more
work to parse.
>Same for the consumer as with your current
> version, if the consumer string has spaces in it, it will look like
> this: consumer=foo bar. I think consumer="foo bar" would be easier to
> parse.
For this very reason, the consumer is explicitly listed last, so the
consumer name matches everything between the "consumer=" and end of
line.
Unless consumer names with spaces are very common in the wild then
quotes only add more clutter.
>
> > gpioget:
> >
> > The default output format is becomes line=value, as per the
> > input for gpioset, and the value is reported as active or inactive,
> > rather than 0 or 1.
> > The previous format is available using the --numeric option.
> >
> > Add an optional hold period between requesting a line and reading the
> > value to allow the line to settle once the requested configuration has
> > been applied (e.g. bias).
> >
> > gpiomon:
> >
> > Consolidate the edge options into a single option.
> >
> > Add a debounce period option.
> >
> > Add options to report event times as UTC or localtime.
> >
> > Add format specifiers for GPIO chip path, line name, stringified event
> > type, and event time as a datetime.
> >
> > Rearrange default output format to place fields with more predicable
> > widths to the left, and to separate major field groups with tabs.
> > Lines are identified consistent with the command line.
> >
> > gpioset:
> >
> > Add a hold period option that specifies the minimum period the line
> > value must be held for. This applies to all set options.
> >
> > Support line values specified as active/inactive, on/off and
> > true/false, as well as 1/0.
> >
> > Add a toggle option that specifies a time sequence over which the
> > requested lines should be toggled. If the sequence is 0 terminated then
> > gpioset exits when the sequence completes, else it repeats the sequence.
> > This allows for anything from simple blinkers to bit bashing from the
> > command line. e.g. gpioset -t 500ms LED=on
> >
> > Add an interactive option to provide a shell-like interface to allow
> > manual or scripted manipulation of requested lines. A basic command set
> > allows lines to be get, set, or toggled, and to insert sleeps between
> > operations.
> >
>
> As discussed elsewhere - it would be great if this part was optional
> and configurable at build-time so that the dependency on libedit could
> be dropped if unavailable.
>
Agreed.
> > Remove the --mode, --sec, and --usec options.
> > The combination of hold period and interactive mode provide functionality
> > equivalent to the old --mode options.
> >
>
> I have one problem with that - I think the basic functionality of:
> "take a line, set its value and wait for a signal" would still be
> useful. As it is now, I'm not sure how to make gpioset just hold a
> line without calling the GPIO_V2_LINE_SET_VALUES_IOCTL ioctl
> periodically.
>
I forgot to mention the daemonize option here, so
gpioset -z myline=1
will do that.
(or
gpioset -i myline=1
if you want to keep the process in the foreground.)
I'll add something to the daemonize help to highlight that it will hold
the line until killed. Is that sufficient?
> > Signed-off-by: Kent Gibson <warthog618@gmail.com>
> > ---
> > configure.ac | 8 +-
> > tools/Makefile.am | 2 +-
> > tools/gpiodetect.c | 113 +++++-
> > tools/gpioget.c | 204 ++++++++++-
> > tools/gpioinfo.c | 223 +++++++++++-
> > tools/gpiomon.c | 450 +++++++++++++++++++++++-
> > tools/gpioset.c | 815 ++++++++++++++++++++++++++++++++++++++++++-
> > tools/tools-common.c | 713 ++++++++++++++++++++++++++++++++++++-
> > tools/tools-common.h | 99 +++++-
> > 9 files changed, 2585 insertions(+), 42 deletions(-)
> >
> > diff --git a/configure.ac b/configure.ac
> > index 6ac1d8e..c8033c5 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -106,14 +106,14 @@ AC_DEFUN([FUNC_NOT_FOUND_TOOLS],
> > AC_DEFUN([HEADER_NOT_FOUND_TOOLS],
> > [ERR_NOT_FOUND([$1 header], [tools])])
> >
> > +AC_DEFUN([LIB_NOT_FOUND_TOOLS],
> > + [ERR_NOT_FOUND([lib$1], [tools])])
> > +
> > if test "x$with_tools" = xtrue
> > then
> > # These are only needed to build tools
> > - AC_CHECK_FUNC([basename], [], [FUNC_NOT_FOUND_TOOLS([basename])])
> > AC_CHECK_FUNC([daemon], [], [FUNC_NOT_FOUND_TOOLS([daemon])])
> > - AC_CHECK_FUNC([signalfd], [], [FUNC_NOT_FOUND_TOOLS([signalfd])])
> > - AC_CHECK_FUNC([setlinebuf], [], [FUNC_NOT_FOUND_TOOLS([setlinebuf])])
> > - AC_CHECK_HEADERS([sys/signalfd.h], [], [HEADER_NOT_FOUND_TOOLS([sys/signalfd.h])])
> > + PKG_CHECK_MODULES(LIBEDIT, libedit)
> > fi
> >
> > AC_ARG_ENABLE([tests],
> > diff --git a/tools/Makefile.am b/tools/Makefile.am
> > index fc074b9..c956314 100644
> > --- a/tools/Makefile.am
> > +++ b/tools/Makefile.am
> > @@ -7,7 +7,7 @@ AM_CFLAGS += -Wall -Wextra -g -std=gnu89
> > noinst_LTLIBRARIES = libtools-common.la
> > libtools_common_la_SOURCES = tools-common.c tools-common.h
> >
> > -LDADD = libtools-common.la $(top_builddir)/lib/libgpiod.la
> > +LDADD = libtools-common.la $(top_builddir)/lib/libgpiod.la $(LIBEDIT_LIBS)
> >
> > bin_PROGRAMS = gpiodetect gpioinfo gpioget gpioset gpiomon
> >
> > diff --git a/tools/gpiodetect.c b/tools/gpiodetect.c
> > index 30bde32..910fe9e 100644
> > --- a/tools/gpiodetect.c
> > +++ b/tools/gpiodetect.c
> > @@ -1,8 +1,7 @@
> > // SPDX-License-Identifier: GPL-2.0-or-later
> > // SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
> > +// SPDX-FileCopyrightText: 2022 Kent Gibson <warthog618@gmail.com>
> >
> > -#include <dirent.h>
> > -#include <errno.h>
> > #include <getopt.h>
> > #include <gpiod.h>
> > #include <stdio.h>
> > @@ -11,3 +10,113 @@
> >
> > #include "tools-common.h"
> >
> > +static void print_help(void)
> > +{
> > + printf("Usage: %s [OPTIONS] [chip]...\n", get_progname());
> > + printf("\n");
> > + printf("List GPIO chips, print their labels and number of GPIO lines.\n");
> > + printf("\n");
> > + printf("Chips may be identified by number, name, or path.\n");
> > + printf("e.g. '0', 'gpiochip0', and '/dev/gpiochip0' all refer to the same chip.\n");
> > + printf("\n");
> > + printf("If no chips are specified then all chips are listed.\n");
> > + printf("\n");
> > + printf("Options:\n");
> > + printf(" -h, --help\t\tdisplay this help and exit\n");
> > + printf(" -v, --version\t\toutput version information and exit\n");
> > +}
> > +
> > +int parse_config(int argc, char **argv)
> > +{
> > + int optc, opti;
> > + const char *const shortopts = "+hv";
> > + const struct option longopts[] = {
> > + { "help", no_argument, NULL, 'h' },
> > + { "version", no_argument, NULL, 'v' },
> > + { GETOPT_NULL_LONGOPT },
> > + };
>
> This can be static as there are no addresses of flag variables assigned.
>
Indeed - and now you mention it I notice a few other things that should be
static too.
> > +
> > + for (;;) {
> > + optc = getopt_long(argc, argv, shortopts, longopts, &opti);
> > + if (optc < 0)
> > + break;
> > +
> > + switch (optc) {
> > + case 'h':
> > + print_help();
> > + exit(EXIT_SUCCESS);
> > + case 'v':
> > + print_version();
> > + exit(EXIT_SUCCESS);
> > + case '?':
> > + die("try %s --help", get_progname());
> > + default:
> > + abort();
> > + }
> > + }
> > + return optind;
> > +}
> > +
> > +int print_chip_info(const char *path)
> > +{
> > + struct gpiod_chip *chip;
> > + struct gpiod_chip_info *info;
> > +
> > + chip = gpiod_chip_open(path);
> > + if (!chip) {
> > + print_perror("unable to open chip '%s'", path);
> > + return 1;
> > + }
> > +
> > + info = gpiod_chip_get_info(chip);
> > + if (!info)
> > + die_perror("unable to read info for '%s'", path);
> > +
> > + printf("%s [%s] (%zu lines)\n",
> > + gpiod_chip_info_get_name(info),
> > + gpiod_chip_info_get_label(info),
> > + gpiod_chip_info_get_num_lines(info));
> > +
> > + gpiod_chip_info_free(info);
> > + gpiod_chip_close(chip);
> > + return 0;
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > + int num_chips, i;
> > + char **paths;
> > + char *path;
> > + int ret = EXIT_SUCCESS;
> > +
> > + i = parse_config(argc, argv);
> > + argc -= i;
> > + argv += i;
> > +
> > + if (argc == 0) {
> > + num_chips = all_chip_paths(&paths);
> > + for (i = 0; i < num_chips; i++) {
> > + if (print_chip_info(paths[i]))
> > + ret = EXIT_FAILURE;
> > +
> > + free(paths[i]);
> > + }
> > + free(paths);
> > + }
> > +
> > + for (i = 0; i < argc; i++) {
> > + if (chip_path_lookup(argv[i], &path)) {
> > + if (print_chip_info(path))
> > + ret = EXIT_FAILURE;
> > +
> > + free(path);
> > + } else {
> > + print_error(
> > + "cannot find GPIO chip character device '%s'",
> > + argv[i]);
> > + ret = EXIT_FAILURE;
> > + }
> > + }
> > +
> > + return ret;
> > +}
> > diff --git a/tools/gpioget.c b/tools/gpioget.c
> > index 1b3e666..7a26066 100644
> > --- a/tools/gpioget.c
> > +++ b/tools/gpioget.c
> > @@ -1,12 +1,214 @@
> > // SPDX-License-Identifier: GPL-2.0-or-later
> > // SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
> > +// SPDX-FileCopyrightText: 2022 Kent Gibson <warthog618@gmail.com>
> >
> > #include <getopt.h>
> > #include <gpiod.h>
> > -#include <limits.h>
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <string.h>
> > +#include <unistd.h>
> >
> > #include "tools-common.h"
> >
> > +static void print_help(void)
> > +{
> > + printf("Usage: %s [OPTIONS] <line>...\n", get_progname());
> > + printf("\n");
> > + printf("Read values of GPIO lines.\n");
> > + printf("\n");
> > + printf("Lines are specified by name, or optionally by offset if the chip option\n");
> > + printf("is provided.\n");
> > + printf("\n");
> > + printf("Options:\n");
> > + printf(" -a, --as-is\t\tleave the line direction unchanged, not forced to input\n");
> > + print_bias_help();
> > + printf(" --by-name\t\ttreat lines as names even if they would parse as an offset\n");
> > + printf(" -c, --chip <chip>\trestrict scope to a particular chip\n");
> > + printf(" -h, --help\t\tdisplay this help and exit\n");
> > + printf(" -l, --active-low\ttreat the line as active low\n");
> > + printf(" -p, --hold-period <period>\n");
> > + printf("\t\t\twait between requesting the lines and reading the values\n");
> > + printf(" --numeric\t\tdisplay line values as '0' (inactive) or '1' (active)\n");
> > + printf(" -s, --strict\t\tabort if requested line names are not unique\n");
> > + printf(" -v, --version\t\toutput version information and exit\n");
> > + print_chip_help();
> > + print_period_help();
> > +}
> > +struct config {
> > + bool active_low;
> > + bool strict;
> > + int bias;
> > + int direction;
> > + unsigned int hold_period_us;
> > + const char *chip_id;
> > + int by_name;
> > + int numeric;
> > +};
> > +
> > +int parse_config(int argc, char **argv, struct config *cfg)
> > +{
> > + int opti, optc;
> > + const char *const shortopts = "+ab:c:hlp:sv";
> > + const struct option longopts[] = {
> > + { "active-low", no_argument, NULL, 'l' },
> > + { "as-is", no_argument, NULL, 'a' },
> > + { "bias", required_argument, NULL, 'b' },
> > + { "by-name", no_argument, &cfg->by_name, 1 },
> > + { "chip", required_argument, NULL, 'c' },
> > + { "help", no_argument, NULL, 'h' },
> > + { "hold-period", required_argument, NULL, 'p' },
> > + { "numeric", no_argument, &cfg->numeric, 1 },
> > + { "strict", no_argument, NULL, 's' },
> > + { "version", no_argument, NULL, 'v' },
> > + { GETOPT_NULL_LONGOPT },
> > + };
> > +
> > + memset(cfg, 0, sizeof(*cfg));
> > + cfg->direction = GPIOD_LINE_DIRECTION_INPUT;
> > +
> > + for (;;) {
> > + optc = getopt_long(argc, argv, shortopts, longopts, &opti);
> > + if (optc < 0)
> > + break;
> > +
> > + switch (optc) {
> > + case 'a':
> > + cfg->direction = GPIOD_LINE_DIRECTION_AS_IS;
> > + break;
> > + case 'b':
> > + cfg->bias = parse_bias_or_die(optarg);
> > + break;
> > + case 'c':
> > + cfg->chip_id = optarg;
> > + break;
> > + case 'l':
> > + cfg->active_low = true;
> > + break;
> > + case 'p':
> > + cfg->hold_period_us = parse_period_or_die(optarg);
> > + break;
> > + case 's':
> > + cfg->strict = true;
> > + break;
> > + case 'h':
> > + print_help();
> > + exit(EXIT_SUCCESS);
> > + case 'v':
> > + print_version();
> > + exit(EXIT_SUCCESS);
> > + case '?':
> > + die("try %s --help", get_progname());
> > + case 0:
> > + break;
> > + default:
> > + abort();
> > + }
> > + }
> > +
> > + return optind;
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > + int i, num_lines, ret, *values;
> > + struct gpiod_line_settings *settings;
> > + struct gpiod_request_config *req_cfg;
> > + struct gpiod_line_request *request;
> > + struct gpiod_line_config *line_cfg;
> > + struct gpiod_chip *chip;
> > + unsigned int *offsets;
> > + struct line_resolver *resolver;
> > + struct resolved_line *line;
> > + struct config cfg;
> > +
> > + i = parse_config(argc, argv, &cfg);
> > + argc -= i;
> > + argv += i;
> > +
> > + if (argc < 1)
> > + die("at least one GPIO line must be specified");
> > +
> > + resolver = resolve_lines(argc, argv, cfg.chip_id, cfg.strict,
> > + cfg.by_name);
> > + validate_resolution(resolver, cfg.chip_id);
> > +
> > + offsets = calloc(resolver->num_lines, sizeof(*offsets));
> > + values = calloc(resolver->num_lines, sizeof(*values));
> > + if (!offsets || !values)
> > + die("out of memory");
> > +
> > + settings = gpiod_line_settings_new();
> > + if (!settings)
> > + die_perror("unable to allocate line settings");
> > +
> > + gpiod_line_settings_set_direction(settings, cfg.direction);
> > +
> > + if (cfg.bias)
> > + gpiod_line_settings_set_bias(settings, cfg.bias);
> > +
> > + if (cfg.active_low)
> > + gpiod_line_settings_set_active_low(settings, true);
> > +
> > + req_cfg = gpiod_request_config_new();
> > + if (!req_cfg)
> > + die_perror("unable to allocate the request config structure");
> > +
> > + line_cfg = gpiod_line_config_new();
> > + if (!line_cfg)
> > + die_perror("unable to allocate the line config structure");
> > +
> > + gpiod_request_config_set_consumer(req_cfg, "gpioget");
> > + for (i = 0; i < resolver->num_chips; i++) {
> > + chip = gpiod_chip_open(resolver->chips[i].path);
> > + if (!chip)
> > + die_perror("unable to open chip '%s'",
> > + resolver->chips[i].path);
> > +
> > + num_lines = get_line_offsets_and_values(resolver, i, offsets,
> > + NULL);
> > +
> > + gpiod_line_config_reset(line_cfg);
> > + ret = gpiod_line_config_add_line_settings(line_cfg, offsets,
> > + num_lines, settings);
> > + if (ret)
> > + die_perror("unable to add line settings");
> > +
> > + request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
> > + if (!request)
> > + die_perror("unable to request lines");
> > +
> > + if (cfg.hold_period_us)
> > + usleep(cfg.hold_period_us);
> > +
> > + ret = gpiod_line_request_get_values(request, values);
> > + if (ret)
> > + die_perror("unable to read GPIO line values");
> > +
> > + set_line_values(resolver, i, values);
> > +
> > + gpiod_line_request_release(request);
> > + gpiod_chip_close(chip);
> > + }
> > + for (i = 0; i < resolver->num_lines; i++) {
> > + line = &resolver->lines[i];
> > + if (cfg.numeric)
> > + printf("%d", line->value);
> > + else
> > + printf("%s=%s", line->id,
> > + line->value ? "active" : "inactive");
> > +
> > + if (i != resolver->num_lines - 1)
> > + printf(" ");
> > + }
> > + printf("\n");
> > +
> > + free_line_resolver(resolver);
> > + gpiod_request_config_free(req_cfg);
> > + gpiod_line_config_free(line_cfg);
> > + gpiod_line_settings_free(settings);
> > + free(offsets);
> > + free(values);
> > +
> > + return EXIT_SUCCESS;
> > +}
> > diff --git a/tools/gpioinfo.c b/tools/gpioinfo.c
> > index ae368fa..5dc28f8 100644
> > --- a/tools/gpioinfo.c
> > +++ b/tools/gpioinfo.c
> > @@ -1,8 +1,7 @@
> > // SPDX-License-Identifier: GPL-2.0-or-later
> > // SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
> > +// SPDX-FileCopyrightText: 2022 Kent Gibson <warthog618@gmail.com>
> >
> > -#include <dirent.h>
> > -#include <errno.h>
> > #include <getopt.h>
> > #include <gpiod.h>
> > #include <stdarg.h>
> > @@ -12,3 +11,223 @@
> >
> > #include "tools-common.h"
> >
> > +static void print_help(void)
> > +{
> > + printf("Usage: %s [OPTIONS] [line]...\n", get_progname());
> > + printf("\n");
> > + printf("Print information about GPIO lines.\n");
> > + printf("\n");
> > + printf("Lines are specified by name, or optionally by offset if the chip option\n");
> > + printf("is provided.\n");
> > + printf("\n");
> > + printf("If no lines are specified than all lines are displayed.\n");
> > + printf("\n");
> > + printf("Options:\n");
> > + printf(" --by-name\t\ttreat lines as names even if they would parse as an offset\n");
> > + printf(" -c, --chip <chip>\trestrict scope to a particular chip\n");
> > + printf(" -h, --help\t\tdisplay this help and exit\n");
> > + printf(" -s, --strict\t\tcheck all lines - don't assume line names are unique\n");
> > + printf(" -v, --version\t\toutput version information and exit\n");
> > + print_chip_help();
> > +}
> > +
> > +struct config {
> > + bool strict;
> > + const char *chip_id;
> > + int by_name;
> > +};
> > +
> > +int parse_config(int argc, char **argv, struct config *cfg)
> > +{
> > + int opti, optc;
> > + const char *const shortopts = "+c:hsv";
> > + const struct option longopts[] = {
> > + { "by-name", no_argument, &cfg->by_name, 1 },
> > + { "chip", required_argument, NULL, 'c' },
> > + { "help", no_argument, NULL, 'h' },
> > + { "strict", no_argument, NULL, 's' },
> > + { "version", no_argument, NULL, 'v' },
> > + { GETOPT_NULL_LONGOPT },
> > + };
> > +
> > + memset(cfg, 0, sizeof(*cfg));
> > +
> > + for (;;) {
> > + optc = getopt_long(argc, argv, shortopts, longopts, &opti);
> > + if (optc < 0)
> > + break;
> > +
> > + switch (optc) {
> > + case 'c':
> > + cfg->chip_id = optarg;
> > + break;
> > + case 's':
> > + cfg->strict = true;
> > + break;
> > + case 'h':
> > + print_help();
> > + exit(EXIT_SUCCESS);
> > + case 'v':
> > + print_version();
> > + exit(EXIT_SUCCESS);
> > + case '?':
> > + die("try %s --help", get_progname());
> > + case 0:
> > + break;
> > + default:
> > + abort();
> > + }
> > + }
> > +
> > + return optind;
> > +}
> > +
> > +
> > +// minimal version similar to tools-common that indicates if a line should be
> > +// printed rather than storing details into the resolver.
> > +// Does not die on non-unique lines.
>
> C-style comments only please. Same elsewhere.
>
Yeah - sorry again - I'm so used to that style that I don't even notice
I'm doing it.
> <snip>
>
> I like the new tools in general. I don't have many issues with the
> code - you are a much better coder than I am.
That's being a bit harsh.
One thing I was considering was reworking the resolver so it would be
more suitable for general use, and move it to core libgpiod so apps
could more readily perform line name discovery.
> I would change the
> coding style here and there but I will probably just spend some time
> on a good clang-format config and use it indiscriminately like I did
> with black for Python.
>
That could be useful. Why doesn't the kernel do that?
And that reminds me - I still need to circle back and take another look
through the Python bindings.
Cheers,
Kent.
next prev parent reply other threads:[~2022-11-08 15:33 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-11 0:29 [libgpiod v2][PATCH v3 0/5] tools: improvements for v2 Kent Gibson
2022-10-11 0:29 ` [libgpiod v2][PATCH v3 1/5] tools: remove old code to simplify review Kent Gibson
2022-10-11 0:29 ` [libgpiod v2][PATCH v3 2/5] tools: line name focussed rework Kent Gibson
2022-11-08 13:13 ` Bartosz Golaszewski
2022-11-08 15:33 ` Kent Gibson [this message]
2022-11-08 18:25 ` Bartosz Golaszewski
2022-11-09 2:00 ` Kent Gibson
2022-11-09 11:16 ` Bartosz Golaszewski
2022-11-09 11:40 ` Kent Gibson
2022-10-11 0:29 ` [libgpiod v2][PATCH v3 3/5] tools: tests for " Kent Gibson
2022-10-11 0:29 ` [libgpiod v2][PATCH v3 4/5] tools: add gpiowatch Kent Gibson
2022-11-08 15:00 ` Bartosz Golaszewski
2022-11-08 15:38 ` Kent Gibson
2022-11-08 18:04 ` Bartosz Golaszewski
2022-11-09 1:57 ` Kent Gibson
2022-10-11 0:29 ` [libgpiod v2][PATCH v3 5/5] tools: gpiowatch tests Kent Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y2p2u7oCQ/fToeLw@sol \
--to=warthog618@gmail.com \
--cc=brgl@bgdev.pl \
--cc=linux-gpio@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).