diff --git a/src/platforms/esp32/components/avm_builtins/gpio_driver.c b/src/platforms/esp32/components/avm_builtins/gpio_driver.c index ca7a2d325..4a488f610 100644 --- a/src/platforms/esp32/components/avm_builtins/gpio_driver.c +++ b/src/platforms/esp32/components/avm_builtins/gpio_driver.c @@ -32,7 +32,6 @@ #include "atom.h" #include "bif.h" #include "context.h" -#include "scheduler.h" #include "debug.h" #include "defaultatoms.h" #include "globalcontext.h" @@ -41,6 +40,7 @@ #include "module.h" #include "nifs.h" #include "platform_defaultatoms.h" +#include "scheduler.h" #include "term.h" #include "utils.h" @@ -52,7 +52,8 @@ #define TAG "gpio_driver" -static const char *const gpio_atom = "\x4" "gpio"; +static const char *const gpio_atom = "\x4" + "gpio"; #ifdef CONFIG_AVM_ENABLE_GPIO_NIFS static const struct Nif *gpio_nif_get_nif(const char *nifname); @@ -67,7 +68,8 @@ static void IRAM_ATTR gpio_isr_handler(void *arg); static Context *gpio_driver_create_port(GlobalContext *global, term opts); #endif -static const char *const gpio_driver_atom = "\xB" "gpio_driver"; +static const char *const gpio_driver_atom = "\xB" + "gpio_driver"; static const AtomStringIntPair pin_mode_table[] = { { ATOM_STR("\x5", "input"), GPIO_MODE_INPUT }, @@ -343,11 +345,32 @@ static bool gpiodriver_is_gpio_attached(struct GPIOData *gpio_data, int gpio_num static term gpiodriver_set_int(Context *ctx, int32_t target_pid, term cmd) { GlobalContext *glb = ctx->global; + int32_t target_local_pid; struct GPIOData *gpio_data = ctx->platform_data; int32_t gpio_num = term_to_int32(term_get_tuple_element(cmd, 1)); term trigger = term_get_tuple_element(cmd, 2); + 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))) { + ESP_LOGE(TAG, "Invalid listener parameter, must be a pid() or registered process!"); + return ERROR_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)) { + ESP_LOGE(TAG, "Invalid listener parameter, atom() is not a registered process name!"); + return ERROR_ATOM; + } + target_local_pid = registered_process; + } + } else { + target_local_pid = target_pid; + } if (gpiodriver_is_gpio_attached(gpio_data, gpio_num)) { return ERROR_ATOM; @@ -397,7 +420,7 @@ static term gpiodriver_set_int(Context *ctx, int32_t target_pid, term cmd) } list_append(&gpio_data->gpio_listeners, &data->gpio_listener_list_head); data->gpio = gpio_num; - data->target_local_pid = target_pid; + data->target_local_pid = target_local_pid; sys_register_listener(glb, &data->listener); data->listener.sender = data; data->listener.handler = gpio_interrupt_callback; @@ -581,44 +604,37 @@ static term nif_gpio_digital_read(Context *ctx, int argc, term argv[]) return gpio_digital_read(argv[0]); } -static const struct Nif gpio_set_pin_mode_nif = -{ +static const struct Nif gpio_set_pin_mode_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_gpio_set_pin_mode }; -static const struct Nif gpio_set_pin_pull_nif = -{ +static const struct Nif gpio_set_pin_pull_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_gpio_set_pin_pull }; -static const struct Nif gpio_hold_en_nif = -{ +static const struct Nif gpio_hold_en_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_gpio_hold_en }; -static const struct Nif gpio_hold_dis_nif = -{ +static const struct Nif gpio_hold_dis_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_gpio_hold_dis }; -static const struct Nif gpio_deep_sleep_hold_en_nif = -{ +static const struct Nif gpio_deep_sleep_hold_en_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_gpio_deep_sleep_hold_en }; -static const struct Nif gpio_deep_sleep_hold_dis_nif = -{ +static const struct Nif gpio_deep_sleep_hold_dis_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_gpio_deep_sleep_hold_dis }; -static const struct Nif gpio_digital_write_nif = -{ +static const struct Nif gpio_digital_write_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_gpio_digital_write };