Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update generic_gpio_libgpiod driver to latest libgpiod versions. #2833

Open
tomeko12 opened this issue Mar 4, 2025 · 20 comments · May be fixed by #2841
Open

Update generic_gpio_libgpiod driver to latest libgpiod versions. #2833

tomeko12 opened this issue Mar 4, 2025 · 20 comments · May be fixed by #2841
Labels
CI Entries related to continuous integration infrastructure (historically also recipes like Makefiles) GPIO Drivers talking to devices (or their chips) over GPIO interface packaging portability We want NUT to build and run everywhere possible
Milestone

Comments

@tomeko12
Copy link

tomeko12 commented Mar 4, 2025

Hi.
Please update generic_gpio_libgpiod driver to latest libgpiod versions.
Currently, this driver require libgpiod version 1.x.x (latest is 1.6.5), but newest distribution don't include this version, 2.x.x only (latest is 2.2.1), and driver can't be build.

@jimklimov jimklimov added packaging CI Entries related to continuous integration infrastructure (historically also recipes like Makefiles) GPIO Drivers talking to devices (or their chips) over GPIO interface portability We want NUT to build and run everywhere possible labels Mar 5, 2025
@jimklimov jimklimov added this to the 2.8.3 milestone Mar 5, 2025
@jimklimov
Copy link
Member

Thanks for the report. Apparently none of the CI farm systems, including those in GHA and similar providers who define the OS we get, exposed this to be a problem. Maybe they don't have the library at all and build --with-all=auto, or have older distro versions and older library :-\

@modrisb : would you have a chance to look at this anytime soon? (I hope to finish one other PR and cut a release to slip into distros' release window, so it is a matter of hours/days to fix before that too...)

@tomeko12 : can you suggest which distro/release this problem can be triggered on?

@jimklimov
Copy link
Member

jimklimov commented Mar 5, 2025

I took a quick look at it, and it seems the v2.x revamp of https://web.git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/ / https://github.com/brgl/libgpiod was even bigger than libusb0 going to libusb1 (where most of the concepts were equivalent but with different names and data types).

Here it is (or seems to be) like a separate project dabbling in the same area as libgpiod v1.x

Still, a separate distro is not so much needed, a custom build and install of the library suffices for attempts to support either API:

:; mkdir -p ~/nut-lin-deps/libgpiod-git
:; cd ~/nut-lin-deps/libgpiod-git
:; git clone https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git .
:; ./autogen.sh --prefix=$HOME/nut-lin-deps/libgpiod-git-inst
:; make install

And in NUT build area:

:; cd ~/nut
:; PKG_CONFIG_PATH=$HOME/nut-lin-deps/libgpiod-git-inst/lib/pkgconfig ./configure --with-gpio

@jimklimov
Copy link
Member

FWIW, some good history (and pointers about future) here:

And some precedent update to new API in another randomly googled project:

jimklimov added a commit to jimklimov/nut that referenced this issue Mar 5, 2025
…ure to C code of WITH_LIBGPIO_VERSION [networkupstools#2833]

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
jimklimov added a commit to jimklimov/nut that referenced this issue Mar 5, 2025
…ools#2833]

Should also serve for actual fix of the drivers for new libgpio API,
but not sure if that would land in NUT v2.8.3 timeframe or after the
release.

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
jimklimov added a commit to jimklimov/nut that referenced this issue Mar 5, 2025
…ure to C code of WITH_LIBGPIO_VERSION [networkupstools#2833]

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
jimklimov added a commit to jimklimov/nut that referenced this issue Mar 5, 2025
…ools#2833]

Should also serve for actual fix of the drivers for new libgpio API,
but not sure if that would land in NUT v2.8.3 timeframe or after the
release.

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
@jimklimov
Copy link
Member

jimklimov commented Mar 5, 2025

Laid some groundwork to detect the libgpiod variant and provide the fixes, but not sure I'd be able to follow up on those quickly (I don't have time now to understand the API changes responsibly, nor hardware to test against).

A commit would be very welcome to complete the PR, feel free to use the https://github.com/jimklimov/nut/tree/issue-2833 branch as the starting point.

Currently the configuration passes, newly introduced #define WITH_LIBGPIO_VERSION 0x00020000 appears in config.h, and the actual build reported problems only with this driver and none others (nor in gpio related tests):

Making all in drivers
  CC       generic_gpio_libgpiod.o
In file included from generic_gpio_libgpiod.c:27:
generic_gpio_libgpiod.h:30:33: error: field ‘gpioLines’ has incomplete type
   30 |         struct gpiod_line_bulk  gpioLines;      /* libgpiod lines to monitor */
      |                                 ^~~~~~~~~
generic_gpio_libgpiod.h:31:33: error: field ‘gpioEventLines’ has incomplete type
   31 |         struct gpiod_line_bulk  gpioEventLines; /* libgpiod lines for event monitoring */
      |                                 ^~~~~~~~~~~~~~
generic_gpio_libgpiod.c: In function ‘reserve_lines_libgpiod’:
generic_gpio_libgpiod.c:80:50: error: storage size of ‘config’ isn’t known
   80 |                 struct gpiod_line_request_config config;
      |                                                  ^~~~~~
generic_gpio_libgpiod.c:84:47: error: ‘GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES’ undeclared (first use in this function)
   84 |                         config.request_type = GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES;
      |                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generic_gpio_libgpiod.c:84:47: note: each undeclared identifier is reported only once for each function it appears in
generic_gpio_libgpiod.c:87:47: error: ‘GPIOD_LINE_REQUEST_DIRECTION_INPUT’ undeclared (first use in this function); did you mean ‘GPIOD_LINE_DIRECTION_INPUT’?
   87 |                         config.request_type = GPIOD_LINE_REQUEST_DIRECTION_INPUT;
      |                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                               GPIOD_LINE_DIRECTION_INPUT
generic_gpio_libgpiod.c:91:26: warning: implicit declaration of function ‘gpiod_line_request_bulk’; did you mean ‘gpiod_line_request_get_fd’? [-Wimplicit-function-declaration]
   91 |                 gpioRc = gpiod_line_request_bulk(&libgpiod_data->gpioLines, &config, NULL);
      |                          ^~~~~~~~~~~~~~~~~~~~~~~
      |                          gpiod_line_request_get_fd
generic_gpio_libgpiod.c:80:50: warning: unused variable ‘config’ [-Wunused-variable]
   80 |                 struct gpiod_line_request_config config;
      |                                                  ^~~~~~
generic_gpio_libgpiod.c: In function ‘gpio_open’:
generic_gpio_libgpiod.c:113:41: warning: implicit declaration of function ‘gpiod_chip_open_by_name’; did you mean ‘gpiod_chip_info_get_name’? [-Wimplicit-function-declaration]
  113 |         libgpiod_data->gpioChipHandle = gpiod_chip_open_by_name(gpioupsfdlocal->chipName);
      |                                         ^~~~~~~~~~~~~~~~~~~~~~~
      |                                         gpiod_chip_info_get_name
generic_gpio_libgpiod.c:113:39: warning: assignment to ‘struct gpiod_chip *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
  113 |         libgpiod_data->gpioChipHandle = gpiod_chip_open_by_name(gpioupsfdlocal->chipName);
      |                                       ^
generic_gpio_libgpiod.c:123:50: warning: implicit declaration of function ‘gpiod_chip_num_lines’; did you mean ‘gpiod_chip_request_lines’? [-Wimplicit-function-declaration]
  123 |                 gpioupsfdlocal->chipLinesCount = gpiod_chip_num_lines(libgpiod_data->gpioChipHandle);
      |                                                  ^~~~~~~~~~~~~~~~~~~~
      |                                                  gpiod_chip_request_lines
generic_gpio_libgpiod.c:134:17: warning: implicit declaration of function ‘gpiod_line_bulk_init’ [-Wimplicit-function-declaration]
  134 |                 gpiod_line_bulk_init(&libgpiod_data->gpioLines);
      |                 ^~~~~~~~~~~~~~~~~~~~
generic_gpio_libgpiod.c:136:26: warning: implicit declaration of function ‘gpiod_chip_get_lines’; did you mean ‘gpiod_chip_get_info’? [-Wimplicit-function-declaration]
  136 |                 gpioRc = gpiod_chip_get_lines(
      |                          ^~~~~~~~~~~~~~~~~~~~
      |                          gpiod_chip_get_info
generic_gpio_libgpiod.c: In function ‘gpio_get_lines_states’:
generic_gpio_libgpiod.c:180:41: error: storage size of ‘event’ isn’t known
  180 |                 struct gpiod_line_event event;
      |                                         ^~~~~
generic_gpio_libgpiod.c:198:24: warning: implicit declaration of function ‘gpiod_line_event_wait_bulk’ [-Wimplicit-function-declaration]
  198 |                 monRes=gpiod_line_event_wait_bulk(
      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~
generic_gpio_libgpiod.c:209:52: warning: implicit declaration of function ‘gpiod_line_bulk_num_lines’ [-Wimplicit-function-declaration]
  209 |                         int num_lines_local = (int)gpiod_line_bulk_num_lines(&libgpiod_data->gpioEventLines);
      |                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~
generic_gpio_libgpiod.c:212:60: warning: implicit declaration of function ‘gpiod_line_bulk_get_line’; did you mean ‘gpiod_line_info_get_drive’? [-Wimplicit-function-declaration]
  212 |                                 struct gpiod_line *eLine = gpiod_line_bulk_get_line(
      |                                                            ^~~~~~~~~~~~~~~~~~~~~~~~
      |                                                            gpiod_line_info_get_drive
generic_gpio_libgpiod.c:216:45: warning: implicit declaration of function ‘gpiod_line_event_read’; did you mean ‘gpiod_edge_event_free’? [-Wimplicit-function-declaration]
  216 |                                 int eventRc=gpiod_line_event_read(eLine, &event);
      |                                             ^~~~~~~~~~~~~~~~~~~~~
      |                                             gpiod_edge_event_free
generic_gpio_libgpiod.c:217:59: warning: implicit declaration of function ‘gpiod_line_offset’; did you mean ‘gpiod_line_info_free’? [-Wimplicit-function-declaration]
  217 |                                 unsigned int lineOffset = gpiod_line_offset(eLine);
      |                                                           ^~~~~~~~~~~~~~~~~
      |                                                           gpiod_line_info_free
generic_gpio_libgpiod.c:180:41: warning: unused variable ‘event’ [-Wunused-variable]
  180 |                 struct gpiod_line_event event;
      |                                         ^~~~~
generic_gpio_libgpiod.c:231:16: warning: implicit declaration of function ‘gpiod_line_get_value_bulk’ [-Wimplicit-function-declaration]
  231 |         gpioRc=gpiod_line_get_value_bulk(
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~
generic_gpio_libgpiod.c:253:17: warning: implicit declaration of function ‘gpiod_line_release_bulk’ [-Wimplicit-function-declaration]
  253 |                 gpiod_line_release_bulk(&libgpiod_data->gpioLines);
      |                 ^~~~~~~~~~~~~~~~~~~~~~~
make[1]: *** [Makefile:2188: generic_gpio_libgpiod.o] Error 1
make[1]: Target 'all' not remade because of errors.

@modrisb
Copy link
Contributor

modrisb commented Mar 5, 2025

@jimklimov not clear yet what would be the best solution: add ifdef's to generic_gpio-gpiolib.c to build for both library versions or create generic_gpio-gpiolib2.c to be used with v2 library. Probably 1st is possible, but may require significant rework and testing.

@jimklimov
Copy link
Member

Well, it depends on how large the API difference is. I hoped for a dozen tactical ifdef's to solve the issue, if most of the other logic remains. Easier to keep the two variant builds in sync this way, going forward (new NUT on older distros).

@modrisb
Copy link
Contributor

modrisb commented Mar 7, 2025

@jimklimov I have some progress with changes to support v2, but need more time for testing, hope will have by Monday. Test tools might be under questions as needs new mock for library. Let me know if see reason to publish recent code to git.

@jimklimov
Copy link
Member

Sounds encouraging, thanks! If it is buildable in at least one case, makes sense to push and check by CI (although that would mostly reveal that ifdef's did not break syntax for existing platforms). Maybe we can add a scenario using (packaged or locally built) libgpiod2 for more relevant checks too :) but I'll be also away for the weekend or much of it.

CC @mbiebl @bgermann : sorry for poking you guys - when is the Debian/Ubuntu packaging freeze for April releases, and how strict is it? Any chance of NUT v2.8.3 making it there if released e.g. next week, or is it too late already?..

@bgermann
Copy link

bgermann commented Mar 7, 2025

I do not use nut myself, just fixed a trivial bug that would have kept the existing package version from being released with trixie.
This was a good enough reason to upload not being the package maintainer.

For Ubuntu, I do not know the date, for Debian it is April 15th, so the new package version should enter on the 5th at the latest. If a SONAME bump (and with it, a package rename) is involved, you are probably out of luck.

The right place to discuss this is the Debian bug.

@modrisb
Copy link
Contributor

modrisb commented Mar 8, 2025

I opened pull request for solution. Test suite executed for both library versions, manual run of driver on RaspberryPi0 2 also for both versions.

@jimklimov
Copy link
Member

jimklimov commented Mar 9, 2025

Super! For posterity, that's a PR against my fork at jimklimov#6 - just as a master to master increment, without the libgpio version detection I proposed earlier.

@modrisb : I think I will pick your changes into the branch I did prepare, if only to make this variation more visible at build and in troubleshooting. One thing that looks odd to me is that both old and new gpio.h do #define GPIOD_API __attribute__((visibility("default"))) so I think builds against both codebase generations that discern by #ifdef GPIOD_API would end up compiling one branch of your source - and at that, the one with gpiod_chip_open_by_name that you no longer check for and is absent from libgpio v2.x. So I am wondering what am I missing and how it works for you to build and test both correctly?

UPDATE: I was wrong about GPIOD_API comments - I did miss something (see later posts).

PS: It was also an unconventional choice of workflow to make a new fork and post a PR from its master branch, rather than a new feature branch in an existing fork :)

jimklimov added a commit to jimklimov/nut that referenced this issue Mar 9, 2025
… WITH_LIBGPIO_VERSION_STR a driver was built against [networkupstools#2833]

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
jimklimov added a commit to jimklimov/nut that referenced this issue Mar 9, 2025
…WITH_LIBGPIO_VERSION [networkupstools#2833]

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
@modrisb
Copy link
Contributor

modrisb commented Mar 9, 2025

How did you checked presence of define for GPIOD_API? V2 git installation adds gpiod.h to /usr/local/include and not to /usr/include, may that's a trick? I lost at least hour on that. I added to code printout that depends on this define and got proper printouts.

Sorry for workflow - not doing this often and again mixed up.

@jimklimov
Copy link
Member

jimklimov commented Mar 9, 2025

I grep'ed the two sets of headers :)

Actually seen in git too:

:; cd libgpiod-git

:; git grep GPIOD_API v2.2.1 | grep define
v2.2.1:lib/internal.h:#define GPIOD_API __attribute__((visibility("default")))

:; git grep GPIOD_API v1.6.5 | grep define
v1.6.5:include/gpiod.h:#define GPIOD_API                __attribute__((visibility("default")))

UPDATE: Oh, I see now that this was in an internal.h for the new code - not exposed in public gpiod.h API anymore. Having a git grep hit confused me before I looked deeper.

jimklimov added a commit to jimklimov/nut that referenced this issue Mar 9, 2025
… WITH_LIBGPIO_VERSION_STR a driver was built against [networkupstools#2833]

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
jimklimov added a commit to jimklimov/nut that referenced this issue Mar 9, 2025
…WITH_LIBGPIO_VERSION [networkupstools#2833]

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
@jimklimov
Copy link
Member

I'm preparing the branch with your and my changes together, checking locally that the two builds pass and will post a PR to upstream NUT - would be grateful if you can test that against HW too :)

jimklimov added a commit to jimklimov/nut that referenced this issue Mar 9, 2025
…implementations [networkupstools#2833]

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
jimklimov added a commit to jimklimov/nut that referenced this issue Mar 9, 2025
…TH_LIBGPIO_VERSION [networkupstools#2833]

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
@jimklimov
Copy link
Member

PR #2841 posted, thanks to @modrisb for the actual changes. I just added the fancy bells and whistles :)

@modrisb
Copy link
Contributor

modrisb commented Mar 9, 2025

@jimklimov what would be right way to get code for testing?

@jimklimov
Copy link
Member

git clone https://github.com/jimklimov/nut -b issue-2833+modrisb nut-issue-2833

@modrisb
Copy link
Contributor

modrisb commented Mar 9, 2025

@jimklimov v2 works fine, except test tool prints lib version in decimal as 131072 (0x00020000); the same for v1 - tests and driver run is ok.

Probably to replace in tests/generic_gpio_utest.c
printf("Tests running for libgpiod library version %ul\n", version);
with
printf("Tests running for libgpiod library version %#018lx\n", version);

But plain decimal 1 or 2 would be more informative and clear.

@jimklimov
Copy link
Member

Aha, missed that hex :\ Thanks for checking!

Your initial post mentioned issues with v1 build - was that an operator error? :)

@modrisb
Copy link
Contributor

modrisb commented Mar 10, 2025

I did not properly cleared build before v1 - my fault.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI Entries related to continuous integration infrastructure (historically also recipes like Makefiles) GPIO Drivers talking to devices (or their chips) over GPIO interface packaging portability We want NUT to build and run everywhere possible
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants