aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c14
-rw-r--r--src/mm-base-manager.c48
-rw-r--r--src/mm-base-manager.h4
-rw-r--r--src/mm-base-modem.c25
-rw-r--r--src/mm-base-modem.h17
-rw-r--r--src/mm-broadband-modem.c81
-rw-r--r--src/mm-context.c11
-rw-r--r--src/mm-context.h1
8 files changed, 200 insertions, 1 deletions
diff --git a/src/main.c b/src/main.c
index 0067583e..89345435 100644
--- a/src/main.c
+++ b/src/main.c
@@ -72,6 +72,13 @@ resuming_cb (MMSleepMonitor *sleep_monitor)
mm_base_manager_start (manager, FALSE);
}
+static void
+resuming_quick_cb (MMSleepMonitor *sleep_monitor)
+{
+ mm_dbg ("syncing modem state (quick resuming)");
+ mm_base_manager_sync (manager);
+}
+
#endif
static void
@@ -191,7 +198,12 @@ main (int argc, char *argv[])
if (mm_context_get_test_no_suspend_resume())
mm_dbg ("Suspend/resume support disabled at runtime");
- else {
+ else if (mm_context_get_test_quick_suspend_resume()) {
+ mm_dbg ("Quick suspend/resume hooks enabled");
+ sleep_monitor = mm_sleep_monitor_get ();
+ g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_RESUMING, G_CALLBACK (resuming_quick_cb), NULL);
+ } else {
+ mm_dbg ("Full suspend/resume hooks enabled");
sleep_monitor = mm_sleep_monitor_get ();
g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_SLEEPING, G_CALLBACK (sleeping_cb), NULL);
g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_RESUMING, G_CALLBACK (resuming_cb), NULL);
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
index 24812932..e7df890a 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -52,6 +52,7 @@
#include "mm-plugin.h"
#include "mm-filter.h"
#include "mm-log-object.h"
+#include "mm-base-modem.h"
static void initable_iface_init (GInitableIface *iface);
static void log_object_iface_init (MMLogObjectInterface *iface);
@@ -724,6 +725,53 @@ mm_base_manager_num_modems (MMBaseManager *self)
}
/*****************************************************************************/
+/* Quick resume synchronization */
+
+#if defined WITH_SYSTEMD_SUSPEND_RESUME
+
+gboolean mm_base_modem_sync_finish (MMBaseModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+mm_base_modem_sync_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error;
+
+ mm_base_modem_sync_finish (self, res, &error);
+ if (error) {
+ mm_obj_warn (self, "synchronization failed");
+ return;
+ }
+ mm_obj_info (self, "synchronization finished");
+}
+
+void
+mm_base_manager_sync (MMBaseManager *self)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (MM_IS_BASE_MANAGER (self));
+
+ /* Refresh each device */
+ g_hash_table_iter_init (&iter, self->priv->devices);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ MMBaseModem *modem = mm_device_peek_modem (MM_DEVICE (value));
+ /* We just want to start the synchronization, we don't need the result */
+ mm_base_modem_sync (modem, (GAsyncReadyCallback)mm_base_modem_sync_ready, NULL);
+ }
+}
+
+#endif
+
+/*****************************************************************************/
/* Set logging */
typedef struct {
diff --git a/src/mm-base-manager.h b/src/mm-base-manager.h
index d70fa08f..be51d0c0 100644
--- a/src/mm-base-manager.h
+++ b/src/mm-base-manager.h
@@ -66,6 +66,10 @@ void mm_base_manager_start (MMBaseManager *manager,
void mm_base_manager_shutdown (MMBaseManager *manager,
gboolean disable);
+#if defined WITH_SYSTEMD_SUSPEND_RESUME
+void mm_base_manager_sync (MMBaseManager *manager);
+#endif
+
guint32 mm_base_manager_num_modems (MMBaseManager *manager);
#endif /* MM_BASE_MANAGER_H */
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c
index 06562af4..55752999 100644
--- a/src/mm-base-modem.c
+++ b/src/mm-base-modem.c
@@ -620,6 +620,31 @@ mm_base_modem_wait_link_port (MMBaseModem *self,
/******************************************************************************/
+static void
+mm_base_modem_sync_ready (MMBaseModem *self,
+ GAsyncResult *res)
+{
+ g_autoptr (GError) error = NULL;
+
+ MM_BASE_MODEM_GET_CLASS (self)->sync_finish (self, res, &error);
+ if (error) {
+ mm_obj_warn (self, "synchronization failed");
+ }
+}
+
+void
+mm_base_modem_sync (MMBaseModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_assert (MM_BASE_MODEM_GET_CLASS (self)->sync != NULL);
+ g_assert (MM_BASE_MODEM_GET_CLASS (self)->sync_finish != NULL);
+
+ MM_BASE_MODEM_GET_CLASS (self)->sync (self,
+ (GAsyncReadyCallback) mm_base_modem_sync_ready,
+ NULL);
+}
+
gboolean
mm_base_modem_disable_finish (MMBaseModem *self,
GAsyncResult *res,
diff --git a/src/mm-base-modem.h b/src/mm-base-modem.h
index 776e3c9c..6194eb93 100644
--- a/src/mm-base-modem.h
+++ b/src/mm-base-modem.h
@@ -108,6 +108,16 @@ struct _MMBaseModemClass {
GAsyncResult *res,
GError **error);
+ /* Modem synchronization.
+ * When resuming in quick suspend/resume mode,
+ * this method triggers a synchronization of all modem interfaces */
+ void (* sync) (MMBaseModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (* sync_finish) (MMBaseModem *self,
+ GAsyncResult *res,
+ GError **error);
+
/* signals */
void (* link_port_grabbed) (MMBaseModem *self,
MMPort *link_port);
@@ -231,6 +241,13 @@ gboolean mm_base_modem_disable_finish (MMBaseModem *self,
GAsyncResult *res,
GError **error);
+void mm_base_modem_sync (MMBaseModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mm_base_modem_sync_finish (MMBaseModem *self,
+ GAsyncResult *res,
+ GError **error);
+
void mm_base_modem_process_sim_event (MMBaseModem *self);
#endif /* MM_BASE_MODEM_H */
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index ee2adfc8..fa1f6125 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -11937,6 +11937,82 @@ enable (MMBaseModem *self,
g_object_unref (task);
}
+/*****************************************************************************/
+
+#if defined WITH_SYSTEMD_SUSPEND_RESUME
+
+typedef enum {
+ SYNCING_STEP_FIRST,
+ SYNCING_STEP_LAST,
+} SyncingStep;
+
+typedef struct {
+ SyncingStep step;
+} SyncingContext;
+
+static gboolean
+synchronize_finish (MMBaseModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+syncing_step (GTask *task)
+{
+ MMBroadbandModem *self;
+ SyncingContext *ctx;
+
+ /* Don't run new steps if we're cancelled */
+ if (g_task_return_error_if_cancelled (task)) {
+ g_object_unref (task);
+ return;
+ }
+
+ self = g_task_get_source_object (task);
+ ctx = g_task_get_task_data (task);
+
+ switch (ctx->step) {
+ case SYNCING_STEP_FIRST:
+ ctx->step++;
+ /* fall through */
+
+ case SYNCING_STEP_LAST:
+ mm_obj_info (self, "resume synchronization state (%d/%d): all done",
+ ctx->step, SYNCING_STEP_LAST);
+ /* We are done without errors! */
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ return;
+
+ default:
+ break;
+ }
+
+ g_assert_not_reached ();
+}
+
+/* 'sync' as function name conflicts with a declared function in unistd.h */
+static void
+synchronize (MMBaseModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SyncingContext *ctx;
+ GTask *task;
+
+ /* Create SyncingContext */
+ ctx = g_new0 (SyncingContext, 1);
+ ctx->step = SYNCING_STEP_FIRST;
+
+ /* Create sync steps task and execute it */
+ task = g_task_new (MM_BROADBAND_MODEM (self), NULL, callback, user_data);
+ g_task_set_task_data (task, ctx, (GDestroyNotify)g_free);
+ syncing_step (task);
+}
+
+#endif
/*****************************************************************************/
@@ -13343,6 +13419,11 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass)
base_modem_class->disable = disable;
base_modem_class->disable_finish = disable_finish;
+#if defined WITH_SYSTEMD_SUSPEND_RESUME
+ base_modem_class->sync = synchronize;
+ base_modem_class->sync_finish = synchronize_finish;
+#endif
+
klass->setup_ports = setup_ports;
klass->initialization_started = initialization_started;
klass->initialization_started_finish = initialization_started_finish;
diff --git a/src/mm-context.c b/src/mm-context.c
index 32590c55..ddc37a33 100644
--- a/src/mm-context.c
+++ b/src/mm-context.c
@@ -227,6 +227,7 @@ static gboolean test_no_udev;
#endif
#if defined WITH_SYSTEMD_SUSPEND_RESUME
static gboolean test_no_suspend_resume;
+static gboolean test_quick_suspend_resume;
#endif
#if defined WITH_QRTR
static gboolean test_no_qrtr;
@@ -261,6 +262,11 @@ static const GOptionEntry test_entries[] = {
"Disable suspend/resume support at runtime even if available",
NULL
},
+ {
+ "test-quick-suspend-resume", 0, 0, G_OPTION_ARG_NONE, &test_quick_suspend_resume,
+ "Enable quick suspend/resume support for modems which stay on during host suspension",
+ NULL
+ },
#endif
#if defined WITH_QRTR
{
@@ -318,6 +324,11 @@ mm_context_get_test_no_suspend_resume (void)
{
return test_no_suspend_resume;
}
+gboolean
+mm_context_get_test_quick_suspend_resume (void)
+{
+ return test_quick_suspend_resume;
+}
#endif
#if defined WITH_QRTR
diff --git a/src/mm-context.h b/src/mm-context.h
index ea9df0cb..0e652ba3 100644
--- a/src/mm-context.h
+++ b/src/mm-context.h
@@ -51,6 +51,7 @@ gboolean mm_context_get_test_no_udev (void);
#endif
#if defined WITH_SYSTEMD_SUSPEND_RESUME
gboolean mm_context_get_test_no_suspend_resume (void);
+gboolean mm_context_get_test_quick_suspend_resume (void);
#endif
#if defined WITH_QRTR
gboolean mm_context_get_test_no_qrtr (void);