diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c index 12e96dc00664cb11b85ad0e6575189d6c799d786..fa9303ca8bfc2328329c10b9ade9dda55d6a08c9 100644 --- a/src/mm-base-modem.c +++ b/src/mm-base-modem.c @@ -89,6 +89,10 @@ struct _MMBaseModemPrivate { MMPortSerialAt *gps_control; MMPortSerialGps *gps; + /* Support for parallel enable/disable operations */ + GList *enable_tasks; + GList *disable_tasks; + #if defined WITH_QMI /* QMI ports */ GList *qmi; @@ -310,49 +314,123 @@ mm_base_modem_grab_port (MMBaseModem *self, } gboolean -mm_base_modem_disable_finish (MMBaseModem *self, - GAsyncResult *res, - GError **error) +mm_base_modem_disable_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error) { - return MM_BASE_MODEM_GET_CLASS (self)->disable_finish (self, res, error); + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +disable_ready (MMBaseModem *self, + GAsyncResult *res) +{ + GError *error = NULL; + GList *l; + GList *disable_tasks; + + g_assert (self->priv->disable_tasks); + disable_tasks = self->priv->disable_tasks; + self->priv->disable_tasks = NULL; + + MM_BASE_MODEM_GET_CLASS (self)->disable_finish (self, res, &error); + for (l = disable_tasks; l; l = g_list_next (l)) { + if (error) + g_task_return_error (G_TASK (l->data), g_error_copy (error)); + else + g_task_return_boolean (G_TASK (l->data), TRUE); + } + g_clear_error (&error); + + g_list_free_full (disable_tasks, (GDestroyNotify)g_object_unref); } void -mm_base_modem_disable (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data) +mm_base_modem_disable (MMBaseModem *self, + GAsyncReadyCallback callback, + gpointer user_data) { + GTask *task; + gboolean run_disable; + g_assert (MM_BASE_MODEM_GET_CLASS (self)->disable != NULL); g_assert (MM_BASE_MODEM_GET_CLASS (self)->disable_finish != NULL); + /* If the list of disable tasks is empty, we need to run */ + run_disable = !self->priv->disable_tasks; + + /* Store task */ + task = g_task_new (self, self->priv->cancellable, callback, user_data); + self->priv->disable_tasks = g_list_append (self->priv->disable_tasks, task); + + if (!run_disable) + return; + MM_BASE_MODEM_GET_CLASS (self)->disable ( self, self->priv->cancellable, - callback, - user_data); + (GAsyncReadyCallback) disable_ready, + NULL); } gboolean -mm_base_modem_enable_finish (MMBaseModem *self, - GAsyncResult *res, - GError **error) +mm_base_modem_enable_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error) { - return MM_BASE_MODEM_GET_CLASS (self)->enable_finish (self, res, error); + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +enable_ready (MMBaseModem *self, + GAsyncResult *res) +{ + GError *error = NULL; + GList *l; + GList *enable_tasks; + + g_assert (self->priv->enable_tasks); + enable_tasks = self->priv->enable_tasks; + self->priv->enable_tasks = NULL; + + MM_BASE_MODEM_GET_CLASS (self)->enable_finish (self, res, &error); + for (l = enable_tasks; l; l = g_list_next (l)) { + if (error) + g_task_return_error (G_TASK (l->data), g_error_copy (error)); + else + g_task_return_boolean (G_TASK (l->data), TRUE); + } + g_clear_error (&error); + + g_list_free_full (enable_tasks, (GDestroyNotify)g_object_unref); } void -mm_base_modem_enable (MMBaseModem *self, - GAsyncReadyCallback callback, - gpointer user_data) +mm_base_modem_enable (MMBaseModem *self, + GAsyncReadyCallback callback, + gpointer user_data) { + GTask *task; + gboolean run_enable; + g_assert (MM_BASE_MODEM_GET_CLASS (self)->enable != NULL); g_assert (MM_BASE_MODEM_GET_CLASS (self)->enable_finish != NULL); + /* If the list of enable tasks is empty, we need to run */ + run_enable = !self->priv->enable_tasks; + + /* Store task */ + task = g_task_new (self, self->priv->cancellable, callback, user_data); + self->priv->enable_tasks = g_list_append (self->priv->enable_tasks, task); + + if (!run_enable) + return; + MM_BASE_MODEM_GET_CLASS (self)->enable ( self, self->priv->cancellable, - callback, - user_data); + (GAsyncReadyCallback) enable_ready, + NULL); } gboolean @@ -1417,6 +1495,9 @@ finalize (GObject *object) * mm_auth_provider_cancel_for_owner (self->priv->authp, object); */ + g_assert (!self->priv->enable_tasks); + g_assert (!self->priv->disable_tasks); + mm_dbg ("Modem (%s) '%s' completely disposed", self->priv->plugin, self->priv->device); diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 8afec66f93fa230fa4d8a7ddd738f4f6280750f4..8c083566191ba6d7aa45f3924734f2028997e2de 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -10006,11 +10006,7 @@ enable (MMBaseModem *self, break; case MM_MODEM_STATE_ENABLING: - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_IN_PROGRESS, - "Cannot enable modem: " - "already being enabled"); + g_assert_not_reached (); break; case MM_MODEM_STATE_ENABLED: