mirror of
https://github.com/FunKey-Project/FunKey-GPIO-Mapping.git
synced 2025-12-12 17:58:54 +01:00
added sanity check of GPIO expander values after a real interrupt or a timeout
This commit is contained in:
parent
4c3f0eca57
commit
0cfcca07cc
42
Makefile
42
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
|
||||
|
||||
@ -1,78 +1,78 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h> // Defines signal-handling functions (i.e. trap Ctrl-C)
|
||||
#include <sys/select.h>
|
||||
#include "gpio-utils.h"
|
||||
#include <assert.h>
|
||||
#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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h> // Defines signal-handling functions (i.e. trap Ctrl-C)
|
||||
#include <sys/select.h>
|
||||
#include "gpio-utils.h"
|
||||
#include <assert.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@ -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++
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
482
gpio-utils.c
482
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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
/****************************************************************
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
/****************************************************************
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
34
gpio-utils.h
34
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);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <linux/input.h>
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user