Reputation: 517
(I'm directly using the new V2 system calls rather than libgpiod
which uses the deprecated V1 calls).
I have got the device fd by using the ioctl GPIO_V2_GET_LINE_IOCTL
and have defined a GPIO line to be an output line in the req.config
struct.
As soon as I call the ioctl GPIO_V2_LINE_SET_CONFIG_IOCTL
the output line's output goes to zero - I would like it to retain its previous value of 1.
I can immediately follow the set config call with a GPIO_V2_LINE_SET_VALUES_IOCTL
ioctl call to explicitly set the value but that seems lame, and will, I assume, cause a short blip on the line.
Is there a way to configure a GPIO output without the line state changing (I am committed to the chardev GPIO model)?
I suppose I could do the hacky thing of configuring the output drive to be open-source with a bias pull-up but that's incredibly ugly and may not be electrically safe depending on what the GPIO is driving (I'm not going to do it).
Upvotes: 0
Views: 504
Reputation: 380
If you mean can you request a line explicitly as an output, but not specify the value it should be set to, then no that is not possible. You have to specify the value. If you don't explicitly specify a value then the default of 0 is assumed. That applies to both the GPIO_V2_GET_LINE_IOCTL and the GPIO_V2_LINE_SET_CONFIG_IOCTL, both of which require the full state of the line to be specified, including the value if the line is an output.
However, depending on your device driver and hardware, you MAY be able to request a line already configured as output "as-is", using GPIO_V2_GET_LINE_IOCTL and not setting either GPIO_V2_LINE_FLAG_INPUT or GPIO_V2_LINE_FLAG_OUTPUT, and then read the current value using GPIO_V2_LINE_GET_VALUES_IOCTL. The behavior in that case is not well defined, and some drivers will return the output buffer value, others the input buffer value, and those may differ if they may be electrically disconnected when the line is configured as an output. YMMV.
Upvotes: 0
Reputation: 517
The comments (mine in particular) did not help. Here is what I have figured out, and what has worked for me.
The problem arises due to confusion about how gpio line output values are set. There are 2 distinct mechanisms, used in 2 different situations, and (IMHO) the documentation is far from clear.
To set an output value at configuration time (ie when configuring the line to be an output), you must use request->config.attrs (request is a gpio_v2_line_request struct pointer). Something like this:
struct gpio_v2_line_config *config = &(request->config);
int attr_idx = <get index of slot for output values in config.attrs>;
int line_idx = <get index of line in request->offsets>
config->attrs[attr_idx].attr_id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;
setbit(config->attrs[attr_idx].mask, line_idx);
if (output_value == 1) {
setbit(config->attrs[attr_idx].mask, line_idx);
}
else {
clearbit(config->attrs[attr_idx].mask, line_idx);
}
Then you can use the GPIO_V2_LINE_SET_CONFIG_IOCTL ioctl call to send your configuration to the gpio lines.
Once the line has been configured, its output values are changed using a gpio_v2_line_values struct. Like this:
struct gpio_v2_line_values values = {0, 0};
int line_idx = <get index of line in request->offsets>
setbit(values.mask, line_idx);
if (output_value == 1) {
setbit(values.bits, line_idx);
}
Use the GPIO_V2_LINE_SET_VALUES_IOCTL ioctl call to set the output lines from your values struct.
Upvotes: 0