Esempio n. 1
0
static void*
mraa_gpio_interrupt_handler(void* arg)
{
    mraa_gpio_context dev = (mraa_gpio_context) arg;
    mraa_result_t ret;

    // open gpio value with open(3)
    char bu[MAX_SIZE];
    sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin);
    int fp = open(bu, O_RDONLY);
    if (fp < 0) {
        syslog(LOG_ERR, "gpio: failed to open gpio%d/value", dev->pin);
        return NULL;
    }
    dev->isr_value_fp = fp;

    for (;;) {
        ret = mraa_gpio_wait_interrupt(dev->isr_value_fp);
        if (ret == MRAA_SUCCESS) {
            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
#ifdef SWIGPYTHON
            // In order to call a python object (all python functions are objects) we
            // need to aquire the GIL (Global Interpreter Lock). This may not always be
            // nessecary but especially if doing IO (like print()) python will segfault
            // if we do not hold a lock on the GIL
            PyGILState_STATE gilstate = PyGILState_Ensure();
            PyObject *arglist;
            PyObject *ret;
            arglist = Py_BuildValue("(i)", dev->isr_args);
            if (arglist == NULL) {
                syslog(LOG_ERR, "gpio: Py_BuildValue NULL");
            } else {
                ret = PyEval_CallObject((PyObject*)dev->isr, arglist);
                if (ret == NULL) {
                    syslog(LOG_ERR, "gpio: PyEval_CallObject failed");
                } else {
                    Py_DECREF(ret);
                }
                Py_DECREF(arglist);
            }

            PyGILState_Release (gilstate);
#else
            dev->isr(dev->isr_args);
#endif
            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        } else {
        // we must have got an error code so die nicely
            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
            close(dev->isr_value_fp);
            dev->isr_value_fp = -1;
            return NULL;
        }
    }
}
Esempio n. 2
0
static void*
mraa_gpio_interrupt_handler(void* arg)
{
    mraa_gpio_context dev = (mraa_gpio_context) arg;
    if (IS_FUNC_DEFINED(dev, gpio_interrupt_handler_replace))
        return dev->advance_func->gpio_interrupt_handler_replace(dev);

    mraa_result_t ret;

    // open gpio value with open(3)
    char bu[MAX_SIZE];
    sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin);
    int fp = open(bu, O_RDONLY);
    if (fp < 0) {
        syslog(LOG_ERR, "gpio: failed to open gpio%d/value", dev->pin);
        return NULL;
    }

#ifndef HAVE_PTHREAD_CANCEL
    if (pipe(dev->isr_control_pipe)) {
        syslog(LOG_ERR, "gpio: failed to create isr control pipe");
        close(fp);
        return NULL;
    }
#endif

    dev->isr_value_fp = fp;

#if defined(SWIGJAVA) || defined(JAVACALLBACK)
    JNIEnv *jenv;
    if(dev->isr == mraa_java_isr_callback) {
        jint err = (*globVM)->AttachCurrentThreadAsDaemon(globVM, (void **)&jenv, NULL);

        if (err != JNI_OK) {
                close(dev->isr_value_fp);
                dev->isr_value_fp = -1;
                return NULL;
        }

        pthread_once(&env_key_init, make_env_key);
        pthread_setspecific(env_key, jenv);
    }
#endif

    for (;;) {
        ret = mraa_gpio_wait_interrupt(dev->isr_value_fp
#ifndef HAVE_PTHREAD_CANCEL
                , dev->isr_control_pipe[0]
#endif
                );
        if (ret == MRAA_SUCCESS && !dev->isr_thread_terminating) {
#ifdef HAVE_PTHREAD_CANCEL
            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
#endif
#ifdef SWIGPYTHON
            // In order to call a python object (all python functions are objects) we
            // need to aquire the GIL (Global Interpreter Lock). This may not always be
            // necessary but especially if doing IO (like print()) python will segfault
            // if we do not hold a lock on the GIL
            PyGILState_STATE gilstate = PyGILState_Ensure();
            PyObject* arglist;
            PyObject* ret;
            arglist = Py_BuildValue("(O)", dev->isr_args);
            if (arglist == NULL) {
                syslog(LOG_ERR, "gpio: Py_BuildValue NULL");
            } else {
                ret = PyEval_CallObject((PyObject*) dev->isr, arglist);
                if (ret == NULL) {
                    syslog(LOG_ERR, "gpio: PyEval_CallObject failed");
                    PyObject *pvalue, *ptype, *ptraceback;
                    PyObject *pvalue_pystr, *ptype_pystr, *ptraceback_pystr;
                    char *pvalue_cstr, *ptype_cstr, *ptraceback_cstr;
                    PyErr_Fetch(&pvalue, &ptype, &ptraceback);
                    pvalue_pystr = PyObject_Str(pvalue);
                    ptype_pystr = PyObject_Str(ptype);
                    ptraceback_pystr = PyObject_Str(ptraceback);
// Python2
#if PY_VERSION_HEX < 0x03000000
                    pvalue_cstr = PyString_AsString(pvalue_pystr);
                    ptype_cstr = PyString_AsString(ptype_pystr);
                    ptraceback_cstr = PyString_AsString(ptraceback_pystr);
// Python 3 and up
#elif PY_VERSION_HEX >= 0x03000000
                    // In Python 3 we need one extra conversion
                    PyObject *pvalue_ustr, *ptype_ustr, *ptraceback_ustr;
                    pvalue_ustr = PyUnicode_AsUTF8String(pvalue_pystr);
                    pvalue_cstr = PyBytes_AsString(pvalue_ustr);
                    ptype_ustr = PyUnicode_AsUTF8String(ptype_pystr);
                    ptype_cstr = PyBytes_AsString(ptype_ustr);
                    ptraceback_ustr = PyUnicode_AsUTF8String(ptraceback_pystr);
                    ptraceback_cstr = PyBytes_AsString(ptraceback_ustr);
#endif // PY_VERSION_HEX
                    syslog(LOG_ERR, "gpio: the error was %s:%s:%s",
                           pvalue_cstr,
                           ptype_cstr,
                           ptraceback_cstr
                    );
                    Py_XDECREF(pvalue);
                    Py_XDECREF(ptype);
                    Py_XDECREF(ptraceback);
                    Py_XDECREF(pvalue_pystr);
                    Py_XDECREF(ptype_pystr);
                    Py_XDECREF(ptraceback_pystr);
// Python 3 and up
#if PY_VERSION_HEX >= 0x03000000
                    Py_XDECREF(pvalue_ustr);
                    Py_XDECREF(ptype_ustr);
                    Py_XDECREF(ptraceback_ustr);
#endif // PY_VERSION_HEX
                } else {
                    Py_DECREF(ret);
                }
                Py_DECREF(arglist);
            }

            PyGILState_Release(gilstate);
#else
            dev->isr(dev->isr_args);
#endif
#ifdef HAVE_PTHREAD_CANCEL
            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
#endif
        } else {
            // we must have got an error code or exit request so die nicely
#ifdef HAVE_PTHREAD_CANCEL
            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
#endif
            close(dev->isr_value_fp);
            dev->isr_value_fp = -1;
#if defined(SWIGJAVA) || defined(JAVACALLBACK)

            if(dev->isr == mraa_java_isr_callback) {
                (*jenv)->DeleteGlobalRef(jenv, (jobject)dev->isr_args);
                (*globVM)->DetachCurrentThread(globVM);
            }
#endif
            return NULL;
        }
    }
}
Esempio n. 3
0
File: gpio.c Progetto: fboudra/mraa
static void*
mraa_gpio_interrupt_handler(void* arg)
{
    mraa_gpio_context dev = (mraa_gpio_context) arg;
    int fp = -1;
    mraa_result_t ret;

    if (IS_FUNC_DEFINED(dev, gpio_interrupt_handler_init_replace)) {
        if (dev->advance_func->gpio_interrupt_handler_init_replace(dev) != MRAA_SUCCESS)
            return NULL;
    } else {
        // open gpio value with open(3)
        char bu[MAX_SIZE];
        sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin);
        fp = open(bu, O_RDONLY);
        if (fp < 0) {
            syslog(LOG_ERR, "gpio%i: interrupt_handler: failed to open 'value' : %s", dev->pin, strerror(errno));
            return NULL;
        }
    }

#ifndef HAVE_PTHREAD_CANCEL
    if (pipe(dev->isr_control_pipe)) {
        syslog(LOG_ERR, "gpio%i: interrupt_handler: failed to create isr control pipe: %s", dev->pin, strerror(errno));
        close(fp);
        return NULL;
    }
#endif

    dev->isr_value_fp = fp;

    if (lang_func->java_attach_thread != NULL) {
        if (dev->isr == lang_func->java_isr_callback) {
            if (lang_func->java_attach_thread() != MRAA_SUCCESS) {
                close(dev->isr_value_fp);
                dev->isr_value_fp = -1;
                return NULL;
            }
        }
    }

    for (;;) {
        if (IS_FUNC_DEFINED(dev, gpio_wait_interrupt_replace)) {
            ret = dev->advance_func->gpio_wait_interrupt_replace(dev);
        } else {
            ret = mraa_gpio_wait_interrupt(dev->isr_value_fp
#ifndef HAVE_PTHREAD_CANCEL
                , dev->isr_control_pipe[0]
#endif
                );
        }
        if (ret == MRAA_SUCCESS && !dev->isr_thread_terminating) {
#ifdef HAVE_PTHREAD_CANCEL
            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
#endif
            if (lang_func->python_isr != NULL) {
                lang_func->python_isr(dev->isr, dev->isr_args);
            } else {
                dev->isr(dev->isr_args);
            }
#ifdef HAVE_PTHREAD_CANCEL
            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
#endif
        } else {
            // we must have got an error code or exit request so die nicely
#ifdef HAVE_PTHREAD_CANCEL
            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
#endif
            if (fp != -1) {
                close(dev->isr_value_fp);
                dev->isr_value_fp = -1;
            }

            if (lang_func->java_detach_thread != NULL && lang_func->java_delete_global_ref != NULL) {
                if (dev->isr == lang_func->java_isr_callback) {
                    lang_func->java_delete_global_ref(dev->isr_args);
                    lang_func->java_detach_thread();
                }
            }

            return NULL;
        }
    }
}