// python function value = input(channel) static PyObject *py_input_gpio(PyObject *self, PyObject *args) { unsigned int gpio; int channel; PyObject *value; if (!PyArg_ParseTuple(args, "i", &channel)) return NULL; if (get_gpio_number(channel, &gpio)) return NULL; // check channel is set up as an input or output if (gpio_direction[gpio] != INPUT && gpio_direction[gpio] != OUTPUT) { PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel first"); return NULL; } if (check_gpio_priv()) return NULL; if (input_gpio(gpio)) { value = Py_BuildValue("i", HIGH); } else { value = Py_BuildValue("i", LOW); } return value; }
// python function add_event_detect(gpio, edge, callback=None, bouncetime=0 static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *kwargs) { unsigned int gpio; int channel, edge, result; unsigned int bouncetime = 0; PyObject *cb_func = NULL; char *kwlist[] = {"gpio", "edge", "callback", "bouncetime", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|Oi", kwlist, &channel, &edge, &cb_func, &bouncetime)) return NULL; if (cb_func != NULL && !PyCallable_Check(cb_func)) { PyErr_SetString(PyExc_TypeError, "Parameter must be callable"); return NULL; } if (get_gpio_number(channel, &gpio)) return NULL; // check channel is set up as an input if (gpio_direction[gpio] != INPUT) { PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first"); return NULL; } // is edge valid value edge -= PY_EVENT_CONST_OFFSET; if (edge != RISING_EDGE && edge != FALLING_EDGE && edge != BOTH_EDGE) { PyErr_SetString(PyExc_ValueError, "The edge must be set to RISING, FALLING or BOTH"); return NULL; } if (check_gpio_priv()) return NULL; if ((result = add_edge_detect(gpio, edge, bouncetime)) != 0) // starts a thread { if (result == 1) { PyErr_SetString(PyExc_RuntimeError, "Edge detection already enabled for this GPIO channel"); return NULL; } else { PyErr_SetString(PyExc_RuntimeError, "Failed to add edge detection"); return NULL; } } if (cb_func != NULL) if (add_py_callback(gpio, cb_func) != 0) return NULL; Py_RETURN_NONE; }
// python function py_wait_for_edge(gpio, edge) static PyObject *py_wait_for_edge(PyObject *self, PyObject *args) { unsigned int gpio; int channel, edge, result; char error[30]; if (!PyArg_ParseTuple(args, "ii", &channel, &edge)) return NULL; if (get_gpio_number(channel, &gpio)) return NULL; // check channel is setup as an input if (gpio_direction[gpio] != INPUT) { PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first"); return NULL; } // is edge a valid value? edge -= PY_EVENT_CONST_OFFSET; if (edge != RISING_EDGE && edge != FALLING_EDGE && edge != BOTH_EDGE) { PyErr_SetString(PyExc_ValueError, "The edge must be set to RISING, FALLING or BOTH"); return NULL; } if (check_gpio_priv()) return NULL; Py_BEGIN_ALLOW_THREADS // disable GIL result = blocking_wait_for_edge(gpio, edge); Py_END_ALLOW_THREADS // enable GIL if (result == 0) { Py_INCREF(Py_None); return Py_None; } else if (result == 1) { PyErr_SetString(PyExc_RuntimeError, "Edge detection events already enabled for this GPIO channel"); return NULL; } else { sprintf(error, "Error #%d waiting for edge", result); PyErr_SetString(PyExc_RuntimeError, error); return NULL; } Py_RETURN_NONE; }
// python function remove_event_detect(gpio) static PyObject *py_remove_event_detect(PyObject *self, PyObject *args) { unsigned int gpio; unsigned int sys_gpio; int channel; struct py_callback *cb = py_callbacks; struct py_callback *temp; struct py_callback *prev = NULL; if (!PyArg_ParseTuple(args, "i", &channel)) return NULL; if (get_gpio_number(channel, &gpio, &sys_gpio)) return NULL; // remove all python callbacks for gpio while (cb != NULL) { if (cb->gpio == gpio) { Py_XDECREF(cb->py_cb); if (prev == NULL) py_callbacks = cb->next; else prev->next = cb->next; temp = cb; cb = cb->next; free(temp); } else { prev = cb; cb = cb->next; } } if (check_gpio_priv()) return NULL; remove_edge_detect(sys_gpio); Py_RETURN_NONE; }
// python function output(channel, value) static PyObject *py_output_gpio(PyObject *self, PyObject *args) { unsigned int gpio; int channel, value; if (!PyArg_ParseTuple(args, "ii", &channel, &value)) return NULL; if (get_gpio_number(channel, &gpio)) return NULL; if (gpio_direction[gpio] != OUTPUT) { PyErr_SetString(PyExc_RuntimeError, "The GPIO channel has not been set up as an OUTPUT"); return NULL; } if (check_gpio_priv()) return NULL; output_gpio(gpio, value); Py_RETURN_NONE; }
// python function py_wait_for_edge(gpio, edge) static PyObject *py_wait_for_edge(PyObject *self, PyObject *args) { unsigned int gpio; unsigned int sys_gpio; int channel, edge, result; char error[30]; if (!PyArg_ParseTuple(args, "ii", &channel, &edge)) return NULL; if (get_gpio_number(channel, &gpio, &sys_gpio)) return NULL; // check channel is setup as an input if (gpio_direction[sys_gpio] != INPUT) { PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first"); return NULL; } //check channel whether support the event detected or not if(is_a20_platform()) { if(support_event_detect(gpio, gpioEdge_BP) < 0) { PyErr_SetString(PyExc_RuntimeError, "the pin doesn't support to detect the external event!"); return NULL; } } else if(is_s500_platform()) { if(support_event_detect(gpio, gpioEdge_GT) < 0) { PyErr_SetString(PyExc_RuntimeError, "the pin doesn't support to detect the external event!"); return NULL; } } // is edge a valid value? edge -= PY_EVENT_CONST_OFFSET; if(is_a20_platform()) { if (edge != RISING_EDGE && edge != FALLING_EDGE && edge != BOTH_EDGE) { PyErr_SetString(PyExc_ValueError, "The edge must be set to RISING, FALLING or BOTH"); return NULL; } } else if(is_s500_platform()) //s500 doesn't support the "BOTH" trigger mode. { if (edge != RISING_EDGE && edge != FALLING_EDGE) { PyErr_SetString(PyExc_ValueError, "The edge must be set to RISING and FALLING"); return NULL; } } if (check_gpio_priv()) return NULL; Py_BEGIN_ALLOW_THREADS // disable GIL result = blocking_wait_for_edge(sys_gpio, edge); Py_END_ALLOW_THREADS // enable GIL if (result == 0) { Py_INCREF(Py_None); return Py_None; } else if (result == 1) { PyErr_SetString(PyExc_RuntimeError, "Edge detection events already enabled for this GPIO channel"); return NULL; } else { sprintf(error, "Error #%d waiting for edge", result); PyErr_SetString(PyExc_RuntimeError, error); return NULL; } Py_RETURN_NONE; }