Created
April 26, 2022 09:53
-
-
Save Tosainu/79b54701269d8eee390dd89ae5d510be to your computer and use it in GitHub Desktop.
GPIO chdev v2 memo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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