GPIO wrapper functions for Linux userspace character device gpio-cdev
and sysfs GPIOs.
Character device GPIOs were introduced in Linux kernel version 4.8. If the toolchain used to compiled c-periphery contains Linux kernel headers older than 4.8 (i.e. linux/gpio.h
is missing), then only legacy sysfs GPIOs will be supported.
#include <periphery/gpio.h>
/* Primary Functions */
gpio_t *gpio_new(void);
int gpio_open(gpio_t *gpio, const char *path, unsigned int line, gpio_direction_t direction);
int gpio_open_name(gpio_t *gpio, const char *path, const char *name, gpio_direction_t direction);
int gpio_open_advanced(gpio_t *gpio, const char *path, unsigned int line, const gpio_config_t *config);
int gpio_open_name_advanced(gpio_t *gpio, const char *path, const char *name, const gpio_config_t *config);
int gpio_open_sysfs(gpio_t *gpio, unsigned int line, gpio_direction_t direction);
int gpio_read(gpio_t *gpio, bool *value);
int gpio_write(gpio_t *gpio, bool value);
int gpio_poll(gpio_t *gpio, int timeout_ms);
int gpio_close(gpio_t *gpio);
void gpio_free(gpio_t *gpio);
/* Read Event (for character device GPIOs) */
int gpio_read_event(gpio_t *gpio, gpio_edge_t *edge, uint64_t *timestamp);
/* Poll Multiple */
int gpio_poll_multiple(gpio_t **gpios, size_t count, int timeout_ms, bool *gpios_ready);
/* Getters */
int gpio_get_direction(gpio_t *gpio, gpio_direction_t *direction);
int gpio_get_edge(gpio_t *gpio, gpio_edge_t *edge);
int gpio_get_bias(gpio_t *gpio, gpio_bias_t *bias);
int gpio_get_drive(gpio_t *gpio, gpio_drive_t *drive);
int gpio_get_inverted(gpio_t *gpio, bool *inverted);
/* Setters */
int gpio_set_direction(gpio_t *gpio, gpio_direction_t direction);
int gpio_set_edge(gpio_t *gpio, gpio_edge_t edge);
int gpio_set_bias(gpio_t *gpio, gpio_bias_t bias);
int gpio_set_drive(gpio_t *gpio, gpio_drive_t drive);
int gpio_set_inverted(gpio_t *gpio, bool inverted);
/* Miscellaneous Properties */
unsigned int gpio_line(gpio_t *gpio);
int gpio_fd(gpio_t *gpio);
int gpio_name(gpio_t *gpio, char *str, size_t len);
int gpio_label(gpio_t *gpio, char *str, size_t len);
int gpio_chip_fd(gpio_t *gpio);
int gpio_chip_name(gpio_t *gpio, char *str, size_t len);
int gpio_chip_label(gpio_t *gpio, char *str, size_t len);
int gpio_tostring(gpio_t *gpio, char *str, size_t len);
/* Error Handling */
int gpio_errno(gpio_t *gpio);
const char *gpio_errmsg(gpio_t *gpio);
-
gpio_direction_t
GPIO_DIR_IN
: InputGPIO_DIR_OUT
: Output, initialized to lowGPIO_DIR_OUT_LOW
: Output, initialized to lowGPIO_DIR_OUT_HIGH
: Output, initialized to high
-
gpio_edge_t
GPIO_EDGE_NONE
: No interrupt edgeGPIO_EDGE_RISING
: Rising edge (0 -> 1 transition)GPIO_EDGE_FALLING
: Falling edge (1 -> 0 transition)GPIO_EDGE_BOTH
: Both edges (X -> !X transition)
-
gpio_bias_t
GPIO_BIAS_DEFAULT
: Default line biasGPIO_BIAS_PULL_UP
: Pull-upGPIO_BIAS_PULL_DOWN
: Pull-downGPIO_BIAS_DISABLE
: Disable line bias
-
gpio_drive_t
GPIO_DRIVE_DEFAULT
: Default line drive (push-pull)GPIO_DRIVE_OPEN_DRAIN
: Open drainGPIO_DRIVE_OPEN_SOURCE
: Open source
gpio_t *gpio_new(void);
Allocate a GPIO handle.
Returns a valid handle on success, or NULL on failure.
int gpio_open(gpio_t *gpio, const char *path, unsigned int line, gpio_direction_t direction);
Open the character device GPIO with the specified GPIO line and direction at the specified character device GPIO chip path (e.g. /dev/gpiochip0
).
gpio
should be a valid pointer to an allocated GPIO handle structure. path
is the GPIO chip character device path. line
is the GPIO line number. direction
is one of the direction values enumerated above.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_open_name(gpio_t *gpio, const char *path, const char *name, gpio_direction_t direction);
Open the character device GPIO with the specified GPIO name and direction at the specified character device GPIO chip path (e.g. /dev/gpiochip0
).
gpio
should be a valid pointer to an allocated GPIO handle structure. path
is the GPIO chip character device path. name
is the GPIO line name. direction
is one of the direction values enumerated above.
Returns 0 on success, or a negative GPIO error code on failure.
typedef struct gpio_config {
gpio_direction_t direction;
gpio_edge_t edge;
gpio_bias_t bias;
gpio_drive_t drive;
bool inverted;
const char *label;
} gpio_config_t;
int gpio_open_advanced(gpio_t *gpio, const char *path, unsigned int line, const gpio_config_t *config);
Open the character device GPIO with the specified GPIO line and configuration at the specified character device GPIO chip path (e.g. /dev/gpiochip0
).
gpio
should be a valid pointer to an allocated GPIO handle structure. path
is the GPIO chip character device path. line
is the GPIO line number. config
should be a valid pointer to a gpio_config_t
structure with valid values. label
can be NULL
for a default consumer label.
Returns 0 on success, or a negative GPIO error code on failure.
typedef struct gpio_config {
gpio_direction_t direction;
gpio_edge_t edge;
gpio_bias_t bias;
gpio_drive_t drive;
bool inverted;
const char *label;
} gpio_config_t;
int gpio_open_name_advanced(gpio_t *gpio, const char *path, const char *name, const gpio_config_t *config);
Open the character device GPIO with the specified GPIO name and configuration at the specified character device GPIO chip path (e.g. /dev/gpiochip0
).
gpio
should be a valid pointer to an allocated GPIO handle structure. path
is the GPIO chip character device path. name
is the GPIO line name. config
should be a valid pointer to a gpio_config_t
structure with valid values. label
can be NULL
for a default consumer label.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_open_sysfs(gpio_t *gpio, unsigned int line, gpio_direction_t direction);
Open the sysfs GPIO with the specified line and direction.
gpio
should be a valid pointer to an allocated GPIO handle structure. line
is the Linux GPIO line number. direction
is one of the direction values enumerated above.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_read(gpio_t *gpio, bool *value);
Read the state of the GPIO into value
.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions. value
should be a pointer to an allocated bool.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_write(gpio_t *gpio, bool value);
Set the state of the GPIO to value
.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_poll(gpio_t *gpio, int timeout_ms);
Poll a GPIO for the edge event configured with gpio_set_edge()
.
For character device GPIOs, the edge event should be consumed with gpio_read_event()
. For sysfs GPIOs, the edge event should be consumed with gpio_read()
.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions. timeout_ms
can be positive for a timeout in milliseconds, zero for a non-blocking poll, or negative for a blocking poll.
Returns 1 on success (an edge event occurred), 0 on timeout, or a negative GPIO error code on failure.
int gpio_read_event(gpio_t *gpio, gpio_edge_t *edge, uint64_t *timestamp);
Read the edge event that occurred with the GPIO.
This method is intended for use with character device GPIOs and is unsupported by sysfs GPIOs.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions. timestamp
is event time reported by Linux, in nanoseconds.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_poll_multiple(gpio_t **gpios, size_t count, int timeout_ms, bool *gpios_ready);
Poll multiple GPIOs for an edge event configured with gpio_set_edge()
.
For character device GPIOs, the edge event should be consumed with gpio_read_event()
. For sysfs GPIOs, the edge event should be consumed with gpio_read()
.
gpios
should be a valid pointer to a size count
array of GPIO handles opened with one of the gpio_open*()
functions. timeout_ms
can be positive for a timeout in milliseconds, zero for a non-blocking poll, or negative for a blocking poll. gpios_ready
is an optional pointer to a size count
array of bool
that will be populated with true
for the corresponding GPIO in the gpios
array if an edge event occurred, or false
if none occurred.
Returns number of GPIOs for which an edge event occurred, 0 on timeout, or a negative GPIO error code on failure.
int gpio_close(gpio_t *gpio);
Close the GPIO.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
Returns 0 on success, or a negative GPIO error code on failure.
void gpio_free(gpio_t *gpio);
Free a GPIO handle.
int gpio_get_direction(gpio_t *gpio, gpio_direction_t *direction);
int gpio_get_edge(gpio_t *gpio, gpio_edge_t *edge);
int gpio_get_bias(gpio_t *gpio, gpio_bias_t *bias);
int gpio_get_drive(gpio_t *gpio, gpio_drive_t *drive);
int gpio_get_inverted(gpio_t *gpio, bool *inverted);
Get the configured direction, interrupt edge, line bias, line drive, inverted (active low) properties, respectively, of the GPIO.
Line bias and line drive properties are not supported by sysfs GPIOs.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_set_direction(gpio_t *gpio, gpio_direction_t direction);
int gpio_set_edge(gpio_t *gpio, gpio_edge_t edge);
int gpio_set_bias(gpio_t *gpio, gpio_bias_t bias);
int gpio_set_drive(gpio_t *gpio, gpio_drive_t drive);
int gpio_set_inverted(gpio_t *gpio, bool inverted);
Set the direction, interrupt edge, line bias, line drive, inverted (active low) properties, respectively, of the GPIO.
Line bias and line drive properties are not supported by sysfs GPIOs.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
Returns 0 on success, or a negative GPIO error code on failure.
unsigned int gpio_line(gpio_t *gpio);
Return the line the GPIO handle was opened with.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
This function is a simple accessor to the GPIO handle structure and always succeeds.
int gpio_fd(gpio_t *gpio);
Return the line file descriptor of the GPIO handle.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
This function is a simple accessor to the GPIO handle structure and always succeeds.
int gpio_name(gpio_t *gpio, char *str, size_t len);
Return the line name of the GPIO.
This method is intended for use with character device GPIOs and always returns the empty string for sysfs GPIOs.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_label(gpio_t *gpio, char *str, size_t len);
Return the line consumer label of the GPIO.
This method is intended for use with character device GPIOs and always returns the empty string for sysfs GPIOs.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_chip_fd(gpio_t *gpio);
Return the GPIO chip file descriptor of the GPIO handle.
This method is intended for use with character device GPIOs and is unsupported by sysfs GPIOs.
gpio
should be a valid pointer to a GPIO handled with one of the gpio_open*()
functions.
Returns a non-negative file descriptor on success, or a negative GPIO error code on failure.
int gpio_chip_name(gpio_t *gpio, char *str, size_t len);
Return the name of the GPIO chip associated with the GPIO.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_chip_label(gpio_t *gpio, char *str, size_t len);
Return the label of the GPIO chip associated with the GPIO.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
Returns 0 on success, or a negative GPIO error code on failure.
int gpio_tostring(gpio_t *gpio, char *str, size_t len);
Return a string representation of the GPIO handle.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
This function behaves and returns like snprintf()
.
int gpio_errno(gpio_t *gpio);
Return the libc errno of the last failure that occurred.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
This function is a simple accessor to the GPIO handle structure and always succeeds.
const char *gpio_errmsg(gpio_t *gpio);
Return a human readable error message of the last failure that occurred. The returned string should not be modified by the application.
gpio
should be a valid pointer to a GPIO handle opened with one of the gpio_open*()
functions.
This function is a simple accessor to the GPIO handle structure and always succeeds.
The periphery GPIO functions return 0 on success or one of the negative error codes below on failure.
The libc errno of the failure in an underlying libc library call can be obtained with the gpio_errno()
helper function. A human readable error message can be obtained with the gpio_errmsg()
helper function.
Error Code | Description |
---|---|
GPIO_ERROR_ARG |
Invalid arguments |
GPIO_ERROR_OPEN |
Opening GPIO |
GPIO_ERROR_NOT_FOUND |
Line name not found |
GPIO_ERROR_QUERY |
Querying GPIO attributes |
GPIO_ERROR_CONFIGURE |
Configuring GPIO attributes |
GPIO_ERROR_UNSUPPORTED |
Unsupported attribute or operation |
GPIO_ERROR_INVALID_OPERATION |
Invalid operation |
GPIO_ERROR_IO |
Reading/writing GPIO |
GPIO_ERROR_CLOSE |
Closing GPIO |
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "gpio.h"
int main(void) {
gpio_t *gpio_in, *gpio_out;
bool value;
gpio_in = gpio_new();
gpio_out = gpio_new();
/* Open GPIO /dev/gpiochip0 line 10 with input direction */
if (gpio_open(gpio_in, "/dev/gpiochip0", 10, GPIO_DIR_IN) < 0) {
fprintf(stderr, "gpio_open(): %s\n", gpio_errmsg(gpio_in));
exit(1);
}
/* Open GPIO /dev/gpiochip0 line 12 with output direction */
if (gpio_open(gpio_out, "/dev/gpiochip0", 12, GPIO_DIR_OUT) < 0) {
fprintf(stderr, "gpio_open(): %s\n", gpio_errmsg(gpio_out));
exit(1);
}
/* Read input GPIO into value */
if (gpio_read(gpio_in, &value) < 0) {
fprintf(stderr, "gpio_read(): %s\n", gpio_errmsg(gpio_in));
exit(1);
}
/* Write output GPIO with !value */
if (gpio_write(gpio_out, !value) < 0) {
fprintf(stderr, "gpio_write(): %s\n", gpio_errmsg(gpio_out));
exit(1);
}
gpio_close(gpio_in);
gpio_close(gpio_out);
gpio_free(gpio_in);
gpio_free(gpio_out);
return 0;
}