From: Roman Bazalevskiy Date: Mon, 8 May 2017 20:03:13 +0000 (+0300) Subject: Вариант, нормально работающий на Orange Pi Zero (только GPIO на гребенке, i2c экстенд... X-Git-Url: https://git.rvb.name/gpio-int.git/commitdiff_plain/f66308a78b25495bfabf643168d2d9d1627b5329?ds=sidebyside Вариант, нормально работающий на Orange Pi Zero (только GPIO на гребенке, i2c экстендер в прерывания не умеет) --- f66308a78b25495bfabf643168d2d9d1627b5329 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ffd424c --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +GISRCS = gpio-int.c +GIOBJS = $(GISRCS:.c=.o) + +all: gpio-int + +gpio-int: $(GIOBJS) + $(CC) $(LDFLAGS) -o $@ $(GIOBJS) $(LIBS) + + +clean: + rm -f $(GIOBJS) + rm -f gpio-int diff --git a/gpio-int.c b/gpio-int.c new file mode 100644 index 0000000..a2045f6 --- /dev/null +++ b/gpio-int.c @@ -0,0 +1,343 @@ +/* Copyright (c) 2011, RidgeRun + * All rights reserved. + * + * Contributors include: + * Todd Fischer + * Brad Lu + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + + /**************************************************************** + * Constants + ****************************************************************/ + +#define SYSFS_GPIO_DIR "/sys/class/gpio" +#define POLL_TIMEOUT (3 * 1000) /* 3 seconds */ +#define MAX_BUF 64 + +/**************************************************************** + * 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, unsigned int out_flag) +{ + 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; + } + + if (out_flag) + write(fd, "out", 4); + else + write(fd, "in", 3); + + 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, 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; +} + +int gpio_set_level(unsigned int gpio, int level) +{ + int fd, len; + char buf[MAX_BUF]; + + len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/active_low", gpio); + + fd = open(buf, O_WRONLY); + if (fd < 0) { + perror("gpio/set-level"); + return fd; + } + + write(fd, level?"1":"0", 2); + + close(fd); + return 0; +} + +/**************************************************************** + * gpio_fd_open + ****************************************************************/ + +int gpio_fd_open(unsigned int gpio) +{ + int fd, len; + char buf[MAX_BUF]; + + len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio); + + fd = open(buf, O_RDONLY | O_NONBLOCK ); + if (fd < 0) { + perror("gpio/fd_open"); + } + return fd; +} + +/**************************************************************** + * gpio_fd_close + ****************************************************************/ + +int gpio_fd_close(int fd) +{ + return close(fd); +} + +/**************************************************************** + * Main + ****************************************************************/ + +#define OPTSTRING "e:l:" + +int main(int argc, char **argv, char **envp) +{ + struct pollfd *fdset; + int timeout, rc; + char *buf[MAX_BUF]; + unsigned int gpio; + unsigned int count; + unsigned int *gpios; + int len; + int i,j; + char valbuf; + int default_level=1; + char *default_edge="both"; + struct timespec spec; + int s,ms; + + int ch; + + while (-1 != (ch = getopt(argc, argv, OPTSTRING))) { + switch (ch) { + case 'e': + default_edge=strdup(optarg); + if ( ! ((0 == strncmp(default_edge,"rising",8)) || + (0 == strncmp(default_edge,"falling",8)) || + (0 == strncmp(default_edge,"both",8))) + ) + { + fprintf(stderr, "error: invalid edge value: %s\n", optarg); + exit(1); + } + break; + case 'l': + if ( 0 == strncmp(optarg,"low",8) ) { + default_level=1; + } else if ( 0 == strncmp(optarg,"high",8) ) { + default_level=0; + } else { + fprintf(stderr, "error: invalid level value: %s\n", optarg); + exit(1); + } + break; + case '?': + printf("Usage: gpio-int [-l level] [-e edge ] \n\n"); + printf("Waits for a change in the GPIO pins voltage level\n"); + exit(2); + } + } + + count=argc-optind; + + gpios = malloc(count*sizeof(unsigned int)); + fdset = malloc(count*sizeof(fdset[0])); + + j=0; + for (i=optind;i