Support gpio interrupt 40/127640/4
authorjino.cho <jino.cho@samsung.com>
Thu, 20 Apr 2017 01:33:55 +0000 (10:33 +0900)
committerjino.cho <jino.cho@samsung.com>
Tue, 2 May 2017 02:10:15 +0000 (11:10 +0900)
The gpio interrupt should work properly if the patch for
peripheral-bus is applied together.

Change-Id: I1c7b0b9db563ea3b3fd222bb4b05b1dbc7b279c8
Signed-off-by: jino.cho <jino.cho@samsung.com>
include/peripheral_dbus.h
src/peripheral_dbus.c
src/peripheral_gpio.c
src/peripheral_io.xml
test/peripheral-io-test.c

index 529128d..e1002fa 100644 (file)
@@ -47,6 +47,8 @@ int peripheral_dbus_gpio_read(peripheral_gpio_h gpio, int *value);
 int peripheral_dbus_gpio_write(peripheral_gpio_h gpio, int value);
 int peripheral_dbus_gpio_get_edge_mode(peripheral_gpio_h gpio, peripheral_gpio_edge_e *edge);
 int peripheral_dbus_gpio_set_edge_mode(peripheral_gpio_h gpio, peripheral_gpio_edge_e edge);
+int peripheral_dbus_gpio_register_cb(peripheral_gpio_h gpio, gpio_isr_cb callback, void *user_data);
+int peripheral_dbus_gpio_unregister_cb(peripheral_gpio_h gpio);
 
 int peripheral_dbus_i2c_open(peripheral_i2c_h i2c, int bus, int address);
 int peripheral_dbus_i2c_close(peripheral_i2c_h i2c);
index e685b71..3a61390 100644 (file)
@@ -24,6 +24,9 @@
 #include "peripheral_internal.h"
 #include "peripheral_io_gdbus.h"
 
+extern int peripheral_gpio_isr_callback(int pin);
+void handle_gpio_changed(PeripheralIoGdbusGpio *gpio, gint pin, gint state, gpointer user_data);
+
 PeripheralIoGdbusGpio *gpio_proxy = NULL;
 PeripheralIoGdbusI2c *i2c_proxy = NULL;
 PeripheralIoGdbusPwm *pwm_proxy = NULL;
@@ -42,6 +45,16 @@ void gpio_proxy_init(void)
                PERIPHERAL_DBUS_GPIO_PATH,
                NULL,
                &error);
+       if (gpio_proxy == NULL) {
+               _E("Can not create gpio proxy : %s", error->message);
+               g_error_free(error);
+               return;
+       }
+
+       g_signal_connect(gpio_proxy,
+                       "gpio-changed",
+                       G_CALLBACK(handle_gpio_changed),
+                       NULL);
 }
 
 void i2c_proxy_init(void)
@@ -100,6 +113,20 @@ void pwm_proxy_deinit()
        }
 }
 
+void handle_gpio_changed(
+               PeripheralIoGdbusGpio *gpio,
+               gint pin,
+               gint state,
+               gpointer user_data)
+{
+       if (!gpio)
+               return;
+
+       _D("gpio=%d state=%d",pin, state);
+
+       peripheral_gpio_isr_callback(pin);
+}
+
 int peripheral_dbus_gpio_open(peripheral_gpio_h gpio)
 {
        GError *error = NULL;
@@ -280,6 +307,48 @@ int peripheral_dbus_gpio_set_edge_mode(peripheral_gpio_h gpio, peripheral_gpio_e
        return ret;
 }
 
+int peripheral_dbus_gpio_register_cb(peripheral_gpio_h gpio, gpio_isr_cb callback, void *user_data)
+{
+       GError *error = NULL;
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+
+       if (gpio_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN;
+
+       if (peripheral_io_gdbus_gpio_call_register_irq_sync(
+                       gpio_proxy,
+                       gpio->pin,
+                       &ret,
+                       NULL,
+                       &error) == FALSE) {
+               _E("Error in %s() : %s\n", __func__, error->message);
+               g_error_free(error);
+               return PERIPHERAL_ERROR_UNKNOWN;
+       }
+
+       return ret;
+}
+
+int peripheral_dbus_gpio_unregister_cb(peripheral_gpio_h gpio)
+{
+       GError *error = NULL;
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+
+       if (gpio_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN;
+
+       if (peripheral_io_gdbus_gpio_call_unregister_irq_sync(
+                       gpio_proxy,
+                       gpio->pin,
+                       &ret,
+                       NULL,
+                       &error) == FALSE) {
+               _E("Error in %s() : %s\n", __func__, error->message);
+               g_error_free(error);
+               return PERIPHERAL_ERROR_UNKNOWN;
+       }
+
+       return ret;
+}
+
 int peripheral_dbus_i2c_open(peripheral_i2c_h i2c, int bus, int address)
 {
        GError *error = NULL;
index 5520c87..f942759 100644 (file)
 #include "peripheral_internal.h"
 #include "peripheral_io_gdbus.h"
 
+typedef struct {
+       int pin;
+       gpio_isr_cb callback;
+       void *user_data;
+} gpio_isr_data_s;
+
+static GList *gpio_isr_list = NULL;
+
+int peripheral_gpio_isr_callback(int pin)
+{
+       GList *link;
+       gpio_isr_data_s *isr_data;
+
+       link = gpio_isr_list;
+       while (link) {
+               isr_data = (gpio_isr_data_s*)link->data;
+
+               if (isr_data->pin == pin) {
+                       if (isr_data->callback)
+                               isr_data->callback(isr_data->user_data);
+                       return PERIPHERAL_ERROR_NONE;
+               }
+               link = g_list_next(link);
+       }
+
+       return PERIPHERAL_ERROR_NONE;
+}
+
+int peripheral_gpio_isr_set(int pin, gpio_isr_cb callback, void *user_data)
+{
+       GList *link;
+       gpio_isr_data_s *isr_data = NULL;
+
+       link = gpio_isr_list;
+       while (link) {
+               gpio_isr_data_s *tmp;
+               tmp = (gpio_isr_data_s*)link->data;
+               if (tmp->pin == pin) {
+                       isr_data = tmp;
+                       break;
+               }
+               link = g_list_next(link);
+       }
+
+       if (isr_data == NULL) {
+               isr_data = (gpio_isr_data_s*)calloc(1, sizeof(gpio_isr_data_s));
+               if (isr_data == NULL) {
+                       _E("failed to allocate gpio_isr_data_s");
+                       return PERIPHERAL_ERROR_OUT_OF_MEMORY;
+               }
+
+               gpio_isr_list = g_list_append(gpio_isr_list, isr_data);
+       }
+
+       isr_data->pin = pin;
+       isr_data->callback = callback;
+       isr_data->user_data = user_data;
+
+       return PERIPHERAL_ERROR_NONE;
+}
+
+int peripheral_gpio_isr_unset(int pin)
+{
+       GList *link;
+       gpio_isr_data_s *isr_data;
+
+       link = gpio_isr_list;
+       while (link) {
+               isr_data = (gpio_isr_data_s*)link->data;
+
+               if (isr_data->pin == pin) {
+                       gpio_isr_list = g_list_remove_link(gpio_isr_list, link);
+                       free(link->data);
+                       g_list_free(link);
+                       break;
+               }
+               link = g_list_next(link);
+       }
+
+       return PERIPHERAL_ERROR_NONE;
+}
+
 /**
  * @brief Initializes(export) gpio pin and creates gpio handle.
  */
@@ -202,12 +284,20 @@ int peripheral_gpio_set_edge_mode(peripheral_gpio_h gpio, peripheral_gpio_edge_e
  */
 int peripheral_gpio_register_cb(peripheral_gpio_h gpio, gpio_isr_cb callback, void *user_data)
 {
+       int ret = PERIPHERAL_ERROR_NONE;
+
        /* check validation of gpio context handle */
        if (gpio == NULL)
                return PERIPHERAL_ERROR_INVALID_PARAMETER;
 
-       //TODO
-       return PERIPHERAL_ERROR_INVALID_OPERATION;
+       ret = peripheral_dbus_gpio_register_cb(gpio, callback, user_data);
+       if (ret != PERIPHERAL_ERROR_NONE)
+               return ret;
+
+       /* set isr */
+       ret = peripheral_gpio_isr_set(gpio->pin, callback, user_data);
+
+       return ret;
 }
 
 /**
@@ -215,11 +305,20 @@ int peripheral_gpio_register_cb(peripheral_gpio_h gpio, gpio_isr_cb callback, vo
  */
 int peripheral_gpio_unregister_cb(peripheral_gpio_h gpio)
 {
+       int ret = PERIPHERAL_ERROR_NONE;
+
        /* check validation of gpio context handle */
        if (gpio == NULL)
                return PERIPHERAL_ERROR_INVALID_PARAMETER;
-       //TODO
-       return PERIPHERAL_ERROR_INVALID_OPERATION;
+
+       ret = peripheral_dbus_gpio_unregister_cb(gpio);
+       if (ret != PERIPHERAL_ERROR_NONE)
+               return ret;
+
+       /* clean up isr */
+       ret = peripheral_gpio_isr_unset(gpio->pin);
+
+       return ret;
 }
 
 /**
index cbda49b..ed9559c 100644 (file)
                        <arg type="i" name="edge" direction="in"/>
                        <arg type="i" name="result" direction="out"/>
                </method>
+               <method name="RegisterIrq">
+                       <arg type="i" name="pin" direction="in"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="UnregisterIrq">
+                       <arg type="i" name="pin" direction="in"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <signal name='GpioChanged'>
+                       <arg type='i' name='pin'/>
+                       <arg type='i' name='state'/>
+               </signal>
        </interface>
        <interface name="org.tizen.peripheral_io.i2c">
                <method name="Open">
index 048d136..bec2885 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <gio/gio.h>
 
 extern int gpio_test();
 extern int i2c_test();
 extern int adc_test();
 
+GMainLoop *loop;
+
 int gpio_test(void)
 {
        int num;
@@ -64,6 +67,79 @@ error:
        return 0;
 }
 
+void gpio_irq_test_isr(void *user_data)
+{
+       int pin;
+       peripheral_gpio_h gpio = user_data;
+
+       peripheral_gpio_get_pin(gpio, &pin);
+
+       printf("gpio_irq_test_isr: GPIO %d interrupt occurs.\n", pin);
+}
+
+void *gpio_irq_test_thread(void *data)
+{
+       peripheral_gpio_h gpio = data;
+       int num;
+
+       printf(">> Press any key to exit GPIO IRQ Test : \n");
+       if (scanf("%d", &num) < 0)
+               return 0;
+
+       peripheral_gpio_unregister_cb(gpio);
+       peripheral_gpio_close(gpio);
+
+       g_main_loop_quit(loop);
+       return 0;
+}
+
+int gpio_irq_test(void)
+{
+       GThread *test_thread;
+       int num;
+       peripheral_gpio_h gpio = NULL;
+       peripheral_gpio_edge_e edge = PERIPHERAL_GPIO_EDGE_NONE;
+
+       printf("artik710 : 27 \n");
+       printf(">> PIN NUMBER : ");
+
+       if (scanf("%d", &num) < 0)
+               return 0;
+
+       if (peripheral_gpio_open(num, &gpio) != PERIPHERAL_ERROR_NONE) {
+               printf("test dev is null\n");
+               return 0;
+       }
+
+       if (peripheral_gpio_set_direction(gpio, PERIPHERAL_GPIO_DIRECTION_IN) != 0) {
+               printf("test set direction error!!!");
+               goto error;
+       }
+
+       printf(">> Select Edge Mode (0 = None, 1 = Falling, 2 = Rising, 3 = Both) : ");
+       if (scanf("%d", &num) < 0)
+               return 0;
+
+       if (num >= 0 && num <= 3)
+               edge = num;
+
+       peripheral_gpio_set_edge_mode( gpio, edge);
+       peripheral_gpio_register_cb(gpio, gpio_irq_test_isr, gpio);
+
+       test_thread = g_thread_new("key input thread", &gpio_irq_test_thread, gpio);
+       loop = g_main_loop_new(NULL, FALSE);
+       g_main_loop_run(loop);
+
+       g_thread_join(test_thread);
+       if (loop != NULL)
+               g_main_loop_unref(loop);
+
+       return 0;
+
+error:
+       peripheral_gpio_close(gpio);
+       return 0;
+}
 
 /* Address of GY30 light sensor */
 #define GY30_ADDR 0x23
@@ -233,7 +309,7 @@ int main(int argc, char **argv)
        printf(" 3. pwm led test\n");
        printf(" 4. pwm motor test\n");
 
-       printf(" 11. H/W IF GPIO Test\n");
+       printf(" 11. GPIO Interrupt Test\n");
        printf(" 12. H/W IF I2C Test\n");
        printf(" 13. H/W IF PWM Test\n");
        printf(" 14. H/W IF SPI Test\n");
@@ -255,7 +331,7 @@ int main(int argc, char **argv)
                ret = pwm_test_motor();
                break;
        case 11:
-               ret = gpio_test();
+               ret = gpio_irq_test();
                break;
        case 12:
                ret = i2c_test();