Вариант, нормально работающий на Orange Pi Zero (только GPIO на гребенке, i2c экстенд... master
authorRoman Bazalevskiy <rvb@rvb.name>
Mon, 8 May 2017 20:03:13 +0000 (23:03 +0300)
committerRoman Bazalevskiy <rvb@rvb.name>
Mon, 8 May 2017 20:03:13 +0000 (23:03 +0300)
Makefile [new file with mode: 0644]
gpio-int.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..a2045f6
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <getopt.h>
+#include <time.h>
+
+ /****************************************************************
+ * 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 ] <gpio-pin...>\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<argc;i++) {
+                gpio = atoi(argv[i]);
+                gpio_unexport(gpio);
+                gpio_export(gpio);
+                gpio_set_dir(gpio, 0);
+                gpio_set_edge(gpio, default_edge);
+                gpio_set_level(gpio, default_level);
+                fdset[j].fd = gpio_fd_open(gpio);
+                fdset[j].events = POLLPRI;
+                gpios[j] = gpio;
+                j++;
+        }
+
+        timeout = POLL_TIMEOUT;
+        while (1) {
+
+                rc = poll(fdset, count, timeout);      
+
+                if (rc < 0) {
+                        printf("\npoll() failed!\n");
+                        break;
+                }
+      
+                clock_gettime(CLOCK_REALTIME, &spec);
+                for (i=0;i<count;i++) {
+                        if (fdset[i].revents & POLLPRI) {
+                                lseek(fdset[i].fd, 0, SEEK_SET);
+                                len = read(fdset[i].fd, buf, MAX_BUF);
+                                valbuf = buf[0];
+                                s=spec.tv_sec;
+                                ms = spec.tv_nsec / 1.0e6;
+                                printf("%d %c %d.%03d\n", gpios[i], valbuf, s, ms);
+                        }
+                }
+
+                fflush(stdout);
+        }
+
+        for (i=0;i<count;i++) {
+                gpio_fd_close(fdset[i].fd);
+        }
+        return 0;