gpio: add interrupted callback 92/164192/5
authorSegwon <segwon.han@samsung.com>
Mon, 18 Dec 2017 02:42:48 +0000 (11:42 +0900)
committerSegwon <segwon.han@samsung.com>
Mon, 18 Dec 2017 12:34:00 +0000 (21:34 +0900)
Change-Id: I6d8d2b3e6382e3ecc2ebbc7cee8747fc2290fae9
Signed-off-by: Segwon <segwon.han@samsung.com>
include/interface/peripheral_interface_gpio.h
include/peripheral_handle.h
src/interface/peripheral_interface_gpio.c
src/peripheral_gpio.c

index d4ca75d..bfc7b09 100644 (file)
@@ -32,7 +32,7 @@ int peripheral_interface_gpio_set_direction(peripheral_gpio_h gpio, peripheral_g
 int peripheral_interface_gpio_write(peripheral_gpio_h gpio, uint32_t value);
 int peripheral_interface_gpio_read(peripheral_gpio_h gpio, uint32_t *value);
 
-int peripheral_interface_gpio_open_isr(peripheral_gpio_h gpio);
-int peripheral_interface_gpio_close_isr(peripheral_gpio_h gpio);
+int peripheral_interface_gpio_set_interrupted_cb(peripheral_gpio_h gpio, peripheral_gpio_interrupted_cb callback, void *user_data);
+int peripheral_interface_gpio_unset_interrupted_cb(peripheral_gpio_h gpio);
 
 #endif/*__PERIPHERAL_INTERFACE_GPIO_H__*/
\ No newline at end of file
index b834d06..e07c4f1 100644 (file)
 #ifndef __PERIPHERAL_HANDLE_H__
 #define __PERIPHERAL_HANDLE_H__
 
+#include <gio/gio.h>
+
+typedef struct _peripheral_gpio_interrupted_cb_info_s {
+       GThread *thread;
+       peripheral_gpio_interrupted_cb cb;
+       peripheral_error_e error;
+       void *user_data;
+       int status;
+} interrupted_cb_info_s;
+
 /**
  * @brief Internal struct for gpio context
  */
@@ -27,6 +37,7 @@ struct _peripheral_gpio_s {
        int fd_value;
        peripheral_gpio_direction_e direction;
        peripheral_gpio_edge_e edge;
+       interrupted_cb_info_s cb_info;
 };
 
 /**
index 119230d..c8dd33b 100644 (file)
  * limitations under the License.
  */
 
+#include <poll.h>
 #include "peripheral_interface_gpio.h"
 
+#define GPIO_INTERRUPTED_CALLBACK_UNSET 0
+#define GPIO_INTERRUPTED_CALLBACK_SET   1
+
 int peripheral_interface_gpio_set_initial_direction_into_handle(peripheral_gpio_h gpio)
 {
        static predefined_type_s types[2] = {
@@ -155,6 +159,7 @@ int peripheral_interface_gpio_read(peripheral_gpio_h gpio, uint32_t *value)
        int length = 1;
        char gpio_buf[GPIO_BUFFER_MAX] = {0, };
 
+       lseek(gpio->fd_value, 0, SEEK_SET);
        ret = read(gpio->fd_value, &gpio_buf, length);
        CHECK_ERROR(ret != length);
 
@@ -172,21 +177,89 @@ int peripheral_interface_gpio_read(peripheral_gpio_h gpio, uint32_t *value)
 
 void peripheral_interface_gpio_close(peripheral_gpio_h gpio)
 {
+       peripheral_interface_gpio_unset_interrupted_cb(gpio);
+
        close(gpio->fd_direction);
        close(gpio->fd_edge);
        close(gpio->fd_value);
 }
 
-int peripheral_interface_gpio_open_isr(peripheral_gpio_h gpio)
+static gboolean __peripheral_interface_gpio_interrupted_cb_invoke(gpointer data)
 {
-       // TODO: set interrupted callback function
+       peripheral_gpio_h gpio = (peripheral_gpio_h)data;
+       gpio->cb_info.cb(gpio, gpio->cb_info.error, NULL);
+       return FALSE;
+}
 
-       return PERIPHERAL_ERROR_NONE;
+static gpointer __peripheral_interface_gpio_poll(void *data)
+{
+       peripheral_gpio_h gpio = (peripheral_gpio_h)data;
+
+       int ret;
+       int poll_state = 0;
+       struct pollfd poll_fd;
+
+       poll_fd.fd = gpio->fd_value;
+       poll_fd.events = POLLPRI;
+
+       uint32_t value;
+
+       while (gpio->cb_info.status == GPIO_INTERRUPTED_CALLBACK_SET) {
+
+               poll_state = poll(&poll_fd, 1, 3000);
+
+               if (poll_state == 0)
+                       continue;
+
+               if (poll_state < 0) {
+                       _E("poll failed!");
+                       gpio->cb_info.error = PERIPHERAL_ERROR_IO_ERROR;
+                       g_idle_add_full(G_PRIORITY_HIGH_IDLE, __peripheral_interface_gpio_interrupted_cb_invoke, gpio, NULL);
+                       break;
+               }
+
+               if (poll_fd.revents & POLLPRI) {
+                       ret = peripheral_interface_gpio_read(gpio, &value);
+                       if (ret != PERIPHERAL_ERROR_NONE)
+                               continue;
+               } else {
+                       continue;
+               }
+
+               if (gpio->edge == PERIPHERAL_GPIO_EDGE_NONE)
+                       continue;
+
+               if (gpio->edge == PERIPHERAL_GPIO_EDGE_RISING && value == 0)
+                       continue;
+
+               if (gpio->edge == PERIPHERAL_GPIO_EDGE_FALLING && value == 1)
+                       continue;
+
+               gpio->cb_info.error = PERIPHERAL_ERROR_NONE;
+               g_idle_add_full(G_PRIORITY_HIGH_IDLE, __peripheral_interface_gpio_interrupted_cb_invoke, gpio, NULL);
+       }
+
+       return NULL;
 }
 
-int peripheral_interface_gpio_close_isr(peripheral_gpio_h gpio)
+int peripheral_interface_gpio_set_interrupted_cb(peripheral_gpio_h gpio, peripheral_gpio_interrupted_cb callback, void *user_data)
 {
-       // TODO: unset interrupted callback function
+       RETV_IF(gpio->direction != PERIPHERAL_GPIO_DIRECTION_IN, PERIPHERAL_ERROR_IO_ERROR);
+
+       peripheral_interface_gpio_unset_interrupted_cb(gpio);
+
+       gpio->cb_info.cb = callback;
+       gpio->cb_info.user_data = user_data;
+       gpio->cb_info.status = GPIO_INTERRUPTED_CALLBACK_SET;
+       gpio->cb_info.thread = g_thread_new(NULL, __peripheral_interface_gpio_poll, gpio);
 
        return PERIPHERAL_ERROR_NONE;
 }
+
+int peripheral_interface_gpio_unset_interrupted_cb(peripheral_gpio_h gpio)
+{
+       gpio->cb_info.status = GPIO_INTERRUPTED_CALLBACK_UNSET;
+       g_thread_join(gpio->cb_info.thread);
+
+       return PERIPHERAL_ERROR_NONE;
+}
\ No newline at end of file
index 4cd0290..b51c577 100644 (file)
@@ -151,7 +151,7 @@ int peripheral_gpio_set_interrupted_cb(peripheral_gpio_h gpio, peripheral_gpio_i
        RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
        RETVM_IF(callback == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio interrupted callback is NULL");
 
-       // TODO : replace interface function
+       peripheral_interface_gpio_set_interrupted_cb(gpio, callback, user_data);
 
        return ret;
 }
@@ -166,7 +166,7 @@ int peripheral_gpio_unset_interrupted_cb(peripheral_gpio_h gpio)
        RETVM_IF(__is_feature_supported() == false, PERIPHERAL_ERROR_NOT_SUPPORTED, "GPIO feature is not supported");
        RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
 
-       // TODO : replace interface function
+       peripheral_interface_gpio_unset_interrupted_cb(gpio);
 
        return ret;
 }