From 0cfcca07ccb62bfb20b10bb152d3c03fb2153988 Mon Sep 17 00:00:00 2001 From: Vincent-FK Date: Wed, 21 Aug 2019 14:11:09 +0200 Subject: [PATCH] added sanity check of GPIO expander values after a real interrupt or a timeout --- Makefile | 42 ++-- funkey_gpio_management.c | 156 ++++++------- funkey_gpio_mapping.conf | 29 +-- gpio-utils.c | 482 +++++++++++++++++++-------------------- gpio-utils.h | 34 +-- gpio_mapping.c | 31 ++- 6 files changed, 401 insertions(+), 373 deletions(-) diff --git a/Makefile b/Makefile index 6936121..9c14bee 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,21 @@ -TOOLS_CFLAGS := -Wstrict-prototypes -Wshadow -Wpointer-arith -Wcast-qual \ - -Wcast-align -Wwrite-strings -Wnested-externs -Winline \ - -W -Wundef -Wmissing-prototypes -# -# Programs -# -all: funkey_gpio_management - -funkey_gpio_management: funkey_gpio_management.o gpio-utils.o uinput.o gpio_mapping.o read_conf_file.o keydefs.o driver_pcal6416a.o - $(CC) $(LDFLAGS) -o $@ $^ - - -# -# Objects -# - -%.o: %.c - $(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@ - -clean: - rm *.o funkey_gpio_management +TOOLS_CFLAGS := -Wstrict-prototypes -Wshadow -Wpointer-arith -Wcast-qual \ + -Wcast-align -Wwrite-strings -Wnested-externs -Winline \ + -W -Wundef -Wmissing-prototypes +# +# Programs +# +all: funkey_gpio_management + +funkey_gpio_management: funkey_gpio_management.o gpio-utils.o uinput.o gpio_mapping.o read_conf_file.o keydefs.o driver_pcal6416a.o + $(CC) $(LDFLAGS) -o $@ $^ + + +# +# Objects +# + +%.o: %.c + $(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@ + +clean: + rm *.o funkey_gpio_management diff --git a/funkey_gpio_management.c b/funkey_gpio_management.c index 8764f65..6651ef5 100644 --- a/funkey_gpio_management.c +++ b/funkey_gpio_management.c @@ -1,78 +1,78 @@ -#include -#include -#include -#include -#include -#include -#include // Defines signal-handling functions (i.e. trap Ctrl-C) -#include -#include "gpio-utils.h" -#include -#include "uinput.h" -#include "gpio_mapping.h" -#include "read_conf_file.h" - - /**************************************************************** - * Defines - ****************************************************************/ - -/**************************************************************** - * Global variables - ****************************************************************/ -int keepgoing = 1; // Set to 0 when ctrl-c is pressed - -/**************************************************************** - * signal_handler - ****************************************************************/ -void signal_handler(int sig); -// Callback called when SIGINT is sent to the process (Ctrl-C) -void signal_handler(int sig) -{ - printf( "Ctrl-C pressed, cleaning up and exiting..\n" ); - keepgoing = 0; -} - -/**************************************************************** - * Local functions - ****************************************************************/ - - -/**************************************************************** - * Main - ****************************************************************/ -int main(int argc, char **argv, char **envp) -{ - // Variables - STRUCT_MAPPED_GPIO * chained_list_mapping = NULL; - int nb_valid_gpios = 0; - int * gpio_pins = NULL; - - // Set the signal callback for Ctrl-C - signal(SIGINT, signal_handler); - - // Init uinput device - init_uinput(); - - // Read Conf File: Get GPIO pins to declare and all valid pin mappings - get_mapping_from_conf_file(&chained_list_mapping, &nb_valid_gpios, &gpio_pins); - - // Init GPIOs - init_mapping_gpios(gpio_pins, nb_valid_gpios, chained_list_mapping); - - // Main Loop - while (keepgoing) { - listen_gpios_interrupts(); - } - - // De-Init GPIOs - deinit_mapping_gpios(); - - /* - * Give userspace some time to read the events before we destroy the - * device with UI_DEV_DESTOY. - */ - close_uinput(); - - return 0; -} - +#include +#include +#include +#include +#include +#include +#include // Defines signal-handling functions (i.e. trap Ctrl-C) +#include +#include "gpio-utils.h" +#include +#include "uinput.h" +#include "gpio_mapping.h" +#include "read_conf_file.h" + + /**************************************************************** + * Defines + ****************************************************************/ + +/**************************************************************** + * Global variables + ****************************************************************/ +int keepgoing = 1; // Set to 0 when ctrl-c is pressed + +/**************************************************************** + * signal_handler + ****************************************************************/ +void signal_handler(int sig); +// Callback called when SIGINT is sent to the process (Ctrl-C) +void signal_handler(int sig) +{ + printf( "Ctrl-C pressed, cleaning up and exiting..\n" ); + keepgoing = 0; +} + +/**************************************************************** + * Local functions + ****************************************************************/ + + +/**************************************************************** + * Main + ****************************************************************/ +int main(int argc, char **argv, char **envp) +{ + // Variables + STRUCT_MAPPED_GPIO * chained_list_mapping = NULL; + int nb_valid_gpios = 0; + int * gpio_pins = NULL; + + // Set the signal callback for Ctrl-C + signal(SIGINT, signal_handler); + + // Init uinput device + init_uinput(); + + // Read Conf File: Get GPIO pins to declare and all valid pin mappings + get_mapping_from_conf_file(&chained_list_mapping, &nb_valid_gpios, &gpio_pins); + + // Init GPIOs + init_mapping_gpios(gpio_pins, nb_valid_gpios, chained_list_mapping); + + // Main Loop + while (keepgoing) { + listen_gpios_interrupts(); + } + + // De-Init GPIOs + deinit_mapping_gpios(); + + /* + * Give userspace some time to read the events before we destroy the + * device with UI_DEV_DESTOY. + */ + close_uinput(); + + return 0; +} + diff --git a/funkey_gpio_mapping.conf b/funkey_gpio_mapping.conf index 4478bda..b418351 100644 --- a/funkey_gpio_mapping.conf +++ b/funkey_gpio_mapping.conf @@ -27,29 +27,32 @@ ################################### # Mapping: -6, KEYBOARD, KEY_S, KEY_S, Start 7, KEYBOARD, KEY_F, KEY_F, Fn +6, KEYBOARD, KEY_S, KEY_S, Start +7+6, KEYBOARD, KEY_K, KEY_K, Select 3, KEYBOARD, KEY_U, KEY_U, Up +7+3, KEYBOARD, KEY_P, KEY_P, Quick Save 4, KEYBOARD, KEY_L, KEY_L, Left +7+4, KEYBOARD, KEY_J, KEY_J, Aspect ratio factor -- 1, KEYBOARD, KEY_D, KEY_D, Down +7+1, KEYBOARD, KEY_H, KEY_H, Aspect ratio mode change 0, KEYBOARD, KEY_R, KEY_R, Right +7+0, KEYBOARD, KEY_I, KEY_I, Aspect ratio factor ++ 15, KEYBOARD, KEY_N, KEY_N, R1 +# Bypass to remove when button axp working: +7+15, KEYBOARD, KEY_Q, 7+11, Launch menu +#7+15, KEYBOARD, KEY_O, KEY_O, R2 2, KEYBOARD, KEY_M, KEY_M, L1 +7+2, KEYBOARD, KEY_V, KEY_V, L2 12, KEYBOARD, KEY_B, KEY_B, B +7+12, KEYBOARD, KEY_G, KEY_G, Brightness++ 14, KEYBOARD, KEY_A, KEY_A, A +7+14, KEYBOARD, KEY_E, KEY_E, Volume-- 13, KEYBOARD, KEY_X, KEY_X, X +7+13, KEYBOARD, KEY_W, KEY_W, Brightness-- 11, KEYBOARD, KEY_Y, KEY_Y, Y -7+7, KEYBOARD, KEY_K, KEY_K, Select -7+15, KEYBOARD, KEY_V, KEY_V, L2 -7+2, KEYBOARD, KEY_O, KEY_O, R2 -#7+3, SHELL_COMMAND, echo "Volume up", 6+3, Volume up -#7+1, SHELL_COMMAND, echo "Volume down", 6+1, Volume down -#7+0, SHELL_COMMAND, echo "Brightness up", 6+0, Brightness up -#7+4, SHELL_COMMAND, echo "Brightness down", 6+4, Brightness down -7+3, SHELL_COMMAND, /root/shell_cmds/start_gpsp.sh, 6+3, start gpsp -7+1, SHELL_COMMAND, /root/shell_cmds/start_pcsx.sh, 6+1, start pcsx -7+0, SHELL_COMMAND, /root/shell_cmds/start_psnes.sh, 6+0, start psnes -7+4, SHELL_COMMAND, /root/shell_cmds/start_mednafen.sh, 6+4, start mednafen GBC -7+11, SHELL_COMMAND, /root/shell_cmds/stop_all_emulators.sh, 6+4, stop all emulators +7+11, KEYBOARD, KEY_C, KEY_C, Volume++ + + diff --git a/gpio-utils.c b/gpio-utils.c index 3355e95..88a1559 100644 --- a/gpio-utils.c +++ b/gpio-utils.c @@ -1,241 +1,241 @@ -/* Copyright (c) 2011, RidgeRun - * All rights reserved. - * -From https://www.ridgerun.com/developer/wiki/index.php/Gpio-int-test.c - - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the RidgeRun. - * 4. Neither the name of the RidgeRun nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY RIDGERUN ''AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "gpio-utils.h" -#include -#include -#include -#include -#include - -/**************************************************************** - * gpio_export - ****************************************************************/ -int gpio_export(unsigned int gpio) -{ - int fd, len; - char buf[MAX_BUF]; - - fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY); - if (fd < 0) { - perror("gpio/export"); - return fd; - } - - len = snprintf(buf, sizeof(buf), "%d", gpio); - write(fd, buf, len); - close(fd); - - return 0; -} - -/**************************************************************** - * gpio_unexport - ****************************************************************/ -int gpio_unexport(unsigned int gpio) -{ - int fd, len; - char buf[MAX_BUF]; - - fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY); - if (fd < 0) { - perror("gpio/export"); - return fd; - } - - len = snprintf(buf, sizeof(buf), "%d", gpio); - write(fd, buf, len); - close(fd); - return 0; -} - -/**************************************************************** - * gpio_set_dir - ****************************************************************/ -int gpio_set_dir(unsigned int gpio, const char* dir) -{ - int fd, len; - char buf[MAX_BUF]; - - len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/direction", gpio); - - fd = open(buf, O_WRONLY); - if (fd < 0) { - perror("gpio/direction"); - return fd; - } - - write(fd, dir, sizeof(dir)+1); - - close(fd); - return 0; -} - -/**************************************************************** - * gpio_set_value - ****************************************************************/ -int gpio_set_value(unsigned int gpio, unsigned int value) -{ - int fd, len; - char buf[MAX_BUF]; - - len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); - - fd = open(buf, O_WRONLY); - if (fd < 0) { - perror("gpio/set-value"); - return fd; - } - - if (value) - write(fd, "1", 2); - else - write(fd, "0", 2); - - close(fd); - return 0; -} - -/**************************************************************** - * gpio_get_value - ****************************************************************/ -int gpio_get_value(unsigned int gpio, unsigned int *value) -{ - int fd, len; - char buf[MAX_BUF]; - char ch; - - len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); - - fd = open(buf, O_RDONLY); - if (fd < 0) { - perror("gpio/get-value"); - return fd; - } - - read(fd, &ch, 1); - - if (ch != '0') { - *value = 1; - } else { - *value = 0; - } - - close(fd); - return 0; -} - - -/**************************************************************** - * gpio_set_edge - ****************************************************************/ - -int gpio_set_edge(unsigned int gpio, const char *edge) -{ - int fd, len; - char buf[MAX_BUF]; - - len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio); - - fd = open(buf, O_WRONLY); - if (fd < 0) { - perror("gpio/set-edge"); - return fd; - } - - write(fd, edge, strlen(edge) + 1); - close(fd); - return 0; -} - -/**************************************************************** - * gpio_fd_open - ****************************************************************/ - -int gpio_fd_open(unsigned int gpio, unsigned int dir) -{ - int fd, len; - char buf[MAX_BUF]; - - len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); - - fd = open(buf, dir | O_NONBLOCK ); - if (fd < 0) { - perror("gpio/fd_open"); - } - return fd; -} - -/**************************************************************** - * gpio_fd_close - ****************************************************************/ - -int gpio_fd_close(int fd) -{ - return close(fd); -} - -/**************************************************************** - * ain_get_value (from Mike McDonald) - * https://groups.google.com/forum/#!topic/beagleboard-ece497/SLJ5nQQ_GoU - ****************************************************************/ -int ain_get_value(unsigned int ain, unsigned int *value) -{ - int fd, len, bytesRead; - char buf[MAX_BUF]; - char adc_in[ADC_BUF]; - - len = snprintf(buf, sizeof(buf), SYSFS_AIN_DIR "/AIN%d", ain); - - fd = open(buf, O_RDONLY); - if (fd < 0) { - perror(buf); - return fd; - } - - // Read from the - bytesRead = read(fd, adc_in, ADC_BUF); - - // Turn the buffer value (a string) into an integer - if (bytesRead != -1) { - *value = atoi(adc_in); - adc_in[bytesRead] = (int)NULL; - lseek(fd, 0, SEEK_SET); - } - - // Sleep for a little to ensure that we get good ADC values - usleep(1000); - - close(fd); - return bytesRead; -} - +/* Copyright (c) 2011, RidgeRun + * All rights reserved. + * +From https://www.ridgerun.com/developer/wiki/index.php/Gpio-int-test.c + + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the RidgeRun. + * 4. Neither the name of the RidgeRun nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RIDGERUN ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gpio-utils.h" +#include +#include +#include +#include +#include + +/**************************************************************** + * gpio_export + ****************************************************************/ +int gpio_export(unsigned int gpio) +{ + int fd, len; + char buf[MAX_BUF]; + + fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY); + if (fd < 0) { + perror("gpio/export"); + return fd; + } + + len = snprintf(buf, sizeof(buf), "%d", gpio); + write(fd, buf, len); + close(fd); + + return 0; +} + +/**************************************************************** + * gpio_unexport + ****************************************************************/ +int gpio_unexport(unsigned int gpio) +{ + int fd, len; + char buf[MAX_BUF]; + + fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY); + if (fd < 0) { + perror("gpio/export"); + return fd; + } + + len = snprintf(buf, sizeof(buf), "%d", gpio); + write(fd, buf, len); + close(fd); + return 0; +} + +/**************************************************************** + * gpio_set_dir + ****************************************************************/ +int gpio_set_dir(unsigned int gpio, const char* dir) +{ + int fd, len; + char buf[MAX_BUF]; + + len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/direction", gpio); + + fd = open(buf, O_WRONLY); + if (fd < 0) { + perror("gpio/direction"); + return fd; + } + + write(fd, dir, sizeof(dir)+1); + + close(fd); + return 0; +} + +/**************************************************************** + * gpio_set_value + ****************************************************************/ +int gpio_set_value(unsigned int gpio, unsigned int value) +{ + int fd, len; + char buf[MAX_BUF]; + + len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); + + fd = open(buf, O_WRONLY); + if (fd < 0) { + perror("gpio/set-value"); + return fd; + } + + if (value) + write(fd, "1", 2); + else + write(fd, "0", 2); + + close(fd); + return 0; +} + +/**************************************************************** + * gpio_get_value + ****************************************************************/ +int gpio_get_value(unsigned int gpio, unsigned int *value) +{ + int fd, len; + char buf[MAX_BUF]; + char ch; + + len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); + + fd = open(buf, O_RDONLY); + if (fd < 0) { + perror("gpio/get-value"); + return fd; + } + + read(fd, &ch, 1); + + if (ch != '0') { + *value = 1; + } else { + *value = 0; + } + + close(fd); + return 0; +} + + +/**************************************************************** + * gpio_set_edge + ****************************************************************/ + +int gpio_set_edge(unsigned int gpio, const char *edge) +{ + int fd, len; + char buf[MAX_BUF]; + + len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio); + + fd = open(buf, O_WRONLY); + if (fd < 0) { + perror("gpio/set-edge"); + return fd; + } + + write(fd, edge, strlen(edge) + 1); + close(fd); + return 0; +} + +/**************************************************************** + * gpio_fd_open + ****************************************************************/ + +int gpio_fd_open(unsigned int gpio, unsigned int dir) +{ + int fd, len; + char buf[MAX_BUF]; + + len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); + + fd = open(buf, dir | O_NONBLOCK ); + if (fd < 0) { + perror("gpio/fd_open"); + } + return fd; +} + +/**************************************************************** + * gpio_fd_close + ****************************************************************/ + +int gpio_fd_close(int fd) +{ + return close(fd); +} + +/**************************************************************** + * ain_get_value (from Mike McDonald) + * https://groups.google.com/forum/#!topic/beagleboard-ece497/SLJ5nQQ_GoU + ****************************************************************/ +int ain_get_value(unsigned int ain, unsigned int *value) +{ + int fd, len, bytesRead; + char buf[MAX_BUF]; + char adc_in[ADC_BUF]; + + len = snprintf(buf, sizeof(buf), SYSFS_AIN_DIR "/AIN%d", ain); + + fd = open(buf, O_RDONLY); + if (fd < 0) { + perror(buf); + return fd; + } + + // Read from the + bytesRead = read(fd, adc_in, ADC_BUF); + + // Turn the buffer value (a string) into an integer + if (bytesRead != -1) { + *value = atoi(adc_in); + adc_in[bytesRead] = (int)NULL; + lseek(fd, 0, SEEK_SET); + } + + // Sleep for a little to ensure that we get good ADC values + usleep(1000); + + close(fd); + return bytesRead; +} + diff --git a/gpio-utils.h b/gpio-utils.h index 1da6ed8..b56c5ad 100644 --- a/gpio-utils.h +++ b/gpio-utils.h @@ -1,17 +1,17 @@ - -#define SYSFS_GPIO_DIR "/sys/class/gpio" -#define MAX_BUF 64 - -int gpio_export(unsigned int gpio); -int gpio_unexport(unsigned int gpio); -int gpio_set_dir(unsigned int gpio, const char* dir); -int gpio_set_value(unsigned int gpio, unsigned int value); -int gpio_get_value(unsigned int gpio, unsigned int *value); -int gpio_set_edge(unsigned int gpio, const char *edge); -int gpio_fd_open(unsigned int gpio, unsigned int dir); -int gpio_fd_close(int fd); - -// Analog in -#define ADC_BUF 1024 -#define SYSFS_AIN_DIR "/sys/devices/ocp.2/helper.11" -int ain_get_value(unsigned int ain, unsigned int *value); + +#define SYSFS_GPIO_DIR "/sys/class/gpio" +#define MAX_BUF 64 + +int gpio_export(unsigned int gpio); +int gpio_unexport(unsigned int gpio); +int gpio_set_dir(unsigned int gpio, const char* dir); +int gpio_set_value(unsigned int gpio, unsigned int value); +int gpio_get_value(unsigned int gpio, unsigned int *value); +int gpio_set_edge(unsigned int gpio, const char *edge); +int gpio_fd_open(unsigned int gpio, unsigned int dir); +int gpio_fd_close(int fd); + +// Analog in +#define ADC_BUF 1024 +#define SYSFS_AIN_DIR "/sys/devices/ocp.2/helper.11" +int ain_get_value(unsigned int ain, unsigned int *value); diff --git a/gpio_mapping.c b/gpio_mapping.c index 2125126..d63fe18 100644 --- a/gpio_mapping.c +++ b/gpio_mapping.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "gpio_mapping.h" #include "driver_pcal6416a.h" @@ -35,6 +36,10 @@ #define GPIO_ERROR_PRINTF(...) #endif +// This define forces to perform a gpio sanity check after a timeout. +// If not declared, there will be no timeout and no periodical sanity check of GPIO expander values +#define TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP 2 + /**************************************************************** * Static variables @@ -277,11 +282,23 @@ int listen_gpios_interrupts(void) memset(mask_gpio_value, false, nb_mapped_gpios*sizeof(bool)); memset(mask_gpio_current_interrupts, false, nb_mapped_gpios*sizeof(bool)); - // Note the max_fd+1 - if (select(max_fd+1, NULL, NULL, &dup, NULL) < 0) { + // Waiting for interrupt or timeout, Note the max_fd+1 +#ifdef TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP + struct timeval timeout = {TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP, 0}; + int nb_interrupts = select(max_fd+1, NULL, NULL, &dup, &timeout); +#else + int nb_interrupts = select(max_fd+1, NULL, NULL, &dup, NULL); +#endif //TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP + if(!nb_interrupts){ + // Timeout case + GPIO_PRINTF(" Timeout, forcing sanity check\n"); + // Timeout forcing a "Found interrupt" event for sanity check + interrupt_found = true; + } + else if ( nb_interrupts < 0) { perror("select"); return -1; - } + } // Check if interrupt from I2C expander // Check which cur_fd is available for read @@ -325,6 +342,14 @@ int listen_gpios_interrupts(void) GPIO_PRINTF(" --> Interrupt GPIO: %d, idx_pin: %d\n", gpio_pins[idx_gpio], idx_gpio); mask_gpio_current_interrupts[idx_gpio] = true; } + + // Sanity check: if we missed an interrupt for some reason, check if the new values are the same + if( !mask_gpio_current_interrupts[idx_gpio] && + (mask_gpio_value[idx_gpio] != previous_mask_gpio_value[idx_gpio]) ){ + // Print information + GPIO_PRINTF(" --> No Interrupt (missed) but value has changed on GPIO: %d, idx_pin: %d\n", gpio_pins[idx_gpio], idx_gpio); + mask_gpio_current_interrupts[idx_gpio] = true; + } }