Get value of a gpio output using libgpiod in Linux

5.1k views Asked by At

I am using Linux (kernel v5.8.17) on an embedded custom board and have a script doing some gpioget and gpioset operations with the libgpiod package.

Setting output pins with gpioset works great, as does getting value of input pins with gpioget. But when I need to know the current value of an output pin, using gpioget changes the pin value, and the direction.

Here is an example:

gpioinfo | grep MB_AC_ON
     line 230:   "MB_AC_ON"       unused  output  active-high
gpioset $(gpiofind "MB_AC_ON")=1
gpioget $(gpiofind "MB_AC_ON")
0
gpioinfo | grep MB_AC_ON
     line 230:   "MB_AC_ON"       unused   input  active-high

Setting the pin to '1' works. But then checking the current value of that same pin using gpioget, the value changes to '0' and the direction is changed to input. Is it even possible to get the value of a gpio output using libgpiod?

2

There are 2 answers

3
Zafer SEN On BEST ANSWER

When I checked the detail by gpioset -h there was a note: I think this is the answer to your question.

Note: the state of a GPIO line controlled over the character device reverts to default when the last process referencing the file descriptor representing the device file exits. This means that it's wrong to run gpioset, have it exit and expect the line to continue being driven high or low. It may happen if given pin is floating but it must be interpreted as undefined behavior.

Also if we look at the code (gpioset: ../libgpiod/tools/gpioset.c) in more detail. We can see that these code blocks below, which lead to the line getting default value (you cannot keep the value you set using by gpioset).

gpiod_line_release_bulk(lines);
gpiod_chip_unref(chip);
gpiod_line_bulk_free(lines);
free(offsets);
free(values);
1
frsc On

Actually the accepted answer contains only one aspect of the problem. Yes, gpioset doesn't guarantee to persist the GPIOs state after exit. One could use the mode parameter to keep the file descriptor open until it receives a signal.

gpioset --mode=signal $(gpiofind "MB_AC_ON")=1

For libgpiod v2 gpioset behaves differently and doesn't exit by default anymore unless it receives a signal. With other simplifications to directly specify a line by label, the equivalent command as above boils down to the following in v2:

gpioset MB_AC_ON=1

Though for some GPIO controllers the state is actually persistent even after gpioset exits, which also seems to be the case for the OP. In those cases you still have the problem that using gpioget afterwards changes the direction from output back to input, even when you just want to get the current state of the output.

In this case v2 of libgpiod has a new parameter --as-is to keep the direction:

gpioget --as-is MB_AC_ON