Support gpio interrupt 41/127641/4
authorjino.cho <jino.cho@samsung.com>
Tue, 18 Apr 2017 07:29:27 +0000 (16:29 +0900)
committerjino.cho <jino.cho@samsung.com>
Tue, 2 May 2017 02:12:23 +0000 (11:12 +0900)
The gpio interrupt should work properly if the patch for
peripheral-io is applied together.

Change-Id: I0bf71501b54728ad0ce83a623e084bf8227b3e9a
Signed-off-by: jino.cho <jino.cho@samsung.com>
src/daemon/peripheral_bus.c
src/daemon/peripheral_bus.h
src/daemon/peripheral_bus_gpio.c
src/daemon/peripheral_bus_gpio.h
src/daemon/peripheral_io.xml

index 5915167..bb2db5d 100644 (file)
@@ -150,6 +150,34 @@ gboolean handle_gpio_set_edge_mode(
        return true;
 }
 
+gboolean handle_gpio_register_irq(
+               PeripheralIoGdbusGpio *gpio,
+               GDBusMethodInvocation *invocation,
+               gint pin,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+
+       ret = peripheral_bus_gpio_register_irq(pin, user_data);
+       peripheral_io_gdbus_gpio_complete_register_irq(gpio, invocation, ret);
+
+       return true;
+}
+
+gboolean handle_gpio_unregister_irq(
+               PeripheralIoGdbusGpio *gpio,
+               GDBusMethodInvocation *invocation,
+               gint pin,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+
+       ret = peripheral_bus_gpio_unregister_irq(pin, user_data);
+       peripheral_io_gdbus_gpio_complete_unregister_irq(gpio, invocation, ret);
+
+       return true;
+}
+
 gboolean handle_i2c_open(
                PeripheralIoGdbusI2c *i2c,
                GDBusMethodInvocation *invocation,
@@ -382,6 +410,14 @@ gboolean handle_pwm_get_period(
        return true;
 }
 
+void peripheral_bus_emit_gpio_changed(PeripheralIoGdbusGpio *gpio,
+                                                                       gint pin,
+                                                                       gint state)
+{
+       g_assert(gpio != NULL);
+
+       peripheral_io_gdbus_gpio_emit_gpio_changed(gpio, pin, state);
+}
 
 static gboolean __gpio_init(peripheral_bus_s *pb_data)
 {
@@ -424,6 +460,14 @@ static gboolean __gpio_init(peripheral_bus_s *pb_data)
                        "handle-set-edge-mode",
                        G_CALLBACK(handle_gpio_set_edge_mode),
                        pb_data);
+       g_signal_connect(pb_data->gpio_skeleton,
+                       "handle-register-irq",
+                       G_CALLBACK(handle_gpio_register_irq),
+                       pb_data);
+       g_signal_connect(pb_data->gpio_skeleton,
+                       "handle-unregister-irq",
+                       G_CALLBACK(handle_gpio_unregister_irq),
+                       pb_data);
 
        manager = g_dbus_object_manager_server_new(PERIPHERAL_DBUS_GPIO_PATH);
 
index 1a2d65a..a79c7d7 100644 (file)
@@ -35,11 +35,17 @@ typedef struct {
        int direction;
        int edge;
        /* interrupt variable */
+       int irq_en;
        int value_fd;
        GIOChannel *io;
        guint io_id;
+       /* gdbus variable */
+       PeripheralIoGdbusGpio *gpio_skeleton;
 } peripheral_bus_gpio_data_s;
 
 typedef peripheral_bus_gpio_data_s * pb_gpio_data_h;
 
+void peripheral_bus_emit_gpio_changed(PeripheralIoGdbusGpio *gpio,
+                                                                       gint pin,
+                                                                       gint state);
 #endif /* __PERIPHERAL_BUS_H__ */
index 621cef0..dbf9a69 100644 (file)
@@ -124,6 +124,7 @@ int peripheral_bus_gpio_open(gint pin, gint *edge, gint *direction, gpointer use
        gpio->pin = pin;
        gpio->edge = *edge;
        gpio->direction = *direction;
+       gpio->gpio_skeleton = pb_data->gpio_skeleton;
 
        return PERIPHERAL_ERROR_NONE;
 
@@ -276,6 +277,128 @@ int peripheral_bus_gpio_read(gint pin, gint *value, gpointer user_data)
        return PERIPHERAL_ERROR_NONE;
 }
 
+static gboolean  peripheral_bus_gpio_cb(GIOChannel *io, GIOCondition condition, gpointer data)
+{
+       pb_gpio_data_h gpio_data = (pb_gpio_data_h)data;
+       GIOStatus status;
+       gchar* strval;
+       int value;
+
+       if (!gpio_data->irq_en)
+               return TRUE;
+
+       if (gpio_data->direction != PERIPHERAL_GPIO_DIRECTION_IN
+               || gpio_data->edge == PERIPHERAL_GPIO_EDGE_NONE)
+               return TRUE;
+
+       g_io_channel_seek_position(io, 0, G_SEEK_SET, NULL);
+       status = g_io_channel_read_line(io, &strval, NULL, NULL, NULL);
+       if (status != G_IO_STATUS_NORMAL) {
+               _E("Unable to read gpio value (%d)", status);
+               return FALSE;
+       }
+       g_strstrip(strval);
+
+       _D("gpio = %d, data = %s", gpio_data->pin, strval);
+
+       if (g_ascii_strcasecmp(strval, "1") == 0)
+               value = 1;
+       else if (g_ascii_strcasecmp(strval, "0") == 0)
+               value = 0;
+       else {
+               g_free(strval);
+               _E("Error: gpio value is error");
+               return FALSE;
+       }
+       g_free(strval);
+
+       if (gpio_data->edge == PERIPHERAL_GPIO_EDGE_RISING && value == 0)
+               return TRUE;
+       else if (gpio_data->edge == PERIPHERAL_GPIO_EDGE_FALLING && value == 1)
+               return TRUE;
+
+       peripheral_bus_emit_gpio_changed(gpio_data->gpio_skeleton, gpio_data->pin, value);
+
+       return TRUE;
+}
+
+int peripheral_bus_gpio_register_irq(gint pin, gpointer user_data)
+{
+       peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+       pb_gpio_data_h gpio;
+       GIOStatus status;
+       gchar* strval;
+
+       gpio = peripheral_bus_gpio_data_get(pin, &pb_data->gpio_list);
+       if (!gpio) {
+               _E("peripheral_bus_gpio_data_get error");
+               return PERIPHERAL_ERROR_UNKNOWN;
+       }
+
+       if ((gpio->value_fd = gpio_open_isr(pin)) < 0)
+               goto err_open_isr;
+
+       gpio->io = g_io_channel_unix_new(gpio->value_fd);
+       if (gpio->io == NULL) {
+               _E("g_io_channel_unix_new error (%d)", gpio->value_fd);
+               goto err_io_channel_new;
+       }
+
+       g_io_channel_seek_position(gpio->io, 0, G_SEEK_SET, NULL);
+       status = g_io_channel_read_line(gpio->io, &strval, NULL, NULL, NULL);
+       if (status != G_IO_STATUS_NORMAL) {
+               _E("Unable to read gpio value (%d)", status);
+               goto err_io_channel_read;
+       }
+       g_free(strval);
+
+       gpio->io_id = g_io_add_watch(gpio->io, G_IO_PRI, peripheral_bus_gpio_cb, gpio);
+       if (gpio->io_id < 0) {
+               _E("g_io_add_watch error (%d)", gpio->io);
+               goto err_io_add_watch;
+       }
+       g_io_channel_unref(gpio->io);
+       gpio->irq_en = 1;
+
+       return PERIPHERAL_ERROR_NONE;
+
+err_io_add_watch:
+err_io_channel_read:
+       g_io_channel_unref(gpio->io);
+       gpio->io_id = 0;
+err_io_channel_new:
+       gpio_close_isr(gpio->value_fd);
+       gpio->io = 0;
+err_open_isr:
+       gpio->value_fd = 0;
+
+       return PERIPHERAL_ERROR_UNKNOWN;
+}
+
+int peripheral_bus_gpio_unregister_irq(gint pin, gpointer user_data)
+{
+       peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+       pb_gpio_data_h gpio;
+
+       gpio = peripheral_bus_gpio_data_get(pin, &pb_data->gpio_list);
+       if (!gpio) {
+               _E("peripheral_bus_gpio_data_get error");
+               return PERIPHERAL_ERROR_UNKNOWN;
+       }
+
+       if (gpio->io) {
+               gpio->irq_en = 0;
+               g_source_remove(gpio->io_id);
+               gpio->io_id = 0;
+               g_io_channel_unref(gpio->io);
+               gpio->io = 0;
+               gpio_close_isr(gpio->value_fd);
+               gpio->value_fd = 0;
+       }
+
+       return PERIPHERAL_ERROR_NONE;
+}
+
 int peripheral_bus_gpio_close(gint pin, gpointer user_data)
 {
        peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
index 5236fee..e7d36cf 100644 (file)
@@ -24,6 +24,8 @@ int peripheral_bus_gpio_set_edge(gint pin, gint edge, gpointer user_data);
 int peripheral_bus_gpio_get_edge(gint pin, gint *edge, gpointer user_data);
 int peripheral_bus_gpio_write(gint pin, gint value, gpointer user_data);
 int peripheral_bus_gpio_read(gint pin, gint *value, gpointer user_data);
+int peripheral_bus_gpio_register_irq(gint pin, gpointer user_data);
+int peripheral_bus_gpio_unregister_irq(gint pin, gpointer user_data);
 int peripheral_bus_gpio_close(gint pin, gpointer user_data);
 
 #endif /* __PERIPHERAL_BUS_GPIO_H__ */
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">