gpio.c: fix segfault on isrExit in python because of double Py_DECREF
[contrib/mraa.git] / src / gpio / gpio.c
1 /*
2  * Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
3  * Author: Brendan Le Foll <brendan.le.foll@intel.com>
4  * Copyright (c) 2014 Intel Corporation.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #include "gpio.h"
26 #include "mraa_internal.h"
27
28 #include <stdlib.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <poll.h>
33 #include <pthread.h>
34 #include <signal.h>
35 #include <sys/stat.h>
36 #include <sys/mman.h>
37
38 #define SYSFS_CLASS_GPIO "/sys/class/gpio"
39 #define MAX_SIZE 64
40 #define POLL_TIMEOUT
41
42 static mraa_result_t
43 mraa_gpio_get_valfp(mraa_gpio_context dev)
44 {
45     char bu[MAX_SIZE];
46     sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin);
47     dev->value_fp = open(bu, O_RDWR);
48     if (dev->value_fp == -1) {
49         return MRAA_ERROR_INVALID_RESOURCE;
50     }
51
52     return MRAA_SUCCESS;
53 }
54
55 mraa_gpio_context
56 mraa_gpio_init(int pin)
57 {
58     if (plat == NULL) {
59         syslog(LOG_ERR, "gpio: platform not initialised");
60         return NULL;
61     }
62     if (pin < 0 || pin > plat->phy_pin_count) {
63         syslog(LOG_ERR, "gpio: pin %i beyond platform definition", pin);
64         return NULL;
65     }
66     if (plat->pins[pin].capabilites.gpio != 1) {
67         syslog(LOG_ERR, "gpio: pin %i not capable of gpio", pin);
68         return NULL;
69     }
70     if (plat->pins[pin].gpio.mux_total > 0) {
71         if (mraa_setup_mux_mapped(plat->pins[pin].gpio) != MRAA_SUCCESS) {
72             syslog(LOG_ERR, "gpio: unable to setup muxes");
73             return NULL;
74         }
75     }
76
77     mraa_gpio_context r = mraa_gpio_init_raw(plat->pins[pin].gpio.pinmap);
78     if (r == NULL) {
79         syslog(LOG_CRIT, "gpio: mraa_gpio_init_raw(%d) returned error", pin);
80         return NULL;
81     }
82     r->phy_pin = pin;
83
84     if (advance_func->gpio_init_post != NULL) {
85         mraa_result_t ret = advance_func->gpio_init_post(r);
86         if (ret != MRAA_SUCCESS) {
87             free(r);
88             return NULL;
89         }
90     }
91     return r;
92 }
93
94 mraa_gpio_context
95 mraa_gpio_init_raw(int pin)
96 {
97     if (advance_func->gpio_init_pre != NULL) {
98         if (advance_func->gpio_init_pre(pin) != MRAA_SUCCESS)
99             return NULL;
100     }
101
102     if (pin < 0)
103         return NULL;
104
105     char bu[MAX_SIZE];
106     int length;
107
108     mraa_gpio_context dev = (mraa_gpio_context) malloc(sizeof(struct _gpio));
109     if (dev == NULL) {
110         syslog(LOG_CRIT, "gpio: Failed to allocate memory for context");
111         return NULL;
112     }
113
114     memset(dev, 0, sizeof(struct _gpio));
115     dev->value_fp = -1;
116     dev->isr_value_fp = -1;
117     dev->pin = pin;
118     dev->phy_pin = -1;
119
120     // then check to make sure the pin is exported.
121     char directory[MAX_SIZE];
122     snprintf(directory, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/", dev->pin);
123     struct stat dir;
124     if (stat(directory, &dir) == 0 && S_ISDIR(dir.st_mode)) {
125         dev->owner = 0; // Not Owner
126     } else {
127         int export = open(SYSFS_CLASS_GPIO "/export", O_WRONLY);
128         if (export == -1) {
129             syslog(LOG_ERR, "gpio: Failed to open export for writing");
130             free(dev);
131             return NULL;
132         }
133         length = snprintf(bu, sizeof(bu), "%d", dev->pin);
134         if (write(export, bu, length * sizeof(char)) == -1) {
135             syslog(LOG_ERR, "gpio: Failed to write %d to export", dev->pin);
136             close(export);
137             free(dev);
138             return NULL;
139         }
140         dev->owner = 1;
141         close(export);
142     }
143
144     return dev;
145 }
146
147
148 static mraa_result_t
149 mraa_gpio_wait_interrupt(int fd)
150 {
151     unsigned char c;
152     struct pollfd pfd;
153
154     if (fd < 0) {
155         return MRAA_ERROR_INVALID_RESOURCE;
156     }
157
158     // setup poll on POLLPRI
159     pfd.fd = fd;
160     pfd.events = POLLPRI;
161
162     // do an initial read to clear interrupt
163     lseek(fd, 0, SEEK_SET);
164     read(fd, &c, 1);
165
166     // Wait for it forever or until pthread_cancel
167     // poll is a cancelable point like sleep()
168     int x = poll(&pfd, 1, -1);
169
170     // do a final read to clear interrupt
171     read(fd, &c, 1);
172
173     return MRAA_SUCCESS;
174 }
175
176 static void*
177 mraa_gpio_interrupt_handler(void* arg)
178 {
179     mraa_gpio_context dev = (mraa_gpio_context) arg;
180     mraa_result_t ret;
181
182     // open gpio value with open(3)
183     char bu[MAX_SIZE];
184     sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin);
185     int fp = open(bu, O_RDONLY);
186     if (fp < 0) {
187         syslog(LOG_ERR, "gpio: failed to open gpio%d/value", dev->pin);
188         return NULL;
189     }
190     dev->isr_value_fp = fp;
191
192     for (;;) {
193         ret = mraa_gpio_wait_interrupt(dev->isr_value_fp);
194         if (ret == MRAA_SUCCESS) {
195             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
196 #ifdef SWIGPYTHON
197             // In order to call a python object (all python functions are objects) we
198             // need to aquire the GIL (Global Interpreter Lock). This may not always be
199             // nessecary but especially if doing IO (like print()) python will segfault
200             // if we do not hold a lock on the GIL
201             PyGILState_STATE gilstate = PyGILState_Ensure();
202             PyObject* arglist;
203             PyObject* ret;
204             arglist = Py_BuildValue("(i)", dev->isr_args);
205             if (arglist == NULL) {
206                 syslog(LOG_ERR, "gpio: Py_BuildValue NULL");
207             } else {
208                 ret = PyEval_CallObject((PyObject*) dev->isr, arglist);
209                 if (ret == NULL) {
210                     syslog(LOG_ERR, "gpio: PyEval_CallObject failed");
211                 } else {
212                     Py_DECREF(ret);
213                 }
214                 Py_DECREF(arglist);
215             }
216
217             PyGILState_Release(gilstate);
218 #else
219             dev->isr(dev->isr_args);
220 #endif
221             pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
222         } else {
223             // we must have got an error code so die nicely
224             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
225             close(dev->isr_value_fp);
226             dev->isr_value_fp = -1;
227             return NULL;
228         }
229     }
230 }
231
232 mraa_result_t
233 mraa_gpio_edge_mode(mraa_gpio_context dev, mraa_gpio_edge_t mode)
234 {
235     if (dev->value_fp != -1) {
236         close(dev->value_fp);
237         dev->value_fp = -1;
238     }
239
240     char filepath[MAX_SIZE];
241     snprintf(filepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/edge", dev->pin);
242
243     int edge = open(filepath, O_RDWR);
244     if (edge == -1) {
245         syslog(LOG_ERR, "gpio: Failed to open edge for writing");
246         return MRAA_ERROR_INVALID_RESOURCE;
247     }
248
249     char bu[MAX_SIZE];
250     int length;
251     switch (mode) {
252         case MRAA_GPIO_EDGE_NONE:
253             length = snprintf(bu, sizeof(bu), "none");
254             break;
255         case MRAA_GPIO_EDGE_BOTH:
256             length = snprintf(bu, sizeof(bu), "both");
257             break;
258         case MRAA_GPIO_EDGE_RISING:
259             length = snprintf(bu, sizeof(bu), "rising");
260             break;
261         case MRAA_GPIO_EDGE_FALLING:
262             length = snprintf(bu, sizeof(bu), "falling");
263             break;
264         default:
265             close(edge);
266             return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED;
267     }
268     if (write(edge, bu, length * sizeof(char)) == -1) {
269         syslog(LOG_ERR, "gpio: Failed to write to edge");
270         close(edge);
271         return MRAA_ERROR_INVALID_RESOURCE;
272     }
273
274     close(edge);
275     return MRAA_SUCCESS;
276 }
277
278 mraa_result_t
279 mraa_gpio_isr(mraa_gpio_context dev, mraa_gpio_edge_t mode, void (*fptr)(void*), void* args)
280 {
281     // we only allow one isr per mraa_gpio_context
282     if (dev->thread_id != 0) {
283         return MRAA_ERROR_NO_RESOURCES;
284     }
285
286     if (MRAA_SUCCESS != mraa_gpio_edge_mode(dev, mode)) {
287         return MRAA_ERROR_UNSPECIFIED;
288     }
289
290     dev->isr = fptr;
291     dev->isr_args = args;
292     pthread_create(&dev->thread_id, NULL, mraa_gpio_interrupt_handler, (void*) dev);
293
294     return MRAA_SUCCESS;
295 }
296
297 mraa_result_t
298 mraa_gpio_isr_exit(mraa_gpio_context dev)
299 {
300     mraa_result_t ret = MRAA_SUCCESS;
301
302     // wasting our time, there is no isr to exit from
303     if (dev->thread_id == 0 && dev->isr_value_fp == -1) {
304         return ret;
305     }
306
307     // stop isr being useful
308     ret = mraa_gpio_edge_mode(dev, MRAA_GPIO_EDGE_NONE);
309
310     if ((dev->thread_id != 0)) {
311         if ((pthread_cancel(dev->thread_id) != 0) || (pthread_join(dev->thread_id, NULL) != 0)) {
312             ret = MRAA_ERROR_INVALID_HANDLE;
313         }
314     }
315
316     // close the filehandle in case it's still open
317     if (dev->isr_value_fp != -1) {
318         if (close(dev->isr_value_fp) != 0) {
319             ret = MRAA_ERROR_INVALID_PARAMETER;
320         }
321     }
322
323     // assume our thread will exit either way we just lost it's handle
324     dev->thread_id = 0;
325     dev->isr_value_fp = -1;
326     return ret;
327 }
328
329 mraa_result_t
330 mraa_gpio_mode(mraa_gpio_context dev, mraa_gpio_mode_t mode)
331 {
332     if (advance_func->gpio_mode_replace != NULL)
333         return advance_func->gpio_mode_replace(dev, mode);
334
335     if (advance_func->gpio_mode_pre != NULL) {
336         mraa_result_t pre_ret = (advance_func->gpio_mode_pre(dev, mode));
337         if (pre_ret != MRAA_SUCCESS)
338             return pre_ret;
339     }
340
341     if (dev->value_fp != -1) {
342         close(dev->value_fp);
343         dev->value_fp = -1;
344     }
345
346     char filepath[MAX_SIZE];
347     snprintf(filepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/drive", dev->pin);
348
349     int drive = open(filepath, O_WRONLY);
350     if (drive == -1) {
351         syslog(LOG_ERR, "gpio: Failed to open drive for writing");
352         return MRAA_ERROR_INVALID_RESOURCE;
353     }
354
355     char bu[MAX_SIZE];
356     int length;
357     switch (mode) {
358         case MRAA_GPIO_STRONG:
359             length = snprintf(bu, sizeof(bu), "strong");
360             break;
361         case MRAA_GPIO_PULLUP:
362             length = snprintf(bu, sizeof(bu), "pullup");
363             break;
364         case MRAA_GPIO_PULLDOWN:
365             length = snprintf(bu, sizeof(bu), "pulldown");
366             break;
367         case MRAA_GPIO_HIZ:
368             length = snprintf(bu, sizeof(bu), "hiz");
369             break;
370         default:
371             close(drive);
372             return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED;
373     }
374     if (write(drive, bu, length * sizeof(char)) == -1) {
375         syslog(LOG_ERR, "gpio: Failed to write to drive mode");
376         close(drive);
377         return MRAA_ERROR_INVALID_RESOURCE;
378     }
379
380     close(drive);
381     if (advance_func->gpio_mode_post != NULL)
382         return advance_func->gpio_mode_post(dev, mode);
383     return MRAA_SUCCESS;
384 }
385
386 mraa_result_t
387 mraa_gpio_dir(mraa_gpio_context dev, mraa_gpio_dir_t dir)
388 {
389     if (advance_func->gpio_dir_replace != NULL) {
390         return advance_func->gpio_dir_replace(dev, dir);
391     }
392     if (advance_func->gpio_dir_pre != NULL) {
393         mraa_result_t pre_ret = (advance_func->gpio_dir_pre(dev, dir));
394         if (pre_ret != MRAA_SUCCESS) {
395             return pre_ret;
396         }
397     }
398
399     if (dev == NULL) {
400         return MRAA_ERROR_INVALID_HANDLE;
401     }
402     if (dev->value_fp != -1) {
403         close(dev->value_fp);
404         dev->value_fp = -1;
405     }
406     char filepath[MAX_SIZE];
407     snprintf(filepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/direction", dev->pin);
408
409     int direction = open(filepath, O_RDWR);
410
411     if (direction == -1) {
412         // Direction Failed to Open. If HIGH or LOW was passed will try and set
413         // If not fail as usual.
414         switch (dir) {
415             case MRAA_GPIO_OUT_HIGH:
416                 return mraa_gpio_write(dev, 1);
417             case MRAA_GPIO_OUT_LOW:
418                 return mraa_gpio_write(dev, 0);
419             default:
420                 return MRAA_ERROR_INVALID_RESOURCE;
421         }
422     }
423
424     char bu[MAX_SIZE];
425     int length;
426     switch (dir) {
427         case MRAA_GPIO_OUT:
428             length = snprintf(bu, sizeof(bu), "out");
429             break;
430         case MRAA_GPIO_IN:
431             length = snprintf(bu, sizeof(bu), "in");
432             break;
433         case MRAA_GPIO_OUT_HIGH:
434             length = snprintf(bu, sizeof(bu), "high");
435             break;
436         case MRAA_GPIO_OUT_LOW:
437             length = snprintf(bu, sizeof(bu), "low");
438             break;
439         default:
440             close(direction);
441             return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED;
442     }
443
444     if (write(direction, bu, length * sizeof(char)) == -1) {
445         close(direction);
446         return MRAA_ERROR_INVALID_RESOURCE;
447     }
448
449     close(direction);
450     if (advance_func->gpio_dir_post != NULL)
451         return advance_func->gpio_dir_post(dev, dir);
452     return MRAA_SUCCESS;
453 }
454
455 int
456 mraa_gpio_read(mraa_gpio_context dev)
457 {
458     if (dev == NULL)
459         return -1;
460
461     if (dev->mmap_read != NULL)
462         return dev->mmap_read(dev);
463
464     if (dev->value_fp == -1) {
465         if (mraa_gpio_get_valfp(dev) != MRAA_SUCCESS) {
466             syslog(LOG_ERR, "gpio: Failed to get value file pointer");
467             return -1;
468         }
469     } else {
470         // if value_fp is new this is pointless
471         lseek(dev->value_fp, 0, SEEK_SET);
472     }
473     char bu[2];
474     if (read(dev->value_fp, bu, 2 * sizeof(char)) != 2) {
475         syslog(LOG_ERR, "gpio: Failed to read a sensible value from sysfs");
476         return -1;
477     }
478     lseek(dev->value_fp, 0, SEEK_SET);
479
480     return (int) strtol(bu, NULL, 10);
481 }
482
483 mraa_result_t
484 mraa_gpio_write(mraa_gpio_context dev, int value)
485 {
486     if (dev == NULL)
487         return MRAA_ERROR_INVALID_HANDLE;
488
489     if (dev->mmap_write != NULL)
490         return dev->mmap_write(dev, value);
491
492     if (advance_func->gpio_write_pre != NULL) {
493         mraa_result_t pre_ret = (advance_func->gpio_write_pre(dev, value));
494         if (pre_ret != MRAA_SUCCESS)
495             return pre_ret;
496     }
497
498     if (dev->value_fp == -1) {
499         if (mraa_gpio_get_valfp(dev) != MRAA_SUCCESS) {
500             return MRAA_ERROR_INVALID_RESOURCE;
501         }
502     }
503
504     if (lseek(dev->value_fp, 0, SEEK_SET) == -1) {
505         return MRAA_ERROR_INVALID_RESOURCE;
506     }
507
508     char bu[MAX_SIZE];
509     int length = snprintf(bu, sizeof(bu), "%d", value);
510     if (write(dev->value_fp, bu, length * sizeof(char)) == -1) {
511         return MRAA_ERROR_INVALID_HANDLE;
512     }
513
514     if (advance_func->gpio_write_post != NULL)
515         return advance_func->gpio_write_post(dev, value);
516     return MRAA_SUCCESS;
517 }
518
519 static mraa_result_t
520 mraa_gpio_unexport_force(mraa_gpio_context dev)
521 {
522     int unexport = open(SYSFS_CLASS_GPIO "/unexport", O_WRONLY);
523     if (unexport == -1) {
524         syslog(LOG_ERR, "gpio: Failed to open unexport for writing");
525         return MRAA_ERROR_INVALID_RESOURCE;
526     }
527
528     char bu[MAX_SIZE];
529     int length = snprintf(bu, sizeof(bu), "%d", dev->pin);
530     if (write(unexport, bu, length * sizeof(char)) == -1) {
531         syslog(LOG_ERR, "gpio: Failed to write to unexport");
532         close(unexport);
533         return MRAA_ERROR_INVALID_RESOURCE;
534     }
535
536     close(unexport);
537     mraa_gpio_isr_exit(dev);
538     return MRAA_SUCCESS;
539 }
540 static mraa_result_t
541 mraa_gpio_unexport(mraa_gpio_context dev)
542 {
543     if (dev->owner) {
544         return mraa_gpio_unexport_force(dev);
545     }
546     return MRAA_ERROR_INVALID_RESOURCE;
547 }
548
549 mraa_result_t
550 mraa_gpio_close(mraa_gpio_context dev)
551 {
552     mraa_result_t result = MRAA_SUCCESS;
553
554     if (advance_func->gpio_close_pre != NULL) {
555         result = advance_func->gpio_close_pre(dev);
556     }
557
558     if (dev->value_fp != -1) {
559         close(dev->value_fp);
560     }
561     mraa_gpio_unexport(dev);
562     free(dev);
563     return result;
564 }
565
566 mraa_result_t
567 mraa_gpio_owner(mraa_gpio_context dev, mraa_boolean_t own)
568 {
569     if (dev == NULL) {
570         return MRAA_ERROR_INVALID_RESOURCE;
571     }
572     syslog(LOG_DEBUG, "gpio: Set owner to %d", (int) own);
573     dev->owner = own;
574     return MRAA_SUCCESS;
575 }
576
577 mraa_result_t
578 mraa_gpio_use_mmaped(mraa_gpio_context dev, mraa_boolean_t mmap_en)
579 {
580     if (advance_func->gpio_mmap_setup != NULL) {
581         return advance_func->gpio_mmap_setup(dev, mmap_en);
582     }
583
584     syslog(LOG_ERR, "gpio: mmap not implemented on this platform");
585     return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED;
586 }
587
588 int
589 mraa_gpio_get_pin(mraa_gpio_context dev)
590 {
591     if (dev == NULL) {
592         syslog(LOG_ERR, "gpio: context is invalid");
593         return -1;
594     }
595     return dev->phy_pin;
596 }
597
598 int
599 mraa_gpio_get_pin_raw(mraa_gpio_context dev)
600 {
601     if (dev == NULL) {
602         syslog(LOG_ERR, "gpio: context is invalid");
603         return -1;
604     }
605     return dev->pin;
606 }