Reading a GPIO value from inside a container

This is related to this existing question :

I’m trying to implement that inside a docker container on a Verdin iMX8M Plus using stock TorizonCore. When I try to use code from the “minimal working C example” in the above link, it doesn’t work. The call to gpio_line_event_get_fd returns -1, errno is 1 “Operation not permitted”.

I tried a simple sample application with the same code in TorizonCore, outside the container, and get the same error.

We’re using similar code on a Colibri T30, polling a GPIO input via poll(fds…), that works fine. Though the file descriptor is not obtained through gpiod, that is not present on T30s.

Is getting a file descriptor for a GPIO not supported for gpiod on newer systems? Or what do I need to tweak to get it allowed? If it’s not supported, is there a workaround?

Greetings @techczech,

How exactly are you building and running the code in the linked post?

I took the code in the referenced post as is without any modifications and compiled it inside a container. When I ran it, it executed without any issues. For reference, I did my test on a Verdin i.MX8M Plus running TorizonCore 6.2.0.

Judging by the error you described, did you use the pass the relevant /dev/gpiochip* into the container so that it can be used?

Best Regards,
Jeremias

We build in a docker container based on your torizon/debian:2-bullseye image. This is in an Ubuntu VM on a PC after enabling ARM emulation via “docker run --rm -it --privileged torizon/binfmt”.

The embedded container on the iMX8M Plus is based on your “torizon/weston-vivante:2” image. The OS version is “TorizonCore with PREEMPT_RT 5.7.0+build.17 (dunfell)”. This is running on a Verdin development board.

The docker-compose.yml to start the container includes :
devices:
- “/dev/gpiochip0”
- “/dev/gpiochip1”
- “/dev/gpiochip2”
- “/dev/gpiochip3”
- “/dev/gpiochip4”
- “/dev/gpiochip5”

Using all that, other gpiod functions work, e.g. gpiod_line_request_output + gpiod_line_set_value are working to light LEDs on the dev board.

The sample I ran in TorizonCore was built in the same docker container. And if the issue was the /dev/gpiochip* into the container, it should have worked out of the container and it didn’t. And I ran with sudo.

True confessions - I took the sample verbatim, built and ran, and got a valid value back from gpiod_line_event. Code that was returning an error was similar, but based on what we used on the T30. Sorting through what’s different…

I took the sample verbatim, built and ran, and got a valid value back from gpiod_line_event

So wait, just to clarify then the code as is does work for you then correct?

Best Regards,
Jeremias

Yes, it works as is both in the container and out of it in TorizonCore. I’m still hunting down why what I originally had does not.

I found the difference in our code where this problem manifests, and can modify the sample code to reproduce the issue. After getting the chip and line, before setting the falling edge, we call gpiod_line_request_input for the line. That is equivalent to how GPIOs are initialized for Yocto on the Colibri T30s, we set the GPIO as input first, then set edge.

I don’t understand that behavior, why setting it as an input would make edge detection and polling not work. But if that’s just how it is, we’ll find workarounds :frowning:

Now that I know what the issue is, I found another community post about the same thing.

Everyplace else I’ve used GPIOs, input/output and input edge are used in conjunction. Apparently in gpiod they’re mutually exclusive. And once you call one, you can’t override it by calling the other. What does work is releasing then reacquiring the line if you want to change.

Thank you for sharing your finding, glad you were able to work things out.

Best Regards,
Jeremias