diff --git a/src/gpio.c b/src/gpio.c index f8e1470..c8d63dc 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -42,11 +42,43 @@ static char *gpio_in_names[] = { "status", }; +int gpio_line_get_value(struct EG25Manager *manager, int line) { + enum gpiod_line_value value; + value = gpiod_line_request_get_value(manager->gpio_in[line], manager->gpio_in_offset[line]); + + switch (value) { + case GPIOD_LINE_VALUE_ACTIVE: + return 1; + case GPIOD_LINE_VALUE_INACTIVE: + return 0; + case GPIOD_LINE_VALUE_ERROR: + g_warning("gpio: couldn't get value on line %d", line); + } + + return -1; +} + +int gpio_line_set_value(struct EG25Manager *manager, int line, int value) { + enum gpiod_line_value line_value = value ? GPIOD_LINE_VALUE_ACTIVE : GPIOD_LINE_VALUE_INACTIVE; + int ret; + + ret = gpiod_line_request_set_value(manager->gpio_out[line], manager->gpio_out_offset[line], line_value); + + if (ret) { + g_warning("gpio: couldn't set value %d on line %d", value, line); + return -1; + } + else { + manager->gpio_out_value[line] = value; + return 0; + } +} + int gpio_sequence_poweron(struct EG25Manager *manager) { - gpiod_line_set_value(manager->gpio_out[GPIO_OUT_PWRKEY], 1); + gpio_line_set_value(manager, GPIO_OUT_PWRKEY, 1); sleep(1); - gpiod_line_set_value(manager->gpio_out[GPIO_OUT_PWRKEY], 0); + gpio_line_set_value(manager, GPIO_OUT_PWRKEY, 0); g_message("Executed power-on/off sequence"); @@ -55,7 +87,7 @@ int gpio_sequence_poweron(struct EG25Manager *manager) int gpio_sequence_shutdown(struct EG25Manager *manager) { - gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DISABLE], 1); + gpio_line_set_value(manager, GPIO_OUT_DISABLE, 1); gpio_sequence_poweron(manager); g_message("Executed power-off sequence"); @@ -65,7 +97,7 @@ int gpio_sequence_shutdown(struct EG25Manager *manager) int gpio_sequence_suspend(struct EG25Manager *manager) { - gpiod_line_set_value(manager->gpio_out[GPIO_OUT_APREADY], 1); + gpio_line_set_value(manager, GPIO_OUT_APREADY, 1); g_message("Executed suspend sequence"); @@ -74,7 +106,7 @@ int gpio_sequence_suspend(struct EG25Manager *manager) int gpio_sequence_resume(struct EG25Manager *manager) { - gpiod_line_set_value(manager->gpio_out[GPIO_OUT_APREADY], 0); + gpio_line_set_value(manager, GPIO_OUT_APREADY, 0); g_message("Executed resume sequence"); @@ -83,8 +115,8 @@ int gpio_sequence_resume(struct EG25Manager *manager) int gpio_sequence_wake(struct EG25Manager *manager) { - if (gpiod_line_get_value(manager->gpio_out[GPIO_OUT_DTR])) { - gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DTR], 0); + if (manager->gpio_out_value[GPIO_OUT_DTR]) { + gpio_line_set_value(manager, GPIO_OUT_DTR, 0); /* Give the modem 200ms to wake from soft sleep */ usleep(200000); @@ -97,7 +129,7 @@ int gpio_sequence_wake(struct EG25Manager *manager) int gpio_sequence_sleep(struct EG25Manager *manager) { - gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DTR], 1); + gpio_line_set_value(manager, GPIO_OUT_DTR, 1); g_message("Executed soft sleep sequence"); return 0; @@ -311,6 +343,7 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) manager->gpio_out[i] = gpio_request_output_line(manager, chip.u.i, line.u.i); if (!manager->gpio_out[i]) g_error("Unable to get output GPIO %d", i); + manager->gpio_out_offset[i] = line.u.i; } for (i = 0; i < GPIO_IN_COUNT; i++) { @@ -335,6 +368,7 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) manager->gpio_in[i] = gpio_request_input_line(manager, chip.u.i, line.u.i); if (!manager->gpio_in[i]) g_error("Unable to get input GPIO %d", i); + manager->gpio_in_offset[i] = line.u.i; } } else { guint offset, chipidx, gpio_idx; @@ -363,6 +397,7 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) manager->gpio_out[i] = gpio_request_input_line(manager, chipidx, offset); if (!manager->gpio_out[i]) g_error("Unable to get output GPIO %d", i); + manager->gpio_out_offset[i] = offset; } for (i = 0; i < GPIO_IN_COUNT; i++) { @@ -380,6 +415,7 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) manager->gpio_in[i] = gpio_request_input_line(manager, chipidx, offset); if (!manager->gpio_in[i]) g_error("Unable to get input GPIO %d", i); + manager->gpio_in_offset[i] = offset; } } @@ -389,11 +425,11 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) gboolean gpio_check_poweroff(struct EG25Manager *manager, gboolean keep_down) { if (manager->gpio_in[GPIO_IN_STATUS] && - gpiod_line_get_value(manager->gpio_in[GPIO_IN_STATUS]) == 1) { + gpio_line_get_value(manager, GPIO_IN_STATUS) == 1) { if (keep_down && manager->gpio_out[GPIO_OUT_RESET]) { // Asserting RESET line to prevent modem from rebooting - gpiod_line_set_value(manager->gpio_out[GPIO_OUT_RESET], 1); + gpio_line_set_value(manager, GPIO_OUT_RESET, 1); } return TRUE; diff --git a/src/manager.h b/src/manager.h index 3c25ecc..4d90e31 100644 --- a/src/manager.h +++ b/src/manager.h @@ -117,7 +117,10 @@ struct EG25Manager { struct gpiod_chip *gpiochip[2]; struct gpiod_line_request *gpio_out[5]; + guint gpio_out_value[5]; + guint gpio_out_offset[5]; struct gpiod_line_request *gpio_in[2]; + guint gpio_in_offset[5]; }; void modem_configure(struct EG25Manager *data);