int add_edge_detect(unsigned int gpio, unsigned int edge, int bouncetime)
// return values:
// 0 - Success
// 1 - Edge detection already added
// 2 - Other error
{
    pthread_t threads;
    struct epoll_event ev;
    long t = 0;
    struct gpios *g;
    int i = -1;

    i = gpio_event_added(gpio);
    if (i == 0) {    // event not already added
        if ((g = new_gpio(gpio)) == NULL)
            return 2;

        gpio_set_edge(gpio, edge);
        g->edge = edge;
        g->bouncetime = bouncetime;
    } else if (i == edge) {  // get existing event
        g = get_gpio(gpio);
        if ((bouncetime != -666 && g->bouncetime != bouncetime) ||  // different event bouncetime used
            (g->thread_added))                // event already added
            return 1;
    } else {
        return 1;
    }

    // create epfd_thread if not already open
    if ((epfd_thread == -1) && ((epfd_thread = epoll_create(1)) == -1))
        return 2;

    // add to epoll fd
    ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
    ev.data.fd = g->value_fd;
    if (epoll_ctl(epfd_thread, EPOLL_CTL_ADD, g->value_fd, &ev) == -1) {
        remove_edge_detect(gpio);
        return 2;
    }
    g->thread_added = 1;

    // start poll thread if it is not already running
    if (!thread_running) {
        if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0) {
           remove_edge_detect(gpio);
           return 2;
        }
    }
    return 0;
}
示例#2
0
int add_edge_detect(unsigned int gpio, unsigned int edge)
// return values:
// 0 - Success
// 1 - Edge detection already added
// 2 - Other error
{
    int fd;
    pthread_t threads;
    struct epoll_event ev;
    long t = 0;

    // check to see if this gpio has been added already
    if (gpio_event_added(gpio) != 0)
        return 1;

    // export /sys/class/gpio interface
    gpio_export(gpio);
    gpio_set_direction(gpio, 1); // 1=input
    gpio_set_edge(gpio, edge);
    if ((fd = open_value_file(gpio)) == -1)
        return 2;
    add_fd_list(gpio,fd);

    // create epfd if not already open
    if ((epfd == -1) && ((epfd = epoll_create(1)) == -1))
        return 2;

    // add to epoll fd
    ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
    ev.data.fd = fd;
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
        return 2;

    // start poll thread if it is not already running
    if (!thread_running)
    {
        if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0)
            return 2;
    }

    return 0;
}
示例#3
0
int add_edge_detect(unsigned int gpio, unsigned int edge, unsigned int bouncetime)
// return values:
// 0 - Success
// 1 - Edge detection already added
// 2 - Other error
{
    pthread_t threads;
    struct epoll_event ev;
    long t = 0;
    struct gpios *g;
    
    // check to see if this gpio has been added already
    if (gpio_event_added(gpio) != 0)
        return 1;

    // create epfd if not already open
    if ((epfd == -1) && ((epfd = epoll_create(1)) == -1))
        return 2;

    if ((g = new_gpio(gpio)) == NULL)
        return 2;
    
    gpio_set_edge(gpio, edge);
    g->bouncetime = bouncetime;

    // add to epoll fd
    ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
    ev.data.fd = g->value_fd;
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, g->value_fd, &ev) == -1) {
        remove_edge_detect(gpio);
        return 2;
    }

    // start poll thread if it is not already running
    if (!thread_running) {
        if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0) {
           remove_edge_detect(gpio);
           return 2;
        }
    }
    return 0;
}
示例#4
0
// python function add_event_callback(gpio, callback, bouncetime=0)
static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject *kwargs)
{
   unsigned int gpio;
   int channel;
   unsigned int bouncetime = 0;
   PyObject *cb_func;
   char *kwlist[] = {"gpio", "callback", "bouncetime", NULL};

   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO|i", kwlist, &channel, &cb_func, &bouncetime))
      return NULL;

   if (!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(WrongDirectionException, "You must setup() the GPIO channel as an input first");
      return NULL;
   }

   if (!gpio_event_added(gpio))
   {
      PyErr_SetString(AddEventException, "Add event detection using add_event_detect first before adding a callback");
      return NULL;
   }

   if (add_py_callback(gpio, bouncetime, cb_func) != 0)
      return NULL;

   Py_INCREF(Py_None);
   return Py_None;
}
示例#5
0
// python function add_event_callback(gpio, callback)
static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject *kwargs)
{
   unsigned int gpio;
   unsigned int sys_gpio;
   int channel;
   PyObject *cb_func;
   char *kwlist[] = {"gpio", "callback", NULL};

   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO|i", kwlist, &channel, &cb_func))
      return NULL;

   if (!PyCallable_Check(cb_func))
   {
      PyErr_SetString(PyExc_TypeError, "Parameter must be callable");
      return NULL;
   }

   if (get_gpio_number(channel, &gpio, &sys_gpio))
       return NULL;
    
   // check channel is set up 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;
   }

   if (!gpio_event_added(sys_gpio))
   {
      PyErr_SetString(PyExc_RuntimeError, "Add event detection using add_event_detect first before adding a callback");
      return NULL;
   }

   if (add_py_callback(sys_gpio, cb_func) != 0)
      return NULL;

   Py_RETURN_NONE;
}
int blocking_wait_for_edge(unsigned int gpio, unsigned int edge, int bouncetime, int timeout)
// return values:
//    1 - Success (edge detected)
//    0 - Timeout
//   -1 - Edge detection already added
//   -2 - Other error
{
    int n, ed;
    struct epoll_event events, ev;
    char buf;
    struct gpios *g = NULL;
    struct timeval tv_timenow;
    unsigned long long timenow;
    int finished = 0;
    int initial_edge = 1;

    if (callback_exists(gpio))
        return -1;

    // add gpio if it has not been added already
    ed = gpio_event_added(gpio);
    if (ed == edge) {   // get existing record
        g = get_gpio(gpio);
        if (g->bouncetime != -666 && g->bouncetime != bouncetime) {
            return -1;
        }
    } else if (ed == NO_EDGE) {   // not found so add event
        if ((g = new_gpio(gpio)) == NULL) {
            return -2;
        }
        gpio_set_edge(gpio, edge);
        g->edge = edge;
        g->bouncetime = bouncetime;
    } else {    // ed != edge - event for a different edge
        g = get_gpio(gpio);
        gpio_set_edge(gpio, edge);
        g->edge = edge;
        g->bouncetime = bouncetime;
        g->initial_wait = 1;
    }

    // create epfd_blocking if not already open
    if ((epfd_blocking == -1) && ((epfd_blocking = epoll_create(1)) == -1)) {
        return -2;
    }

    // add to epoll fd
    ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
    ev.data.fd = g->value_fd;
    if (epoll_ctl(epfd_blocking, EPOLL_CTL_ADD, g->value_fd, &ev) == -1) {
        return -2;
    }

    // wait for edge
    while (!finished) {
        if ((n = epoll_wait(epfd_blocking, &events, 1, timeout)) == -1) {
            epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
            return -2;
        }
        if (initial_edge) {    // first time triggers with current state, so ignore
            initial_edge = 0;
        } else {
            gettimeofday(&tv_timenow, NULL);
            timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec;
            if (g->bouncetime == -666 || timenow - g->lastcall > g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) {
                g->lastcall = timenow;
                finished = 1;
            }
        }
    }

    // check event was valid
    if (n > 0) {
        lseek(events.data.fd, 0, SEEK_SET);
        if ((read(events.data.fd, &buf, 1) != 1) || (events.data.fd != g->value_fd)) {
            epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
            return -2;
        }
    }

    epoll_ctl(epfd_blocking, EPOLL_CTL_DEL, g->value_fd, &ev);
    if (n == 0) {
       return 0; // timeout
    } else {
       return 1; // edge found
    }
}
示例#7
0
int blocking_wait_for_edge(unsigned int gpio, unsigned int edge)
// standalone from all the event functions above
{
    int epfd, fd, n, i;
    struct epoll_event events, ev;
    char buf;

    if ((epfd = epoll_create(1)) == -1)
        return 1;

    // check to see if this gpio has been added already
    if (gpio_event_added(gpio) != 0)
        return 2;

    // export /sys/class/gpio interface
    gpio_export(gpio);
    gpio_set_direction(gpio, 1); // 1=input
    gpio_set_edge(gpio, edge);
    if ((fd = open_value_file(gpio)) == -1)
        return 3;

    // add to epoll fd
    ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
    ev.data.fd = fd;
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
    {
        gpio_unexport(gpio);
        close(fd);
        return 4;
    }

    // epoll for event
    for (i = 0; i<2; i++) // first time triggers with current state, so ignore
       if ((n = epoll_wait(epfd, &events, 1, -1)) == -1)
       {
           gpio_unexport(gpio);
           close(fd);
           return 5;
       }

    if (n > 0)
    {
        lseek(events.data.fd, 0, SEEK_SET);
        if (read(events.data.fd, &buf, 1) != 1)
        {
            gpio_unexport(gpio);
            close(fd);
            return 6;
        }
        if (events.data.fd != fd)
        {
            gpio_unexport(gpio);
            close(fd);
            return 7;
        }
    }

    // clean up
    gpio_unexport(gpio);
    close(fd);
    close(epfd);
    return 0;
}