diff --git a/meson.build b/meson.build index cb0d72e..069147b 100644 --- a/meson.build +++ b/meson.build @@ -8,7 +8,7 @@ project ( 'eg25manager', 'c', - version : '0.1.1', + version : '0.1.2', license : 'GPLv3+', meson_version : '>= 0.50.0', default_options : diff --git a/src/at.c b/src/at.c index e035d34..39a857a 100644 --- a/src/at.c +++ b/src/at.c @@ -80,8 +80,7 @@ static gboolean send_at_command(struct EG25Manager *manager) else manager->modem_state = EG25_STATE_CONFIGURED; } else if (manager->modem_state == EG25_STATE_SUSPENDING) { - g_message("suspend sequence is over, drop inhibitor"); - suspend_inhibit(manager, FALSE); + modem_suspend_post(manager); } else if (manager->modem_state == EG25_STATE_RESETTING) { manager->modem_state = EG25_STATE_POWERED; } @@ -122,7 +121,7 @@ static void retry_at_command(struct EG25Manager *manager) g_critical("Command %s retried %d times, aborting...", at_cmd->cmd, at_cmd->retries); next_at_command(manager); } else { - g_timeout_add_seconds(3, G_SOURCE_FUNC(send_at_command), manager); + g_timeout_add(500, G_SOURCE_FUNC(send_at_command), manager); } } @@ -269,14 +268,18 @@ void at_sequence_configure(struct EG25Manager *manager) append_at_command(manager, "QCFG", "apready", NULL, "1,0,500"); } append_at_command(manager, "QURCCFG", "urcport", NULL, "\"usbat\""); - append_at_command(manager, "QGPS", NULL, NULL, "1"); + if (manager->manage_gnss) + append_at_command(manager, "QGPS", NULL, NULL, "1"); append_at_command(manager, "QSCLK", NULL, "1", NULL); + // Make sure URC cache is disabled + append_at_command(manager, "QCFG", "urc/cache", "0", NULL); send_at_command(manager); } void at_sequence_suspend(struct EG25Manager *manager) { - append_at_command(manager, "QGPSEND", NULL, NULL, NULL); + if (manager->manage_gnss) + append_at_command(manager, "QGPSEND", NULL, NULL, NULL); append_at_command(manager, "QCFG", "urc/cache", "1", NULL); send_at_command(manager); } @@ -284,7 +287,8 @@ void at_sequence_suspend(struct EG25Manager *manager) void at_sequence_resume(struct EG25Manager *manager) { append_at_command(manager, "QCFG", "urc/cache", "0", NULL); - append_at_command(manager, "QGPS", NULL, "1", NULL); + if (manager->manage_gnss) + append_at_command(manager, "QGPS", NULL, "1", NULL); send_at_command(manager); } diff --git a/src/manager.c b/src/manager.c index bc08ddb..6445e0f 100644 --- a/src/manager.c +++ b/src/manager.c @@ -121,7 +121,7 @@ static gboolean modem_reset_done(struct EG25Manager* manager) void modem_reset(struct EG25Manager *manager) { - int fd, ret, len = strlen(manager->modem_usb_id); + int fd, ret, len; if (manager->reset_timer) return; @@ -131,6 +131,13 @@ void modem_reset(struct EG25Manager *manager) manager->suspend_timer = 0; } + if (!manager->modem_usb_id) { + g_warning("Unknown modem USB ID"); + goto error; + } + + len = strlen(manager->modem_usb_id); + manager->modem_state = EG25_STATE_RESETTING; fd = open("/sys/bus/usb/drivers/usb/unbind", O_WRONLY); @@ -162,10 +169,16 @@ error: at_sequence_reset(manager); } -void modem_suspend(struct EG25Manager *manager) +void modem_suspend_pre(struct EG25Manager *manager) +{ + at_sequence_suspend(manager); +} + +void modem_suspend_post(struct EG25Manager *manager) { gpio_sequence_suspend(manager); - at_sequence_suspend(manager); + g_message("suspend sequence is over, drop inhibitor"); + suspend_inhibit(manager, FALSE); } void modem_resume_pre(struct EG25Manager *manager) @@ -180,14 +193,27 @@ void modem_resume_post(struct EG25Manager *manager) int main(int argc, char *argv[]) { + g_autoptr(GOptionContext) opt_context = NULL; + g_autoptr(GError) err = NULL; struct EG25Manager manager; char compatible[32]; int fd, ret; + const GOptionEntry options[] = { + { "gnss", 'g', 0, G_OPTION_ARG_NONE, &manager.manage_gnss, "Manage the GNSS feature.", NULL }, + { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } + }; memset(&manager, 0, sizeof(manager)); manager.at_fd = -1; manager.suspend_inhibit_fd = -1; + opt_context = g_option_context_new ("- Power management for the Quectel EG25 modem"); + g_option_context_add_main_entries (opt_context, options, NULL); + if (!g_option_context_parse (opt_context, &argc, &argv, &err)) { + g_warning ("%s", err->message); + return 1; + } + manager.loop = g_main_loop_new(NULL, FALSE); fd = open("/proc/device-tree/compatible", O_RDONLY); diff --git a/src/manager.h b/src/manager.h index c51f32f..f6351be 100644 --- a/src/manager.h +++ b/src/manager.h @@ -28,6 +28,7 @@ enum EG25State { struct EG25Manager { GMainLoop *loop; guint reset_timer; + gboolean manage_gnss; int at_fd; guint at_source; @@ -54,7 +55,8 @@ struct EG25Manager { void modem_configure(struct EG25Manager *data); void modem_reset(struct EG25Manager *data); -void modem_suspend(struct EG25Manager *data); +void modem_suspend_pre(struct EG25Manager *data); +void modem_suspend_post(struct EG25Manager *data); void modem_resume_pre(struct EG25Manager *data); void modem_resume_post(struct EG25Manager *data); void modem_update_state(struct EG25Manager *data, MMModemState state); diff --git a/src/suspend.c b/src/suspend.c index 2e1301e..6d34594 100644 --- a/src/suspend.c +++ b/src/suspend.c @@ -94,7 +94,7 @@ static void signal_cb(GDBusProxy *proxy, if (is_about_to_suspend) { g_message("system is about to suspend"); manager->modem_state = EG25_STATE_SUSPENDING; - modem_suspend(manager); + modem_suspend_pre(manager); } else { g_message("system is resuming"); take_inhibitor(manager); diff --git a/src/udev.c b/src/udev.c index acf10f8..1c5ebd8 100644 --- a/src/udev.c +++ b/src/udev.c @@ -12,7 +12,7 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *devic { struct EG25Manager *manager = data; - if (strcmp(action, "unbind") != 0 || manager->modem_state == EG25_STATE_RESETTING) + if (strcmp(action, "unbind") != 0 || manager->modem_state == EG25_STATE_RESETTING || !manager->modem_usb_id) return; if (strncmp(g_udev_device_get_name(device), manager->modem_usb_id, strlen(manager->modem_usb_id)) == 0 &&