rpi_gpio 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,43 +0,0 @@
1
- /*
2
- Copyright (c) 2013-2015 Ben Croston
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy of
5
- this software and associated documentation files (the "Software"), to deal in
6
- the Software without restriction, including without limitation the rights to
7
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8
- of the Software, and to permit persons to whom the Software is furnished to do
9
- so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
- SOFTWARE.
21
- */
22
-
23
- #include "cpuinfo.h"
24
-
25
- #define MODE_UNKNOWN -1
26
- #define BOARD 10
27
- #define BCM 11
28
- #define SERIAL 40
29
- #define SPI 41
30
- #define I2C 42
31
- #define PWM 43
32
-
33
- int gpio_mode;
34
- const int pin_to_gpio_rev1[41];
35
- const int pin_to_gpio_rev2[41];
36
- const int pin_to_gpio_rev3[41];
37
- const int (*pin_to_gpio)[41];
38
- int gpio_direction[54];
39
- rpi_info rpiinfo;
40
- int setup_error;
41
- int module_setup;
42
- int check_gpio_priv(void);
43
- int get_gpio_number(int channel, unsigned int *gpio);
@@ -1,84 +0,0 @@
1
- /*
2
- Copyright (c) 2013-2015 Ben Croston
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy of
5
- this software and associated documentation files (the "Software"), to deal in
6
- the Software without restriction, including without limitation the rights to
7
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8
- of the Software, and to permit persons to whom the Software is furnished to do
9
- so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
- SOFTWARE.
21
- */
22
-
23
- #include "Python.h"
24
- #include "constants.h"
25
- #include "common.h"
26
- #include "c_gpio.h"
27
- #include "event_gpio.h"
28
-
29
- void define_constants(PyObject *module)
30
- {
31
- high = Py_BuildValue("i", HIGH);
32
- PyModule_AddObject(module, "HIGH", high);
33
-
34
- low = Py_BuildValue("i", LOW);
35
- PyModule_AddObject(module, "LOW", low);
36
-
37
- output = Py_BuildValue("i", OUTPUT);
38
- PyModule_AddObject(module, "OUT", output);
39
-
40
- input = Py_BuildValue("i", INPUT);
41
- PyModule_AddObject(module, "IN", input);
42
-
43
- pwm = Py_BuildValue("i", PWM);
44
- PyModule_AddObject(module, "HARD_PWM", pwm);
45
-
46
- serial = Py_BuildValue("i", SERIAL);
47
- PyModule_AddObject(module, "SERIAL", serial);
48
-
49
- i2c = Py_BuildValue("i", I2C);
50
- PyModule_AddObject(module, "I2C", i2c);
51
-
52
- spi = Py_BuildValue("i", SPI);
53
- PyModule_AddObject(module, "SPI", spi);
54
-
55
- unknown = Py_BuildValue("i", MODE_UNKNOWN);
56
- PyModule_AddObject(module, "UNKNOWN", unknown);
57
-
58
- board = Py_BuildValue("i", BOARD);
59
- PyModule_AddObject(module, "BOARD", board);
60
-
61
- bcm = Py_BuildValue("i", BCM);
62
- PyModule_AddObject(module, "BCM", bcm);
63
-
64
- pud_off = Py_BuildValue("i", PUD_OFF + PY_PUD_CONST_OFFSET);
65
- PyModule_AddObject(module, "PUD_OFF", pud_off);
66
-
67
- pud_up = Py_BuildValue("i", PUD_UP + PY_PUD_CONST_OFFSET);
68
- PyModule_AddObject(module, "PUD_UP", pud_up);
69
-
70
- pud_down = Py_BuildValue("i", PUD_DOWN + PY_PUD_CONST_OFFSET);
71
- PyModule_AddObject(module, "PUD_DOWN", pud_down);
72
-
73
- rising_edge = Py_BuildValue("i", RISING_EDGE + PY_EVENT_CONST_OFFSET);
74
- PyModule_AddObject(module, "RISING", rising_edge);
75
-
76
- falling_edge = Py_BuildValue("i", FALLING_EDGE + PY_EVENT_CONST_OFFSET);
77
- PyModule_AddObject(module, "FALLING", falling_edge);
78
-
79
- both_edge = Py_BuildValue("i", BOTH_EDGE + PY_EVENT_CONST_OFFSET);
80
- PyModule_AddObject(module, "BOTH", both_edge);
81
-
82
- version = Py_BuildValue("s", "0.5.11");
83
- PyModule_AddObject(module, "VERSION", version);
84
- }
@@ -1,45 +0,0 @@
1
- /*
2
- Copyright (c) 2013 Ben Croston
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy of
5
- this software and associated documentation files (the "Software"), to deal in
6
- the Software without restriction, including without limitation the rights to
7
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8
- of the Software, and to permit persons to whom the Software is furnished to do
9
- so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
- SOFTWARE.
21
- */
22
-
23
- #define PY_PUD_CONST_OFFSET 20
24
- #define PY_EVENT_CONST_OFFSET 30
25
-
26
- PyObject *high;
27
- PyObject *low;
28
- PyObject *input;
29
- PyObject *output;
30
- PyObject *pwm;
31
- PyObject *serial;
32
- PyObject *i2c;
33
- PyObject *spi;
34
- PyObject *unknown;
35
- PyObject *board;
36
- PyObject *bcm;
37
- PyObject *pud_off;
38
- PyObject *pud_up;
39
- PyObject *pud_down;
40
- PyObject *rising_edge;
41
- PyObject *falling_edge;
42
- PyObject *both_edge;
43
- PyObject *version;
44
-
45
- void define_constants(PyObject *module);
@@ -1,149 +0,0 @@
1
- /*
2
- Copyright (c) 2012-2015 Ben Croston
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy of
5
- this software and associated documentation files (the "Software"), to deal in
6
- the Software without restriction, including without limitation the rights to
7
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8
- of the Software, and to permit persons to whom the Software is furnished to do
9
- so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
- SOFTWARE.
21
- */
22
-
23
- #include <stdio.h>
24
- #include <stdlib.h>
25
- #include <string.h>
26
- #include "cpuinfo.h"
27
-
28
- int get_rpi_info(rpi_info *info)
29
- {
30
- FILE *fp;
31
- char buffer[1024];
32
- char hardware[1024];
33
- char revision[1024];
34
- char *rev;
35
- int found = 0;
36
- int len;
37
-
38
- if ((fp = fopen("/proc/cpuinfo", "r")) == NULL)
39
- return -1;
40
- while(!feof(fp)) {
41
- fgets(buffer, sizeof(buffer) , fp);
42
- sscanf(buffer, "Hardware : %s", hardware);
43
- if (strcmp(hardware, "BCM2708") == 0 ||
44
- strcmp(hardware, "BCM2709") == 0 ||
45
- strcmp(hardware, "BCM2835") == 0 ||
46
- strcmp(hardware, "BCM2836") == 0) {
47
- found = 1;
48
- }
49
- sscanf(buffer, "Revision : %s", revision);
50
- }
51
- fclose(fp);
52
-
53
- if (!found)
54
- return -1;
55
-
56
- if ((len = strlen(revision)) == 0)
57
- return -1;
58
-
59
- if (len >= 6 && strtol((char[]){revision[len-6],0}, NULL, 16) & 8) {
60
- // new scheme
61
- //info->rev = revision[len-1]-'0';
62
- strcpy(info->revision, revision);
63
- switch (revision[len-2]) {
64
- case '0': info->type = "Model A"; info->p1_revision = 2; break;
65
- case '1': info->type = "Model B"; info->p1_revision = 2; break;
66
- case '2': info->type = "Model A+"; info->p1_revision = 3; break;
67
- case '3': info->type = "Model B+"; info->p1_revision = 3; break;
68
- case '4': info->type = "Pi2 Model B"; info->p1_revision = 3; break;
69
- case '5': info->type = "Alpha"; info->p1_revision = 3; break;
70
- case '6': info->type = "Compute"; info->p1_revision = 0; break;
71
- default : info->type = "Unknown"; info->p1_revision = 3; break;
72
- }
73
- switch (revision[len-4]) {
74
- case '0': info->processor = "BCM2835"; break;
75
- case '1': info->processor = "BCM2836"; break;
76
- default : info->processor = "Unknown"; break;
77
- }
78
- switch (revision[len-5]) {
79
- case '0': info->manufacturer = "Sony"; break;
80
- case '1': info->manufacturer = "Egoman"; break;
81
- case '2': info->manufacturer = "Embest"; break;
82
- case '4': info->manufacturer = "Embest"; break;
83
- default : info->manufacturer = "Unknown"; break;
84
- }
85
- switch (strtol((char[]){revision[len-6],0}, NULL, 16) & 7) {
86
- case 0: info->ram = "256M"; break;
87
- case 1: info->ram = "512M"; break;
88
- case 2: info->ram = "1024M"; break;
89
- default: info->ram = "Unknown"; break;
90
- }
91
- } else {
92
- // old scheme
93
- info->ram = "Unknown";
94
- info->manufacturer = "Unknown";
95
- info->processor = "Unknown";
96
- info->type = "Unknown";
97
- strcpy(info->revision, revision);
98
-
99
- // get last four characters (ignore preceeding 1000 for overvolt)
100
- if (len > 4)
101
- rev = (char *)&revision+len-4;
102
- else
103
- rev = revision;
104
-
105
- if ((strcmp(rev, "0002") == 0) ||
106
- (strcmp(rev, "0003") == 0))
107
- info->p1_revision = 1;
108
- else if ((strcmp(rev, "0004") == 0) ||
109
- (strcmp(rev, "0005") == 0) ||
110
- (strcmp(rev, "0006") == 0) ||
111
- (strcmp(rev, "0007") == 0) ||
112
- (strcmp(rev, "0008") == 0) ||
113
- (strcmp(rev, "0009") == 0) ||
114
- (strcmp(rev, "000d") == 0) ||
115
- (strcmp(rev, "000e") == 0) ||
116
- (strcmp(rev, "000f") == 0))
117
- info->p1_revision = 2;
118
- else if (strcmp(rev, "0011") == 0)
119
- info->p1_revision = 0; // compute module
120
- else // assume B+ (0010) or A+ (0012) or RPi2
121
- info->p1_revision = 3;
122
- }
123
- return 0;
124
- }
125
-
126
- /*
127
-
128
- 32 bits
129
- NEW 23: will be 1 for the new scheme, 0 for the old scheme
130
- MEMSIZE 20: 0=256M 1=512M 2=1G
131
- MANUFACTURER 16: 0=SONY 1=EGOMAN
132
- PROCESSOR 12: 0=2835 1=2836
133
- TYPE 04: 0=MODELA 1=MODELB 2=MODELA+ 3=MODELB+ 4=Pi2 MODEL B 5=ALPHA 6=CM
134
- REV 00: 0=REV0 1=REV1 2=REV2
135
-
136
- pi2 = 1<<23 | 2<<20 | 1<<12 | 4<<4 = 0xa01040
137
-
138
- --------------------
139
-
140
- SRRR MMMM PPPP TTTT TTTT VVVV
141
-
142
- S scheme (0=old, 1=new)
143
- R RAM (0=256, 1=512, 2=1024)
144
- M manufacturer (0='SONY',1='EGOMAN',2='EMBEST',3='UNKNOWN',4='EMBEST')
145
- P processor (0=2835, 1=2836)
146
- T type (0='A', 1='B', 2='A+', 3='B+', 4='Pi 2 B', 5='Alpha', 6='Compute Module')
147
- V revision (0-15)
148
-
149
- */
@@ -1,36 +0,0 @@
1
- /*
2
- Copyright (c) 2012-2015 Ben Croston
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy of
5
- this software and associated documentation files (the "Software"), to deal in
6
- the Software without restriction, including without limitation the rights to
7
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8
- of the Software, and to permit persons to whom the Software is furnished to do
9
- so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
- SOFTWARE.
21
- */
22
-
23
- #ifndef CPUINFO_H
24
- #define CPUINFO_H
25
- typedef struct
26
- {
27
- int p1_revision;
28
- char *ram;
29
- char *manufacturer;
30
- char *processor;
31
- char *type;
32
- char revision[1024];
33
- } rpi_info;
34
- #endif /* CPUINFO_H */
35
-
36
- int get_rpi_info(rpi_info *info);
@@ -1,550 +0,0 @@
1
- /*
2
- Copyright (c) 2013-2014 Ben Croston
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy of
5
- this software and associated documentation files (the "Software"), to deal in
6
- the Software without restriction, including without limitation the rights to
7
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8
- of the Software, and to permit persons to whom the Software is furnished to do
9
- so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
- SOFTWARE.
21
- */
22
-
23
- #include <pthread.h>
24
- #include <sys/epoll.h>
25
- #include <stdio.h>
26
- #include <stdlib.h>
27
- #include <fcntl.h>
28
- #include <unistd.h>
29
- #include <string.h>
30
- #include <sys/time.h>
31
- #include "event_gpio.h"
32
-
33
- const char *stredge[4] = {"none", "rising", "falling", "both"};
34
-
35
- struct gpios
36
- {
37
- unsigned int gpio;
38
- int value_fd;
39
- int exported;
40
- int edge;
41
- int initial_thread;
42
- int initial_wait;
43
- int thread_added;
44
- int bouncetime;
45
- unsigned long long lastcall;
46
- struct gpios *next;
47
- };
48
- struct gpios *gpio_list = NULL;
49
-
50
- // event callbacks
51
- struct callback
52
- {
53
- unsigned int gpio;
54
- void (*func)(unsigned int gpio);
55
- struct callback *next;
56
- };
57
- struct callback *callbacks = NULL;
58
-
59
- pthread_t threads;
60
- int event_occurred[54] = { 0 };
61
- int thread_running = 0;
62
- int epfd_thread = -1;
63
- int epfd_blocking = -1;
64
-
65
- /************* /sys/class/gpio functions ************/
66
- int gpio_export(unsigned int gpio)
67
- {
68
- int fd, len;
69
- char str_gpio[3];
70
-
71
- if ((fd = open("/sys/class/gpio/export", O_WRONLY)) < 0)
72
- return -1;
73
-
74
- len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio);
75
- write(fd, str_gpio, len);
76
- close(fd);
77
-
78
- return 0;
79
- }
80
-
81
- int gpio_unexport(unsigned int gpio)
82
- {
83
- int fd, len;
84
- char str_gpio[3];
85
-
86
- if ((fd = open("/sys/class/gpio/unexport", O_WRONLY)) < 0)
87
- return -1;
88
-
89
- len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio);
90
- write(fd, str_gpio, len);
91
- close(fd);
92
-
93
- return 0;
94
- }
95
-
96
- int gpio_set_direction(unsigned int gpio, unsigned int in_flag)
97
- {
98
- int fd;
99
- char filename[33];
100
-
101
- snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/direction", gpio);
102
- if ((fd = open(filename, O_WRONLY)) < 0)
103
- return -1;
104
-
105
- if (in_flag)
106
- write(fd, "in", 3);
107
- else
108
- write(fd, "out", 4);
109
-
110
- close(fd);
111
- return 0;
112
- }
113
-
114
- int gpio_set_edge(unsigned int gpio, unsigned int edge)
115
- {
116
- int fd;
117
- char filename[28];
118
-
119
- snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio);
120
-
121
- if ((fd = open(filename, O_WRONLY)) < 0)
122
- return -1;
123
-
124
- write(fd, stredge[edge], strlen(stredge[edge]) + 1);
125
- close(fd);
126
- return 0;
127
- }
128
-
129
- int open_value_file(unsigned int gpio)
130
- {
131
- int fd;
132
- char filename[29];
133
-
134
- // create file descriptor of value file
135
- snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", gpio);
136
- if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0)
137
- return -1;
138
- return fd;
139
- }
140
-
141
- /********* gpio list functions **********/
142
- struct gpios *get_gpio(unsigned int gpio)
143
- {
144
- struct gpios *g = gpio_list;
145
- while (g != NULL) {
146
- if (g->gpio == gpio)
147
- return g;
148
- g = g->next;
149
- }
150
- return NULL;
151
- }
152
-
153
- struct gpios *get_gpio_from_value_fd(int fd)
154
- {
155
- struct gpios *g = gpio_list;
156
- while (g != NULL) {
157
- if (g->value_fd == fd)
158
- return g;
159
- g = g->next;
160
- }
161
- return NULL;
162
- }
163
-
164
- struct gpios *new_gpio(unsigned int gpio)
165
- {
166
- struct gpios *new_gpio;
167
-
168
- new_gpio = malloc(sizeof(struct gpios));
169
- if (new_gpio == 0)
170
- return NULL; // out of memory
171
-
172
- new_gpio->gpio = gpio;
173
- if (gpio_export(gpio) != 0) {
174
- free(new_gpio);
175
- return NULL;
176
- }
177
- new_gpio->exported = 1;
178
-
179
- if (gpio_set_direction(gpio,1) != 0) { // 1==input
180
- free(new_gpio);
181
- return NULL;
182
- }
183
-
184
- if ((new_gpio->value_fd = open_value_file(gpio)) == -1) {
185
- gpio_unexport(gpio);
186
- free(new_gpio);
187
- return NULL;
188
- }
189
-
190
- new_gpio->initial_thread = 1;
191
- new_gpio->initial_wait = 1;
192
- new_gpio->bouncetime = -666;
193
- new_gpio->lastcall = 0;
194
- new_gpio->thread_added = 0;
195
-
196
- if (gpio_list == NULL) {
197
- new_gpio->next = NULL;
198
- } else {
199
- new_gpio->next = gpio_list;
200
- }
201
- gpio_list = new_gpio;
202
- return new_gpio;
203
- }
204
-
205
- void delete_gpio(unsigned int gpio)
206
- {
207
- struct gpios *g = gpio_list;
208
- struct gpios *temp;
209
- struct gpios *prev = NULL;
210
-
211
- while (g != NULL) {
212
- if (g->gpio == gpio) {
213
- if (prev == NULL)
214
- gpio_list = g->next;
215
- else
216
- prev->next = g->next;
217
- temp = g;
218
- g = g->next;
219
- free(temp);
220
- return;
221
- } else {
222
- prev = g;
223
- g = g->next;
224
- }
225
- }
226
- }
227
-
228
- int gpio_event_added(unsigned int gpio)
229
- {
230
- struct gpios *g = gpio_list;
231
- while (g != NULL) {
232
- if (g->gpio == gpio)
233
- return g->edge;
234
- g = g->next;
235
- }
236
- return 0;
237
- }
238
-
239
- /******* callback list functions ********/
240
- int add_edge_callback(unsigned int gpio, void (*func)(unsigned int gpio))
241
- {
242
- struct callback *cb = callbacks;
243
- struct callback *new_cb;
244
-
245
- new_cb = malloc(sizeof(struct callback));
246
- if (new_cb == 0)
247
- return -1; // out of memory
248
-
249
- new_cb->gpio = gpio;
250
- new_cb->func = func;
251
- new_cb->next = NULL;
252
-
253
- if (callbacks == NULL) {
254
- // start new list
255
- callbacks = new_cb;
256
- } else {
257
- // add to end of list
258
- while (cb->next != NULL)
259
- cb = cb->next;
260
- cb->next = new_cb;
261
- }
262
- return 0;
263
- }
264
-
265
- int callback_exists(unsigned int gpio)
266
- {
267
- struct callback *cb = callbacks;
268
- while (cb != NULL) {
269
- if (cb->gpio == gpio)
270
- return 1;
271
- cb = cb->next;
272
- }
273
- return 0;
274
- }
275
-
276
- void run_callbacks(unsigned int gpio)
277
- {
278
- struct callback *cb = callbacks;
279
- while (cb != NULL)
280
- {
281
- if (cb->gpio == gpio)
282
- cb->func(cb->gpio);
283
- cb = cb->next;
284
- }
285
- }
286
-
287
- void remove_callbacks(unsigned int gpio)
288
- {
289
- struct callback *cb = callbacks;
290
- struct callback *temp;
291
- struct callback *prev = NULL;
292
-
293
- while (cb != NULL)
294
- {
295
- if (cb->gpio == gpio)
296
- {
297
- if (prev == NULL)
298
- callbacks = cb->next;
299
- else
300
- prev->next = cb->next;
301
- temp = cb;
302
- cb = cb->next;
303
- free(temp);
304
- } else {
305
- prev = cb;
306
- cb = cb->next;
307
- }
308
- }
309
- }
310
-
311
- void *poll_thread(void *threadarg)
312
- {
313
- struct epoll_event events;
314
- char buf;
315
- struct timeval tv_timenow;
316
- unsigned long long timenow;
317
- struct gpios *g;
318
- int n;
319
-
320
- thread_running = 1;
321
- while (thread_running) {
322
- if ((n = epoll_wait(epfd_thread, &events, 1, -1)) == -1) {
323
- thread_running = 0;
324
- pthread_exit(NULL);
325
- }
326
- if (n > 0) {
327
- lseek(events.data.fd, 0, SEEK_SET);
328
- if (read(events.data.fd, &buf, 1) != 1) {
329
- thread_running = 0;
330
- pthread_exit(NULL);
331
- }
332
- g = get_gpio_from_value_fd(events.data.fd);
333
- if (g->initial_thread) { // ignore first epoll trigger
334
- g->initial_thread = 0;
335
- } else {
336
- gettimeofday(&tv_timenow, NULL);
337
- timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec;
338
- if (g->bouncetime == -666 || timenow - g->lastcall > g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) {
339
- g->lastcall = timenow;
340
- event_occurred[g->gpio] = 1;
341
- run_callbacks(g->gpio);
342
- }
343
- }
344
- }
345
- }
346
- thread_running = 0;
347
- pthread_exit(NULL);
348
- }
349
-
350
- void remove_edge_detect(unsigned int gpio)
351
- {
352
- struct epoll_event ev;
353
- struct gpios *g = get_gpio(gpio);
354
-
355
- if (g == NULL)
356
- return;
357
-
358
- // delete epoll of fd
359
-
360
- ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
361
- ev.data.fd = g->value_fd;
362
- epoll_ctl(epfd_thread, EPOLL_CTL_DEL, g->value_fd, &ev);
363
-
364
- // delete callbacks for gpio
365
- remove_callbacks(gpio);
366
-
367
- // btc fixme - check return result??
368
- gpio_set_edge(gpio, NO_EDGE);
369
- g->edge = NO_EDGE;
370
-
371
- if (g->value_fd != -1)
372
- close(g->value_fd);
373
-
374
- // btc fixme - check return result??
375
- gpio_unexport(gpio);
376
- event_occurred[gpio] = 0;
377
-
378
- delete_gpio(gpio);
379
- }
380
-
381
- int event_detected(unsigned int gpio)
382
- {
383
- if (event_occurred[gpio]) {
384
- event_occurred[gpio] = 0;
385
- return 1;
386
- } else {
387
- return 0;
388
- }
389
- }
390
-
391
- void event_cleanup(unsigned int gpio)
392
- // gpio of -666 means clean every channel used
393
- {
394
- struct gpios *g = gpio_list;
395
- struct gpios *temp = NULL;
396
-
397
- while (g != NULL) {
398
- if ((gpio == -666) || (g->gpio == gpio))
399
- temp = g->next;
400
- remove_edge_detect(g->gpio);
401
- g = temp;
402
- }
403
- if (gpio_list == NULL)
404
- if (epfd_blocking != -1)
405
- close(epfd_blocking);
406
- epfd_blocking = -1;
407
- if (epfd_thread != -1)
408
- close(epfd_thread);
409
- epfd_thread = -1;
410
- thread_running = 0;
411
- }
412
-
413
- void event_cleanup_all(void)
414
- {
415
- event_cleanup(-666);
416
- }
417
-
418
- int add_edge_detect(unsigned int gpio, unsigned int edge, int bouncetime)
419
- // return values:
420
- // 0 - Success
421
- // 1 - Edge detection already added
422
- // 2 - Other error
423
- {
424
- pthread_t threads;
425
- struct epoll_event ev;
426
- long t = 0;
427
- struct gpios *g;
428
- int i = -1;
429
-
430
- i = gpio_event_added(gpio);
431
- if (i == 0) { // event not already added
432
- if ((g = new_gpio(gpio)) == NULL)
433
- return 2;
434
-
435
- gpio_set_edge(gpio, edge);
436
- g->edge = edge;
437
- g->bouncetime = bouncetime;
438
- } else if (i == edge) { // get existing event
439
- g = get_gpio(gpio);
440
- if ((bouncetime != -666 && g->bouncetime != bouncetime) || // different event bouncetime used
441
- (g->thread_added)) // event already added
442
- return 1;
443
- } else {
444
- return 1;
445
- }
446
-
447
- // create epfd_thread if not already open
448
- if ((epfd_thread == -1) && ((epfd_thread = epoll_create(1)) == -1))
449
- return 2;
450
-
451
- // add to epoll fd
452
- ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
453
- ev.data.fd = g->value_fd;
454
- if (epoll_ctl(epfd_thread, EPOLL_CTL_ADD, g->value_fd, &ev) == -1) {
455
- remove_edge_detect(gpio);
456
- return 2;
457
- }
458
- g->thread_added = 1;
459
-
460
- // start poll thread if it is not already running
461
- if (!thread_running) {
462
- if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0) {
463
- remove_edge_detect(gpio);
464
- return 2;
465
- }
466
- }
467
- return 0;
468
- }
469
-
470
- int blocking_wait_for_edge(unsigned int gpio, unsigned int edge, int bouncetime)
471
- // return values:
472
- // 0 - Success
473
- // 1 - Edge detection already added
474
- // 2 - Other error
475
- {
476
- int n, ed;
477
- struct epoll_event events, ev;
478
- char buf;
479
- struct gpios *g = NULL;
480
- struct timeval tv_timenow;
481
- unsigned long long timenow;
482
- int finished = 0;
483
- int initial_edge = 1;
484
-
485
- if (callback_exists(gpio))
486
- return 1;
487
-
488
- // add gpio if it has not been added already
489
- ed = gpio_event_added(gpio);
490
- if (ed == edge) { // get existing record
491
- g = get_gpio(gpio);
492
- if (g->bouncetime != -666 && g->bouncetime != bouncetime) {
493
- return 1;
494
- }
495
- } else if (ed == NO_EDGE) { // not found so add event
496
- if ((g = new_gpio(gpio)) == NULL)
497
- return 2;
498
- gpio_set_edge(gpio, edge);
499
- g->edge = edge;
500
- g->bouncetime = bouncetime;
501
- } else { // ed != edge - event for a different edge
502
- g = get_gpio(gpio);
503
- gpio_set_edge(gpio, edge);
504
- g->edge = edge;
505
- g->bouncetime = bouncetime;
506
- g->initial_wait = 1;
507
- }
508
-
509
- // create epfd_blocking if not already open
510
- if ((epfd_blocking == -1) && ((epfd_blocking = epoll_create(1)) == -1)) {
511
- return 2;
512
- }
513
-
514
- // add to epoll fd
515
- ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
516
- ev.data.fd = g->value_fd;
517
- if (epoll_ctl(epfd_blocking, EPOLL_CTL_ADD, g->value_fd, &ev) == -1) {
518
- return 2;
519
- }
520
-
521
- // wait for edge
522
- while (!finished) {
523
- if ((n = epoll_wait(epfd_blocking, &events, 1, -1)) == -1) {
524
- epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
525
- return 2;
526
- }
527
- if (initial_edge) { // first time triggers with current state, so ignore
528
- initial_edge = 0;
529
- } else {
530
- gettimeofday(&tv_timenow, NULL);
531
- timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec;
532
- if (g->bouncetime == -666 || timenow - g->lastcall > g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) {
533
- g->lastcall = timenow;
534
- finished = 1;
535
- }
536
- }
537
- }
538
-
539
- // check event was valid
540
- if (n > 0) {
541
- lseek(events.data.fd, 0, SEEK_SET);
542
- if ((read(events.data.fd, &buf, 1) != 1) || (events.data.fd != g->value_fd)) {
543
- epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
544
- return 2;
545
- }
546
- }
547
-
548
- epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
549
- return 0;
550
- }