diff --git a/libs/eavmlib/src/gpio.erl b/libs/eavmlib/src/gpio.erl index f91ac90d1d..7699f90fac 100644 --- a/libs/eavmlib/src/gpio.erl +++ b/libs/eavmlib/src/gpio.erl @@ -41,6 +41,7 @@ stop/0, close/1 ]). + -export([ init/1, deinit/1, diff --git a/src/platforms/stm32/src/lib/gpio_driver.c b/src/platforms/stm32/src/lib/gpio_driver.c index 0eef6006ce..1e7781863a 100644 --- a/src/platforms/stm32/src/lib/gpio_driver.c +++ b/src/platforms/stm32/src/lib/gpio_driver.c @@ -64,6 +64,7 @@ #define INVALID_LEVEL_ATOM globalcontext_make_atom(ctx->global, ATOM_STR("\xD", "invalid_level")) #define INVALID_IRQ_ATOM globalcontext_make_atom(ctx->global, ATOM_STR("\xB", "invalid_irq")) #define INVALID_TRIGGER_ATOM globalcontext_make_atom(ctx->global, ATOM_STR("\xF", "invalid_trigger")) +#define INVALID_LISTENER_ATOM globalcontext_make_atom(ctx->global, ATOM_STR("\x10", "invalid_listener")) // Port driver specific data structures and definitions #ifndef AVM_DISABLE_GPIO_PORT_DRIVER @@ -719,6 +720,8 @@ static bool gpiodriver_is_gpio_attached(struct GPIOData *gpio_data, term gpio_ba static term gpiodriver_set_int(Context *ctx, int32_t target_pid, term cmd) { + int32_t target_local_pid; + term gpio_tuple = term_get_tuple_element(cmd, 1); if (UNLIKELY(!term_is_tuple(gpio_tuple))) { AVM_LOGE(TAG, "Invalid GPIO Pin tuple, expect {Bank, Pin}."); @@ -760,6 +763,27 @@ static term gpiodriver_set_int(Context *ctx, int32_t target_pid, term cmd) return create_pair(ctx, ERROR_ATOM, INVALID_TRIGGER_ATOM); } + if (term_get_tuple_arity(cmd) == 4) { + term pid = term_get_tuple_element(cmd, 3); + if (UNLIKELY(!term_is_pid(pid) && !term_is_atom(pid))) { + AVM_LOGE(TAG, "Invalid listener parameter, must be a pid() or registered process!"); + return create_pair(ctx, ERROR_ATOM, INVALID_LISTENER_ATOM); + } + if (term_is_pid(pid)) { + target_local_pid = term_to_local_process_id(pid); + } else { + int pid_atom_index = term_to_atom_index(pid); + int32_t registered_process = (int32_t) globalcontext_get_registered_process(ctx->global, pid_atom_index); + if (UNLIKELY(registered_process == 0)) { + AVM_LOGE(TAG, "Invalid listener parameter, atom() is not a registered process name!"); + return create_pair(ctx, ERROR_ATOM, NOPROC_ATOM); + } + target_local_pid = registered_process; + } + } else { + target_local_pid = target_pid; + } + uint32_t exti = 1U << gpio_pin; if (!list_is_empty(&gpio_data->gpio_listeners)) { @@ -788,7 +812,7 @@ static term gpiodriver_set_int(Context *ctx, int32_t target_pid, term cmd) AVM_ABORT(); } list_append(&gpio_data->gpio_listeners, &data->gpio_listener_list_head); - data->target_local_pid = target_pid; + data->target_local_pid = target_local_pid; data->bank_atom = gpio_bank_atom; data->gpio_pin = gpio_pin; data->exti = exti;