Skip to content

Instantly share code, notes, and snippets.

@Tosainu
Created April 26, 2022 09:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tosainu/79b54701269d8eee390dd89ae5d510be to your computer and use it in GitHub Desktop.
Save Tosainu/79b54701269d8eee390dd89ae5d510be to your computer and use it in GitHub Desktop.
GPIO chdev v2 memo
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/gpio.h>
static void perror_exit(const char* s) {
perror(s);
exit(1);
}
int main() {
int fd = open("/dev/gpiochip0", O_RDWR | O_CLOEXEC);
if (fd < 0) {
perror_exit("open");
}
printf("[+] open(\"/dev/gpiochip0\") = %d\n", fd);
puts("");
struct gpiochip_info info;
if (ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &info) < 0) {
perror_exit("GPIO_GET_CHIPINFO_IOCTL");
}
printf("[+] info.name = \"%s\"\n", info.name);
printf("[+] info.label = \"%s\"\n", info.label);
printf("[+] info.lines = \"%u\"\n", info.lines);
puts("");
for (unsigned int offset = 0; offset < info.lines; ++offset) {
struct gpio_v2_line_info line = {
.offset = offset,
};
if (ioctl(fd, GPIO_V2_GET_LINEINFO_IOCTL, &line) < 0) {
perror_exit("GPIO_V2_GET_LINEINFO_IOCTL");
}
printf("[+] %3u: %08llx, name = \"%s\", consumer = \"%s\"\n", offset, line.flags, line.name,
line.consumer);
}
puts("");
puts("[+] gpio_v2_line_flag");
#define PRINT_FLAG(flag) printf("[+] %08llx: " #flag "\n", (long long unsigned int)flag);
PRINT_FLAG(GPIO_V2_LINE_FLAG_USED);
PRINT_FLAG(GPIO_V2_LINE_FLAG_ACTIVE_LOW);
PRINT_FLAG(GPIO_V2_LINE_FLAG_INPUT);
PRINT_FLAG(GPIO_V2_LINE_FLAG_OUTPUT);
PRINT_FLAG(GPIO_V2_LINE_FLAG_EDGE_RISING);
PRINT_FLAG(GPIO_V2_LINE_FLAG_EDGE_FALLING);
PRINT_FLAG(GPIO_V2_LINE_FLAG_OPEN_DRAIN);
PRINT_FLAG(GPIO_V2_LINE_FLAG_OPEN_SOURCE);
PRINT_FLAG(GPIO_V2_LINE_FLAG_BIAS_PULL_UP);
PRINT_FLAG(GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN);
PRINT_FLAG(GPIO_V2_LINE_FLAG_BIAS_DISABLED);
PRINT_FLAG(GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME);
#undef PRINT_FLAG
puts("");
puts("[+] waiting MIO23 (SW1) rising edge event");
{
struct gpio_v2_line_request req;
memset(&req, 0, sizeof req);
req.offsets[0] = 23;
req.num_lines = 1;
req.config.flags = GPIO_V2_LINE_FLAG_INPUT | GPIO_V2_LINE_FLAG_EDGE_RISING;
req.config.num_attrs = 0;
if (ioctl(fd, GPIO_V2_GET_LINE_IOCTL, &req) < 0) {
perror_exit("GPIO_V2_GET_LINE_IOCTL");
}
for (int i = 0; i < 10; ++i) {
struct gpio_v2_line_event event;
int ret = read(req.fd, &event, sizeof event);
if (ret < 0) {
perror_exit("read");
}
if (ret != sizeof event) {
return 1;
}
printf("[+] event.id = %02x\n", event.id);
}
close(req.fd);
}
puts("");
puts("[+] waiting MIO23 (SW1) falling edge event");
{
struct gpio_v2_line_request req;
memset(&req, 0, sizeof req);
req.offsets[0] = 23;
req.num_lines = 1;
req.config.flags = GPIO_V2_LINE_FLAG_INPUT | GPIO_V2_LINE_FLAG_EDGE_FALLING;
req.config.num_attrs = 0;
if (ioctl(fd, GPIO_V2_GET_LINE_IOCTL, &req) < 0) {
perror_exit("GPIO_V2_GET_LINE_IOCTL");
}
for (int i = 0; i < 10; ++i) {
struct gpio_v2_line_event event;
int ret = read(req.fd, &event, sizeof event);
if (ret < 0) {
perror_exit("read");
}
if (ret != sizeof event) {
return 1;
}
printf("[+] event.id = %02x\n", event.id);
}
close(req.fd);
}
puts("");
puts("[+] waiting MIO23 (SW1) both edges event");
{
struct gpio_v2_line_request req;
memset(&req, 0, sizeof req);
req.offsets[0] = 23;
req.num_lines = 1;
req.config.flags =
GPIO_V2_LINE_FLAG_INPUT | GPIO_V2_LINE_FLAG_EDGE_FALLING | GPIO_V2_LINE_FLAG_EDGE_RISING;
req.config.num_attrs = 0;
if (ioctl(fd, GPIO_V2_GET_LINE_IOCTL, &req) < 0) {
perror_exit("GPIO_V2_GET_LINE_IOCTL");
}
for (int i = 0; i < 10; ++i) {
struct gpio_v2_line_event event;
int ret = read(req.fd, &event, sizeof event);
if (ret < 0) {
perror_exit("read");
}
if (ret != sizeof event) {
return 1;
}
printf("[+] event.id = %02x\n", event.id);
}
close(req.fd);
}
puts("");
puts("[+] MIO19 (LED1) blink");
{
struct gpio_v2_line_request req;
memset(&req, 0, sizeof req);
req.offsets[0] = 19;
req.num_lines = 1;
req.config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
req.config.num_attrs = 1;
req.config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;
req.config.attrs[0].mask = 1;
req.config.attrs[0].attr.values = 1; // initial value = 1
if (ioctl(fd, GPIO_V2_GET_LINE_IOCTL, &req) < 0) {
perror_exit("GPIO_V2_GET_LINE_IOCTL");
}
for (int i = 0; i < 20; ++i) {
struct gpio_v2_line_values values;
usleep(500000); // 500 ms
values.mask = 1;
values.bits = 0;
if (ioctl(req.fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values) < 0) {
perror_exit("GPIO_V2_LINE_SET_VALUES_IOCTL");
}
if (ioctl(req.fd, GPIO_V2_LINE_GET_VALUES_IOCTL, &values) < 0) {
perror_exit("GPIO_V2_LINE_GET_VALUES_IOCTL");
}
printf("[+] values.bits = %08x\n", values.bits);
usleep(500000); // 500 ms
values.mask = 1;
values.bits = 1;
if (ioctl(req.fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values) < 0) {
perror_exit("GPIO_V2_LINE_SET_VALUES_IOCTL");
}
if (ioctl(req.fd, GPIO_V2_LINE_GET_VALUES_IOCTL, &values) < 0) {
perror_exit("GPIO_V2_LINE_GET_VALUES_IOCTL");
}
printf("[+] values.bits = %08x\n", values.bits);
}
close(req.fd);
}
close(fd);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment