diff --git a/include/mraa_adv_func.h b/include/mraa_adv_func.h index 94e4d5d..968ff90 100644 --- a/include/mraa_adv_func.h +++ b/include/mraa_adv_func.h @@ -54,6 +54,7 @@ typedef struct { mraa_result_t (*gpio_write_pre) (mraa_gpio_context dev, int value); mraa_result_t (*gpio_write_post) (mraa_gpio_context dev, int value); mraa_result_t (*gpio_mmap_setup) (mraa_gpio_context dev, mraa_boolean_t en); + void* (*gpio_interrupt_handler_replace) (mraa_gpio_context dev); mraa_result_t (*i2c_init_pre) (unsigned int bus); mraa_result_t (*i2c_init_bus_replace) (mraa_i2c_context dev); diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c index 2dcf60c..9e221eb 100644 --- a/src/gpio/gpio.c +++ b/src/gpio/gpio.c @@ -63,13 +63,14 @@ mraa_gpio_init_internal(mraa_adv_func_t* func_table, int pin) char bu[MAX_SIZE]; int length; - mraa_gpio_context dev = (mraa_gpio_context) malloc(sizeof(struct _gpio)); + mraa_gpio_context dev = (mraa_gpio_context) calloc(1, sizeof(struct _gpio)); if (dev == NULL) { syslog(LOG_CRIT, "gpio: Failed to allocate memory for context"); return NULL; } dev->advance_func = func_table; + dev->pin = pin; if (IS_FUNC_DEFINED(dev, gpio_init_internal_replace)) { status = dev->advance_func->gpio_init_internal_replace(pin); @@ -85,10 +86,8 @@ mraa_gpio_init_internal(mraa_adv_func_t* func_table, int pin) goto init_internal_cleanup; } - memset(dev, 0, sizeof(struct _gpio)); dev->value_fp = -1; dev->isr_value_fp = -1; - dev->pin = pin; dev->phy_pin = -1; // then check to make sure the pin is exported. @@ -214,6 +213,9 @@ static void* mraa_gpio_interrupt_handler(void* arg) { mraa_gpio_context dev = (mraa_gpio_context) arg; + if (IS_FUNC_DEFINED(dev, gpio_interrupt_handler_replace)) + return dev->advance_func->gpio_interrupt_handler_replace(dev); + mraa_result_t ret; // open gpio value with open(3) diff --git a/src/usb/ftdi_ft4222.c b/src/usb/ftdi_ft4222.c index adb766a..1d7ac4d 100644 --- a/src/usb/ftdi_ft4222.c +++ b/src/usb/ftdi_ft4222.c @@ -24,6 +24,8 @@ #include #include +#include +#include #include "linux/i2c-dev.h" #include "common.h" #include "ftd2xx.h" @@ -37,6 +39,8 @@ static FT_HANDLE ftHandle = (FT_HANDLE)NULL; static int bus_speed = 400; +static int numI2cGpioExapnderPins = 8; +static int numUsbGpio = 0; mraa_result_t @@ -362,13 +366,13 @@ mraa_ftdi_ft4222_gpio_init_internal_replace(int pin) static mraa_result_t mraa_ftdi_ft4222_gpio_mode_replace(mraa_gpio_context dev, mraa_gpio_mode_t mode) { - return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; + return MRAA_SUCCESS; } static mraa_result_t mraa_ftdi_ft4222_gpio_edge_mode_replace(mraa_gpio_context dev, mraa_gpio_edge_t mode) { - return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; + return MRAA_SUCCESS; } static int @@ -409,11 +413,38 @@ mraa_ftdi_ft4222_gpio_dir_replace(mraa_gpio_context dev, mraa_gpio_dir_t dir) return mraa_ftdi_ft4222_gpio_write_replace(dev, 1); case MRAA_GPIO_OUT_LOW: return mraa_ftdi_ft4222_gpio_write_replace(dev, 0); - default: - return MRAA_SUCCESS; + default:; } + return MRAA_SUCCESS; } +void mraa_ftdi_ft4222_sleep_ms(unsigned long mseconds) +{ + struct timespec sleepTime; + + sleepTime.tv_sec = mseconds / 1000; // Number of seconds + sleepTime.tv_nsec = ( mseconds % 1000 ) * 1000000; // Convert fractional seconds to nanoseconds + + // Iterate nanosleep in a loop until the total sleep time is the original + // value of the seconds parameter + while ( ( nanosleep( &sleepTime, &sleepTime ) != 0 ) && ( errno == EINTR ) ); +} + +static void* +mraa_ftdi_ft4222_gpio_interrupt_handler_replace(mraa_gpio_context dev) +{ + int prev_level = mraa_ftdi_ft4222_gpio_read_replace(dev); + while (1) { + int level = mraa_ftdi_ft4222_gpio_read_replace(dev); + if (level != prev_level) { + dev->isr(dev->isr_args); + prev_level = level; + } + // printf("mraa_ftdi_ft4222_gpio_interrupt_handler_replace\n"); + mraa_ftdi_ft4222_sleep_ms(100); + } + return NULL; +} static void mraa_ftdi_ft4222_populate_i2c_func_table(mraa_adv_func_t* func_table) @@ -442,6 +473,7 @@ mraa_ftdi_ft4222_populate_gpio_func_table(mraa_adv_func_t* func_table) func_table->gpio_dir_replace = &mraa_ftdi_ft4222_gpio_dir_replace; func_table->gpio_read_replace = &mraa_ftdi_ft4222_gpio_read_replace; func_table->gpio_write_replace = &mraa_ftdi_ft4222_gpio_write_replace; + func_table->gpio_interrupt_handler_replace = &mraa_ftdi_ft4222_gpio_interrupt_handler_replace; } @@ -453,7 +485,7 @@ mraa_ftdi_ft4222() return NULL; mraa_boolean_t haveGpio = mraa_ftdi_ft4222_detect_io_expander(); int pinIndex = 0; - int numUsbGpio = haveGpio ? 8 : 0; + numUsbGpio = haveGpio ? numI2cGpioExapnderPins : 0; int numUsbPins = numUsbGpio + 2; // Add SDA and SCL sub_plat->platform_name = PLATFORM_NAME; sub_plat->phy_pin_count = numUsbPins;