diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-base-manager.c | 13 | ||||
-rw-r--r-- | src/mm-base-modem.c | 249 | ||||
-rw-r--r-- | src/mm-base-modem.h | 123 | ||||
-rw-r--r-- | src/mm-broadband-modem.c | 3 | ||||
-rw-r--r-- | src/mm-device.c | 2 | ||||
-rw-r--r-- | src/mm-iface-modem-simple.c | 1 | ||||
-rw-r--r-- | src/mm-iface-modem.c | 5 |
7 files changed, 274 insertions, 122 deletions
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c index c053a53e..449b74df 100644 --- a/src/mm-base-manager.c +++ b/src/mm-base-manager.c @@ -961,7 +961,10 @@ foreach_disable (gpointer key, ctx->low_power = foreach_ctx->low_power; ctx->remove = foreach_ctx->remove; - mm_base_modem_disable (modem, (GAsyncReadyCallback)shutdown_disable_ready, ctx); + mm_base_modem_disable (modem, + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, + (GAsyncReadyCallback)shutdown_disable_ready, + ctx); } static gboolean @@ -1067,8 +1070,12 @@ mm_base_manager_sync (MMBaseManager *self) modem = mm_device_peek_modem (MM_DEVICE (value)); /* We just want to start the synchronization, we don't need the result */ - if (modem) - mm_base_modem_sync (modem, (GAsyncReadyCallback)base_modem_sync_ready, NULL); + if (modem) { + mm_base_modem_sync (modem, + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, + (GAsyncReadyCallback)base_modem_sync_ready, + NULL); + } } } diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c index 0e0fe00c..bef3ddf0 100644 --- a/src/mm-base-modem.c +++ b/src/mm-base-modem.c @@ -712,51 +712,189 @@ mm_base_modem_wait_link_port (MMBaseModem *self, } /******************************************************************************/ +/* Common support to perform state update/sync operations with the base modem. */ +typedef enum { + STATE_OPERATION_TYPE_INITIALIZE, + STATE_OPERATION_TYPE_ENABLE, + STATE_OPERATION_TYPE_DISABLE, #if defined WITH_SUSPEND_RESUME + STATE_OPERATION_TYPE_SYNC, +#endif +} StateOperationType; -gboolean -mm_base_modem_sync_finish (MMBaseModem *self, - GAsyncResult *res, - GError **error) +typedef struct { + StateOperation operation; + StateOperationFinish operation_finish; + gssize operation_id; +} StateOperationContext; + +static void +state_operation_context_free (StateOperationContext *ctx) +{ + g_assert (ctx->operation_id < 0); + g_slice_free (StateOperationContext, ctx); +} + +static gboolean +state_operation_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void -sync_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) +state_operation_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) { GError *error = NULL; - if (!MM_BASE_MODEM_GET_CLASS (self)->sync_finish (self, res, &error)) + StateOperationContext *ctx; + + ctx = g_task_get_task_data (task); + + if (ctx->operation_id >= 0) { + mm_base_modem_operation_unlock (self, ctx->operation_id); + ctx->operation_id = (gssize) -1; + } + + if (!ctx->operation_finish (self, res, &error)) g_task_return_error (task, error); else g_task_return_boolean (task, TRUE); g_object_unref (task); } -void -mm_base_modem_sync (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data) +static void +state_operation_run (GTask *task) { - GTask *task; + MMBaseModem *self; + StateOperationContext *ctx; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + ctx->operation (self, + self->priv->cancellable, + (GAsyncReadyCallback) state_operation_ready, + task); +} + +static void +lock_before_state_operation_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + StateOperationContext *ctx; + + ctx = g_task_get_task_data (task); + + ctx->operation_id = mm_base_modem_operation_lock_finish (self, res, &error); + if (ctx->operation_id < 0) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + state_operation_run (task); +} + +static void +state_operation (MMBaseModem *self, + StateOperationType operation_type, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + StateOperationContext *ctx; + gboolean optional; + const gchar *operation_description; + + ctx = g_slice_new0 (StateOperationContext); + ctx->operation_id = (gssize) -1; + + /* configure operation to run */ + switch (operation_type) { + case STATE_OPERATION_TYPE_INITIALIZE: + operation_description = "initialization"; + optional = FALSE; + ctx->operation = MM_BASE_MODEM_GET_CLASS (self)->initialize; + ctx->operation_finish = MM_BASE_MODEM_GET_CLASS (self)->initialize_finish; + break; + case STATE_OPERATION_TYPE_ENABLE: + operation_description = "enabling"; + optional = FALSE; + ctx->operation = MM_BASE_MODEM_GET_CLASS (self)->enable; + ctx->operation_finish = MM_BASE_MODEM_GET_CLASS (self)->enable_finish; + break; + case STATE_OPERATION_TYPE_DISABLE: + operation_description = "disabling"; + optional = FALSE; + ctx->operation = MM_BASE_MODEM_GET_CLASS (self)->disable; + ctx->operation_finish = MM_BASE_MODEM_GET_CLASS (self)->disable_finish; + break; +#if defined WITH_SUSPEND_RESUME + case STATE_OPERATION_TYPE_SYNC: + operation_description = "sync"; + optional = TRUE; + ctx->operation = MM_BASE_MODEM_GET_CLASS (self)->sync; + ctx->operation_finish = MM_BASE_MODEM_GET_CLASS (self)->sync_finish; + break; +#endif + default: + g_assert_not_reached (); + } task = g_task_new (self, NULL, callback, user_data); + g_task_set_task_data (task, ctx, (GDestroyNotify) state_operation_context_free); - if (!MM_BASE_MODEM_GET_CLASS (self)->sync || - !MM_BASE_MODEM_GET_CLASS (self)->sync_finish) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, - "Suspend/resume quick synchronization unsupported"); + if (optional && (!ctx->operation || !ctx->operation_finish)) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Unsupported"); g_object_unref (task); return; } + g_assert (ctx->operation && ctx->operation_finish); - MM_BASE_MODEM_GET_CLASS (self)->sync (self, - (GAsyncReadyCallback) sync_ready, - task); + if (operation_lock == MM_BASE_MODEM_OPERATION_LOCK_ALREADY_ACQUIRED) { + state_operation_run (task); + return; + } + + g_assert (operation_lock == MM_BASE_MODEM_OPERATION_LOCK_REQUIRED); + mm_base_modem_operation_lock (self, + MM_BASE_MODEM_OPERATION_PRIORITY_DEFAULT, + operation_description, + (GAsyncReadyCallback) lock_before_state_operation_ready, + task); +} + +/******************************************************************************/ + +#if defined WITH_SUSPEND_RESUME + +gboolean +mm_base_modem_sync_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error) +{ + return state_operation_finish (self, res, error); +} + +void +mm_base_modem_sync (MMBaseModem *self, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data) +{ + state_operation (self, + STATE_OPERATION_TYPE_SYNC, + operation_lock, + callback, + user_data); } #endif /* WITH_SUSPEND_RESUME */ @@ -768,67 +906,70 @@ mm_base_modem_disable_finish (MMBaseModem *self, GAsyncResult *res, GError **error) { - return MM_BASE_MODEM_GET_CLASS (self)->disable_finish (self, res, error); + return state_operation_finish (self, res, error); } void -mm_base_modem_disable (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data) +mm_base_modem_disable (MMBaseModem *self, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data) { - g_assert (MM_BASE_MODEM_GET_CLASS (self)->disable != NULL); - g_assert (MM_BASE_MODEM_GET_CLASS (self)->disable_finish != NULL); - MM_BASE_MODEM_GET_CLASS (self)->disable ( - self, - self->priv->cancellable, - callback, - user_data); + state_operation (self, + STATE_OPERATION_TYPE_DISABLE, + operation_lock, + callback, + user_data); } +/******************************************************************************/ + gboolean mm_base_modem_enable_finish (MMBaseModem *self, GAsyncResult *res, GError **error) { - return MM_BASE_MODEM_GET_CLASS (self)->enable_finish (self, res, error); + return state_operation_finish (self, res, error); } void -mm_base_modem_enable (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data) +mm_base_modem_enable (MMBaseModem *self, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data) { - g_assert (MM_BASE_MODEM_GET_CLASS (self)->enable != NULL); - g_assert (MM_BASE_MODEM_GET_CLASS (self)->enable_finish != NULL); - MM_BASE_MODEM_GET_CLASS (self)->enable ( - self, - self->priv->cancellable, - callback, - user_data); + state_operation (self, + STATE_OPERATION_TYPE_ENABLE, + operation_lock, + callback, + user_data); } +/******************************************************************************/ + gboolean mm_base_modem_initialize_finish (MMBaseModem *self, GAsyncResult *res, GError **error) { - return MM_BASE_MODEM_GET_CLASS (self)->initialize_finish (self, res, error); + return state_operation_finish (self, res, error); } void -mm_base_modem_initialize (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_assert (MM_BASE_MODEM_GET_CLASS (self)->initialize != NULL); - g_assert (MM_BASE_MODEM_GET_CLASS (self)->initialize_finish != NULL); - MM_BASE_MODEM_GET_CLASS (self)->initialize ( - self, - self->priv->cancellable, - callback, - user_data); +mm_base_modem_initialize (MMBaseModem *self, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data) +{ + state_operation (self, + STATE_OPERATION_TYPE_INITIALIZE, + operation_lock, + callback, + user_data); } +/******************************************************************************/ + void mm_base_modem_set_hotplugged (MMBaseModem *self, gboolean hotplugged) diff --git a/src/mm-base-modem.h b/src/mm-base-modem.h index 24dfcdc9..c7a5a4e9 100644 --- a/src/mm-base-modem.h +++ b/src/mm-base-modem.h @@ -78,49 +78,36 @@ struct _MMBaseModem { MMBaseModemPrivate *priv; }; +/* Common state operation definitions */ +typedef void (* StateOperation) (MMBaseModem *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +typedef gboolean (*StateOperationFinish) (MMBaseModem *self, + GAsyncResult *res, + GError **error); + struct _MMBaseModemClass { MmGdbusObjectSkeletonClass parent; - /* Modem initialization. - * As soon as the ports are organized, this method gets called */ - void (* initialize) (MMBaseModem *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*initialize_finish) (MMBaseModem *self, - GAsyncResult *res, - GError **error); - - /* Modem enabling. - * User action requested from DBus, usually */ - void (* enable) (MMBaseModem *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*enable_finish) (MMBaseModem *self, - GAsyncResult *res, - GError **error); - - /* Modem disabling. - * User action requested from DBus, usually */ - void (* disable) (MMBaseModem *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*disable_finish) (MMBaseModem *self, - GAsyncResult *res, - GError **error); + /* Modem initialization. As soon as the ports are organized, this method gets called */ + StateOperation initialize; + StateOperationFinish initialize_finish; + + /* Modem enabling. User action requested from DBus, usually */ + StateOperation enable; + StateOperationFinish enable_finish; + + /* Modem disabling. Either user action or internally triggered. */ + StateOperation disable; + StateOperationFinish disable_finish; #if defined WITH_SUSPEND_RESUME /* 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); + StateOperation sync; + StateOperationFinish sync_finish; #endif /* Allow plugins to subclass port object creation as needed */ @@ -271,37 +258,45 @@ gssize mm_base_modem_authorize_and_operation_lock_finish (MMBaseModem GError **error); /******************************************************************************/ - -void mm_base_modem_initialize (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_base_modem_initialize_finish (MMBaseModem *self, - GAsyncResult *res, - GError **error); - -void mm_base_modem_enable (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_base_modem_enable_finish (MMBaseModem *self, - GAsyncResult *res, - GError **error); - -void mm_base_modem_disable (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_base_modem_disable_finish (MMBaseModem *self, - GAsyncResult *res, - GError **error); +/* State operations */ + +typedef enum { + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, + MM_BASE_MODEM_OPERATION_LOCK_ALREADY_ACQUIRED, +} MMBaseModemOperationLock; + +void mm_base_modem_initialize (MMBaseModem *self, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_base_modem_initialize_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error); + +void mm_base_modem_enable (MMBaseModem *self, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_base_modem_enable_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error); + +void mm_base_modem_disable (MMBaseModem *self, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_base_modem_disable_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error); #if defined WITH_SUSPEND_RESUME - -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_sync (MMBaseModem *self, + MMBaseModemOperationLock operation_lock, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_base_modem_sync_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error); #endif #endif /* MM_BASE_MODEM_H */ diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 79f6496a..f3f79ed5 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -12706,13 +12706,14 @@ syncing_step (GTask *task) /* 'sync' as function name conflicts with a declared function in unistd.h */ static void synchronize (MMBaseModem *self, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { SyncingContext *ctx; GTask *task; - task = g_task_new (MM_BROADBAND_MODEM (self), NULL, callback, user_data); + task = g_task_new (self, cancellable, callback, user_data); /* Create SyncingContext */ ctx = g_new0 (SyncingContext, 1); diff --git a/src/mm-device.c b/src/mm-device.c index fa8aab82..40b2039c 100644 --- a/src/mm-device.c +++ b/src/mm-device.c @@ -437,6 +437,7 @@ mm_device_initialize_modem (MMDevice *self) mm_obj_dbg (self, "modem initializing..."); mm_base_modem_initialize (modem, + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, (GAsyncReadyCallback)initialize_ready, g_object_ref (self)); } @@ -749,6 +750,7 @@ mm_device_inhibit (MMDevice *self, /* Make sure modem is disabled while inhibited */ mm_base_modem_disable (self->priv->modem, + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, (GAsyncReadyCallback)inhibit_disable_ready, task); } diff --git a/src/mm-iface-modem-simple.c b/src/mm-iface-modem-simple.c index 4397bf3e..004371b2 100644 --- a/src/mm-iface-modem-simple.c +++ b/src/mm-iface-modem-simple.c @@ -756,6 +756,7 @@ connection_step (ConnectionContext *ctx) mm_obj_msg (ctx->self, "simple connect state (%d/%d): enable", ctx->step, CONNECTION_STEP_LAST); mm_base_modem_enable (MM_BASE_MODEM (ctx->self), + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, (GAsyncReadyCallback)enable_ready, ctx); return; diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c index 51c3088c..bb6c71d0 100644 --- a/src/mm-iface-modem.c +++ b/src/mm-iface-modem.c @@ -345,6 +345,7 @@ mm_iface_modem_process_sim_event (MMIfaceModem *self) mm_base_modem_set_reprobe (MM_BASE_MODEM (self), TRUE); mm_base_modem_disable (MM_BASE_MODEM (self), + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, (GAsyncReadyCallback) after_sim_event_disable_ready, NULL); } @@ -2328,11 +2329,13 @@ handle_enable_auth_ready (MMBaseModem *self, if (ctx->enable) { mm_obj_info (self, "processing user request to enable modem..."); mm_base_modem_enable (self, + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, (GAsyncReadyCallback)enable_ready, ctx); } else { mm_obj_info (self, "processing user request to disable modem..."); mm_base_modem_disable (self, + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, (GAsyncReadyCallback)enable_ready, ctx); } @@ -2408,6 +2411,7 @@ disable_after_low (MMIfaceModem *self, { mm_obj_info (self, "automatically disable modem after low-power mode..."); mm_base_modem_disable (MM_BASE_MODEM (self), + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, (GAsyncReadyCallback)disable_after_low_ready, ctx); } @@ -3703,6 +3707,7 @@ restart_initialize_idle (MMIfaceModem *self) priv = get_private (self); mm_base_modem_initialize (MM_BASE_MODEM (self), + MM_BASE_MODEM_OPERATION_LOCK_REQUIRED, (GAsyncReadyCallback) reinitialize_ready, NULL); |