From 1762a85eacbe1aa7f7e4cd82d0030d41793f7847 Mon Sep 17 00:00:00 2001 From: "jino.cho" Date: Thu, 20 Apr 2017 10:33:55 +0900 Subject: [PATCH] Support gpio interrupt The gpio interrupt should work properly if the patch for peripheral-bus is applied together. Change-Id: I1c7b0b9db563ea3b3fd222bb4b05b1dbc7b279c8 Signed-off-by: jino.cho --- include/peripheral_dbus.h | 2 + src/peripheral_dbus.c | 69 ++++++++++++++++++++++++++++++ src/peripheral_gpio.c | 107 ++++++++++++++++++++++++++++++++++++++++++++-- src/peripheral_io.xml | 12 ++++++ test/peripheral-io-test.c | 80 +++++++++++++++++++++++++++++++++- 5 files changed, 264 insertions(+), 6 deletions(-) diff --git a/include/peripheral_dbus.h b/include/peripheral_dbus.h index 529128d..e1002fa 100644 --- a/include/peripheral_dbus.h +++ b/include/peripheral_dbus.h @@ -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); diff --git a/src/peripheral_dbus.c b/src/peripheral_dbus.c index e685b71..3a61390 100644 --- a/src/peripheral_dbus.c +++ b/src/peripheral_dbus.c @@ -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; diff --git a/src/peripheral_gpio.c b/src/peripheral_gpio.c index 5520c87..f942759 100644 --- a/src/peripheral_gpio.c +++ b/src/peripheral_gpio.c @@ -25,6 +25,88 @@ #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; } /** diff --git a/src/peripheral_io.xml b/src/peripheral_io.xml index cbda49b..ed9559c 100644 --- a/src/peripheral_io.xml +++ b/src/peripheral_io.xml @@ -41,6 +41,18 @@ + + + + + + + + + + + + diff --git a/test/peripheral-io-test.c b/test/peripheral-io-test.c index 048d136..bec2885 100644 --- a/test/peripheral-io-test.c +++ b/test/peripheral-io-test.c @@ -19,11 +19,14 @@ #include #include #include +#include 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(); -- 2.7.4