Forum > Linux
Accessing GPIOs using Linux
MarkMLl:
Various single-board Linux-based computers allow direct access to the GPIO pins via (memory-mapped) ports etc.
However, the "correct" way of doing this has, for a long time, been to go via /sys/class/gpio.
This has now been deprecated, and instead one is supposed to use libgpiod, which despite its name is not a daemon but is supposed to use "non-forgeable" descriptor tokens to refer to chips and lines.
APPROACH THIS NEW API WITH CAUTION: IT IS NOT STABLE AND SOME OF THE ENTRY POINTS HAVE CHANGED THE NUMBER OF EXPECTED PARAMETERS WITH NO EASY WAY OF DETERMINING WHAT VERSION IS ON ANY PARTICULAR SYSTEM.
Apologies to anybody who thinks this is misplaced, but I think it's important for people developing for e.g. the Raspberry Pi to see it, even if they don't realise that they're running Linux or "a unix".
Subsequently: I'd like to say that I'm unhappy about this being moved by a moderator. However I consider it sufficiently important that I'm not going to "throw my toys out of the pram" by deleting it.
MarkMLl
PascalDragon:
--- Quote from: MarkMLl on August 30, 2021, 01:47:18 pm ---Subsequently: I'd like to say that I'm unhappy about this being moved by a moderator. However I consider it sufficiently important that I'm not going to "throw my toys out of the pram" by deleting it.
--- End quote ---
This is about a Linux-specific API, so of course this belongs into the Linux-specific sub forum and not into the general one.
ArminLinder:
No matter where the warning is placed, I welcome it.
I tried to look up those "non-forgeable" desctiptor tokens, but found nothing.
Where can I read more about that mechanism?
Tnnx, Armin.
MarkMLl:
--- Quote from: PascalDragon on August 30, 2021, 02:31:54 pm ---This is about a Linux-specific API, so of course this belongs into the Linux-specific sub forum and not into the general one.
--- End quote ---
Does it apply to Android? How often are Android and for that matter Raspbian (or WTF it's now called) acknowledged as being Linux by their devotees?
MarkMLl
MarkMLl:
--- Quote from: Nimral on August 30, 2021, 03:12:15 pm ---I tried to look up those "non-forgeable" desctiptor tokens, but found nothing.
Where can I read more about that mechanism?
--- End quote ---
I think they're just numbers, I've not checked whether they are in fact non-sequential and not pointers but the important point is they should be /treated/ as opaque. My suspicion is that it was some programmer's bright idea and he hoped to encourage more people to adopt the style rather than blithely passing pointers around.
The documentation situation is lousy, there's fairly decent descriptions of the parameters and return values in the .h file, but that's about the best one can expect.
What I can say is that gpiod.h which come with Debian Buster and Bullseye has an API where one has to allocate bulk objects oneself and pass them as a parameter to the calls that do bulk reads, wait for events on a number of lines etc.; contrast this with the current kernel where you ask the API for a bulk object. So in the old API you have e.g.
--- Code: C [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---int gpiod_chip_get_all_lines(struct gpiod_chip *chip, struct gpiod_line_bulk *bulk) GPIOD_API;
while in the new one you have
--- Code: C [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---struct gpiod_line_bulk * gpiod_chip_get_all_lines(struct gpiod_chip *chip);
...get it wrong and the program will crash.
I think that it's possible to distinguish between the available .so libraries using
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- (* At some point the API has changed from the bulk calls requiring a pointer to a bulk object as an explicit parameter to allocating bulk object internal to the library or kernel and returning a pointer or nil. The presence of this entry point might be sufficient distinction. *) function hasOldBulkApi(): boolean; var bulk: Pgpiod_line_bulk; begin result := true; try bulk := Gpiod.gpiod_line_bulk_new(1); Gpiod.gpiod_line_bulk_free(bulk); result := false except end end { hasOldBulkApi } ;
where the Gpiod object wraps all of the dynamic loading and will raise an exception if the gpiod_line_bulk_new() entry point is unimplemented.
Knowing that, it would be possible to have a single Pascal interface which implemented e.g. gpiod_chip_get_all_lines() differently depending on the run-time behaviour of libgpiod. However a preferable solution- and one that I think the (unpublished) utility I use for processing some of this stuff could handle- would be to have libgpio0_dynamic.pas for the old API and libgpio_dynamic.pas for the new one... but it's still a lot of work to fix a foul-up which quite simply SHOULD NOT HAVE HAPPENED TO A PUBLIC API.
MarkMLl
Navigation
[0] Message Index
[#] Next page