From db4493322d9ec9381bad72de05d075f390e3dc4f Mon Sep 17 00:00:00 2001 From: Robert Wolterman Date: Sun, 10 Jul 2016 14:56:40 -0500 Subject: [PATCH] Inital attempt at fixing #9. Things are still broken. wait_for_edge no longer works on AP-EINT1/3, XIO will trigger only one on falling edge. --- source/event_gpio.c | 116 ++++++++++++++++++++++++++++++++++++++++++-- source/event_gpio.h | 7 ++- source/py_gpio.c | 9 ++-- test/gptest.py | 3 +- 4 files changed, 126 insertions(+), 9 deletions(-) diff --git a/source/event_gpio.c b/source/event_gpio.c index a3483dc..e3b38ec 100644 --- a/source/event_gpio.c +++ b/source/event_gpio.c @@ -64,6 +64,7 @@ struct fdx *fd_list = NULL; struct callback { int gpio; + int edge; void (*func)(int gpio); struct callback *next; }; @@ -422,9 +423,12 @@ int gpio_get_value(int gpio, unsigned int *value) int gpio_set_edge(int gpio, unsigned int edge) { - int fd; + int fd, e_no; char filename[MAX_FILENAME]; + // DEBUG + printf("DEBUG: gpio_set_edge(%d, %d (%s))\n", gpio, edge, stredge[edge]); + snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio); BUF2SMALL(filename); if ((fd = open(filename, O_WRONLY)) < 0) { @@ -446,6 +450,78 @@ int gpio_set_edge(int gpio, unsigned int edge) return 0; } +int open_edge_file(int gpio) +{ + int fd; + char filename[MAX_FILENAME]; + + // create file descriptor of value file + snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio); BUF2SMALL(filename); + + if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0) { + char err[256]; + snprintf(err, sizeof(err), "open_edge_file: could not open '%s' (%s)", filename, strerror(errno)); + add_error_msg(err); + return -1; + } + + return fd; +} /* open_edge_file */ + +int gpio_get_edge(int gpio) +{ + int e_no; + int fd = fd_lookup(gpio); + int rtnedge = -1; + + if (!fd) + { + if ((fd = open_edge_file(gpio)) == -1) { + char err[256]; + snprintf(err, sizeof(err), "gpio_get_value: could not open GPIO %d edge file", gpio); + add_error_msg(err); + return -1; + } + } + + if (lseek(fd, 0, SEEK_SET) < 0) { + char err[256]; + snprintf(err, sizeof(err), "gpio_get_value: could not seek GPIO %d (%s)", gpio, strerror(errno)); + add_error_msg(err); + return -1; + } + + char edge[16] = { 0 }; /* make sure read is null-terminated */ + ssize_t s = read(fd, &edge, sizeof(edge) - 1); e_no = errno; + close(fd); + while (s > 0 && edge[s-1] == '\n') { /* strip trailing newlines */ + edge[s-1] = '\0'; + s --; + } + + if (s < 0) { + char err[256]; + snprintf(err, sizeof(err), "gpio_get_value: could not read GPIO %d (%s)", gpio, strerror(errno)); + add_error_msg(err); + return -1; + } + + if (strcmp(edge, "rising") == 0) + { + rtnedge = 1; + } + else if (strcmp(edge, "falling") == 0) + { + rtnedge = 2; + } + else if (strcmp(edge, "both") == 0) + { + rtnedge = 3; + } + + return rtnedge; +} + int gpio_lookup(int fd) { struct fdx *f = fd_list; @@ -466,7 +542,7 @@ void exports_cleanup(void) gpio_unexport(exported_gpios->gpio); } -int add_edge_callback(int gpio, void (*func)(int gpio)) +int add_edge_callback(int gpio, int edge, void (*func)(int gpio)) { struct callback *cb = callbacks; struct callback *new_cb; @@ -474,6 +550,7 @@ int add_edge_callback(int gpio, void (*func)(int gpio)) new_cb = malloc(sizeof(struct callback)); ASSRT(new_cb != NULL); new_cb->gpio = gpio; + new_cb->edge = edge; new_cb->func = func; new_cb->next = NULL; @@ -495,7 +572,33 @@ void run_callbacks(int gpio) while (cb != NULL) { if (cb->gpio == gpio) - cb->func(cb->gpio); + { + int canrun = 0; + int edge = gpio_get_edge(gpio); + unsigned int value = 0; + gpio_get_value(gpio, &value); + // Both Edge + if (cb->edge == 3) + { + canrun = 1; + } + // Rising Edge + else if ((cb->edge == 1) && (value == 1)) + { + canrun = 1; + } + // Falling Edge + else if ((cb->edge == 2) && (value == 0)) + { + canrun = 1; + } + // Only run if we are allowed + if (canrun) + { + cb->func(cb->gpio); + } + + } cb = cb->next; } } @@ -573,10 +676,17 @@ void *poll_thread(void *threadarg) } // The return value represents the ending level after the edge. gpio = gpio_lookup(events.data.fd); + // DEBUG + printf("DEBUG *poll_thread -> GPIO: %d\n", gpio); if (gpio_initial(gpio)) { // ignore first epoll trigger + printf("DEBUG *poll_thread -> GPIO INITIAL HIT\n"); set_initial_false(gpio); } else { + printf("DEBUG *poll_thread -> GPIO RUNNING CALLBACK\n"); dyn_int_array_set(&event_occurred, gpio, 1, 0); + int value = 0; + gpio_get_value(gpio, &value); + printf("DEBUG *poll_thread -> GPIO VALUE: %d\n", value); run_callbacks(gpio); } } diff --git a/source/event_gpio.h b/source/event_gpio.h index 603677d..44dfb13 100644 --- a/source/event_gpio.h +++ b/source/event_gpio.h @@ -62,9 +62,14 @@ int gpio_get_direction(int gpio, unsigned int *value); int gpio_set_value(int gpio, unsigned int value); int gpio_get_value(int gpio, unsigned int *value); +int gpio_set_edge(int gpio, unsigned int edge); +int open_edge_file(int gpio); +int gpio_get_edge(int gpio); + int add_edge_detect(int gpio, unsigned int edge); void remove_edge_detect(int gpio); -int add_edge_callback(int gpio, void (*func)(int gpio)); +//int add_edge_callback(int gpio, void (*func)(int gpio)); +int add_edge_callback(int gpio, int edge, void (*func)(int gpio)); int event_detected(int gpio); int gpio_event_add(int gpio); int gpio_event_remove(int gpio); diff --git a/source/py_gpio.c b/source/py_gpio.c index ebb8aff..5cc8a8e 100644 --- a/source/py_gpio.c +++ b/source/py_gpio.c @@ -264,7 +264,7 @@ static void run_py_callbacks(int gpio) } } -static int add_py_callback(char *channel, int gpio, unsigned int bouncetime, PyObject *cb_func) +static int add_py_callback(char *channel, int gpio, int edge, unsigned int bouncetime, PyObject *cb_func) { struct py_callback *new_py_cb; struct py_callback *cb = py_callbacks; @@ -294,7 +294,7 @@ static int add_py_callback(char *channel, int gpio, unsigned int bouncetime, PyO cb = cb->next; cb->next = new_py_cb; } - add_edge_callback(gpio, run_py_callbacks); + add_edge_callback(gpio, edge, run_py_callbacks); return 0; } @@ -343,7 +343,8 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject PyErr_SetString(PyExc_RuntimeError, "Add event detection using add_event_detect first before adding a callback"); return NULL; } - if (add_py_callback(channel, gpio, bouncetime, cb_func) != 0) + // Defaulting to Falling edge + if (add_py_callback(channel, gpio, 2, bouncetime, cb_func) != 0) return NULL; Py_RETURN_NONE; @@ -410,7 +411,7 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k } if (cb_func != NULL) - if (add_py_callback(channel, gpio, bouncetime, cb_func) != 0) + if (add_py_callback(channel, gpio, edge, bouncetime, cb_func) != 0) return NULL; Py_RETURN_NONE; diff --git a/test/gptest.py b/test/gptest.py index a177f58..25e1aee 100755 --- a/test/gptest.py +++ b/test/gptest.py @@ -22,7 +22,7 @@ loopfunction_exit = False def loopfunction(): print("LOOP FUNCTION") - for i in xrange(4): + for i in xrange(6): if loopfunction_exit: break if i % 2: @@ -124,6 +124,7 @@ loopfunction() mystr = " num_callbacks = %d" % num_callbacks print(mystr) +print("\nWAIT FOR EDGE TESTING") print("PRESS CONTROL-C TO EXIT IF SCRIPT GETS STUCK") GPIO.remove_event_detect("XIO-P2") try: