summarylogtreecommitdiffstats
path: root/read-pin-base.patch
blob: 0e527c97336a75a9cdb52b6eacfd4a92d257fc5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
diff -r c53985209d09 source/event_gpio.c
--- a/source/event_gpio.c	Sun Oct 30 22:41:09 2016 +0000
+++ b/source/event_gpio.c	Thu Feb 23 18:22:28 2017 +0100
@@ -24,6 +24,7 @@
 #include <sys/epoll.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -62,17 +63,64 @@
 int thread_running = 0;
 int epfd_thread = -1;
 int epfd_blocking = -1;
+int pin_base = -1;
 
 /************* /sys/class/gpio functions ************/
+void gpio_find_chip_base()
+{
+    DIR *gpio_dir;
+    struct dirent *child;
+    char label_path[128];
+    char label[128];
+    int fd;
+
+    /* No need to search for it twice */
+    if (pin_base >= 0)
+        return;
+
+    if ((gpio_dir = opendir("/sys/class/gpio")) == NULL) {
+        pin_base = 0;
+        return;
+    }
+
+    while ((child = readdir(gpio_dir)) != NULL) {
+        if (!strstr(child->d_name, "gpiochip"))
+            continue;
+
+        if (snprintf(label_path, sizeof(label_path),
+                     "/sys/class/gpio/%s/label", child->d_name) < 0) {
+            pin_base = 0;
+            return;
+        }
+
+        if ((fd = open(label_path, O_RDONLY)) < 0) {
+            pin_base = 0;
+            return;
+        }
+
+        if (read(fd, label, sizeof(label)) > 0 &&
+            strstr(label, "pinctrl-bcm2835")) {
+            pin_base = atoi(child->d_name + 8);
+            break;
+        }
+        close(fd);
+    }
+
+    if (pin_base < 0)
+        pin_base = 0;
+}
+
 int gpio_export(unsigned int gpio)
 {
     int fd, len;
-    char str_gpio[3];
+    char str_gpio[64];
 
     if ((fd = open("/sys/class/gpio/export", O_WRONLY)) < 0)
        return -1;
 
-    len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio);
+    gpio_find_chip_base();
+
+    len = snprintf(str_gpio, sizeof(str_gpio), "%d", pin_base + gpio);
     write(fd, str_gpio, len);
     close(fd);
 
@@ -82,12 +130,14 @@
 int gpio_unexport(unsigned int gpio)
 {
     int fd, len;
-    char str_gpio[3];
+    char str_gpio[64];
 
     if ((fd = open("/sys/class/gpio/unexport", O_WRONLY)) < 0)
         return -1;
 
-    len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio);
+    gpio_find_chip_base();
+
+    len = snprintf(str_gpio, sizeof(str_gpio), "%d", pin_base + gpio);
     write(fd, str_gpio, len);
     close(fd);
 
@@ -99,9 +149,11 @@
     int retry;
     struct timespec delay;
     int fd;
-    char filename[33];
+    char filename[64];
 
-    snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/direction", gpio);
+    gpio_find_chip_base();
+
+    snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/direction", pin_base + gpio);
 
     // retry waiting for udev to set correct file permissions
     delay.tv_sec = 0;
@@ -126,9 +178,11 @@
 int gpio_set_edge(unsigned int gpio, unsigned int edge)
 {
     int fd;
-    char filename[28];
+    char filename[64];
 
-    snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio);
+    gpio_find_chip_base();
+
+    snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", pin_base + gpio);
 
     if ((fd = open(filename, O_WRONLY)) < 0)
         return -1;
@@ -141,10 +195,12 @@
 int open_value_file(unsigned int gpio)
 {
     int fd;
-    char filename[29];
+    char filename[64];
+
+    gpio_find_chip_base();
 
     // create file descriptor of value file
-    snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", gpio);
+    snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", pin_base + gpio);
     if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0)
         return -1;
     return fd;