#include #include #include #include #include #include #include #include "gpio.h" #include "timespec.h" #include "ping_pong.h" #define LAST_PONG_TIMEOUT (PING_INTERVAL * 3) /* 17 red (11) 27 green (13) 22 blue (15) */ /* 19 switch (35) 26 switch (37) */ #define RED 0b001 #define GREEN 0b010 #define BLUE 0b100 int gpio_open(const char * path, struct gpio_state * gpio_state) { gpio_state->chip_fd = open(path, O_RDWR); if (gpio_state->chip_fd == -1) { perror("open gpio"); return -1; } struct gpio_v2_line_request request_leds = { .offsets = { 17, 27, 22 }, .consumer = "timer-leds", .config = { .flags = GPIO_V2_LINE_FLAG_OUTPUT, }, .num_lines = 3, }; int ret1 = ioctl(gpio_state->chip_fd, GPIO_V2_GET_LINE_IOCTL, &request_leds); if (ret1 == -1) { gpio_state->chip_fd = -1; perror("GPIO_V2_GET_LINE_IOCTL timer-leds"); return -1; } gpio_state->led_request_fd = request_leds.fd; struct gpio_v2_line_request request_switch = { .offsets = { 19, 26 }, .consumer = "timer-switch", .config = { .flags = GPIO_V2_LINE_FLAG_INPUT | GPIO_V2_LINE_FLAG_BIAS_PULL_UP, }, .num_lines = 2, }; int ret2 = ioctl(gpio_state->chip_fd, GPIO_V2_GET_LINE_IOCTL, &request_switch); if (ret2 == -1) { gpio_state->chip_fd = -1; perror("GPIO_V2_GET_LINE_IOCTL timer-switch"); return -1; } gpio_state->switch_request_fd = request_switch.fd; return 0; } void gpio_set_values(struct gpio_state * gpio_state, uint64_t bits) { if (gpio_state->chip_fd == -1) { return; } struct gpio_v2_line_values values = { .bits = bits, .mask = 0b111, }; int ret = ioctl(gpio_state->led_request_fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values); assert(ret != -1); } uint64_t gpio_get_values(struct gpio_state * gpio_state) { if (gpio_state->chip_fd == -1) { return 0; } struct gpio_v2_line_values values = { .mask = 0b11, }; int ret = ioctl(gpio_state->switch_request_fd, GPIO_V2_LINE_GET_VALUES_IOCTL, &values); assert(ret != -1); return (~values.bits) & 0b11; } void gpio_set_values_from_link_states(struct gpio_state * gpio_state, struct link_state * link_states, int link_states_length) { struct timespec now; int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &now); assert(ret != -1); int error = 0; for (int i = 0; i < link_states_length; i++) { struct timespec delta = timespec_sub(&now, &link_states[i].last_pong); if (delta.tv_sec >= LAST_PONG_TIMEOUT) { printf("[%d] gpio pong timeout %ld\n", i, delta.tv_sec); error |= 1 << (i % 2); } else { printf("[%d] gpio pong ok %ld\n", i, delta.tv_sec); } } if (error == 0) { gpio_set_values(gpio_state, GREEN); } else { int color = 0; if (error & 0b01) color |= RED; if (error & 0b10) color |= BLUE; gpio_set_values(gpio_state, color); } } /* int main() { struct gpio_state gpio_state; gpio_open("/dev/gpiochip0", &gpio_state); set_gpio_values(&gpio_state, 0b000); } */