diff options
-rw-r--r-- | src/mm-base-modem.c | 10 | ||||
-rw-r--r-- | src/mm-bearer-qmi.c | 4 | ||||
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 2 | ||||
-rw-r--r-- | src/mm-port-probe.c | 26 | ||||
-rw-r--r-- | src/mm-port-qmi.c | 104 | ||||
-rw-r--r-- | src/mm-port-qmi.h | 25 |
6 files changed, 132 insertions, 39 deletions
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c index 81d33038..60ad8b2e 100644 --- a/src/mm-base-modem.c +++ b/src/mm-base-modem.c @@ -1584,6 +1584,14 @@ finalize (GObject *object) G_OBJECT_CLASS (mm_base_modem_parent_class)->finalize (object); } +#if defined WITH_QMI +static void +foreach_port_qmi_close (MMPortQmi *port_qmi) +{ + mm_port_qmi_close (port_qmi, NULL, NULL); +} +#endif + #if defined WITH_MBIM static void foreach_port_mbim_close (MMPortMbim *port_mbim) @@ -1623,7 +1631,7 @@ dispose (GObject *object) * otherwise the allocated CIDs will be kept allocated, and if we end up * allocating too many newer allocations will fail with client-ids-exhausted * errors. */ - g_list_foreach (self->priv->qmi, (GFunc)mm_port_qmi_close, NULL); + g_list_foreach (self->priv->qmi, (GFunc)foreach_port_qmi_close, NULL); g_list_free_full (self->priv->qmi, g_object_unref); self->priv->qmi = NULL; #endif diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c index 2b25b136..ac869534 100644 --- a/src/mm-bearer-qmi.c +++ b/src/mm-bearer-qmi.c @@ -481,7 +481,7 @@ connect_context_free (ConnectContext *ctx) } if (ctx->explicit_qmi_open) - mm_port_qmi_close (ctx->qmi); + mm_port_qmi_close (ctx->qmi, NULL, NULL); g_clear_error (&ctx->error_ipv4); g_clear_error (&ctx->error_ipv6); @@ -1883,7 +1883,7 @@ reset_bearer_connection (MMBearerQmi *self, if (self->priv->qmi) { if (self->priv->explicit_qmi_open) { self->priv->explicit_qmi_open = FALSE; - mm_port_qmi_close (self->priv->qmi); + mm_port_qmi_close (self->priv->qmi, NULL, NULL); } g_clear_object (&self->priv->qmi); } diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index acea951f..4919a246 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -8651,7 +8651,7 @@ dispose (GObject *object) untrack_qmi_device_removed (self, qmi); /* If we did open the QMI port during initialization, close it now */ if (mm_port_qmi_is_open (qmi)) - mm_port_qmi_close (qmi); + mm_port_qmi_close (qmi, NULL, NULL); } g_list_free_full (self->priv->firmware_list, g_object_unref); diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c index c0b5b455..1700111f 100644 --- a/src/mm-port-probe.c +++ b/src/mm-port-probe.c @@ -435,8 +435,8 @@ port_probe_run_context_free (PortProbeRunContext *ctx) #if defined WITH_QMI if (ctx->port_qmi) { - if (mm_port_qmi_is_open (ctx->port_qmi)) - mm_port_qmi_close (ctx->port_qmi); + /* We should have closed it cleanly before */ + g_assert (!mm_port_qmi_is_open (ctx->port_qmi)); g_object_unref (ctx->port_qmi); } #endif @@ -465,6 +465,22 @@ static gboolean wdm_probe (MMPortProbe *self); #if defined WITH_QMI static void +qmi_port_close_ready (MMPortQmi *qmi_port, + GAsyncResult *res, + MMPortProbe *self) +{ + PortProbeRunContext *ctx; + + g_assert (self->priv->task); + ctx = g_task_get_task_data (self->priv->task); + + mm_port_qmi_close_finish (qmi_port, res, NULL); + + /* Keep on */ + ctx->source_id = g_idle_add ((GSourceFunc) wdm_probe, self); +} + +static void port_qmi_open_ready (MMPortQmi *port_qmi, GAsyncResult *res, MMPortProbe *self) @@ -487,10 +503,10 @@ port_qmi_open_ready (MMPortQmi *port_qmi, /* Set probing result */ mm_port_probe_set_result_qmi (self, is_qmi); - mm_port_qmi_close (port_qmi); - /* Keep on */ - ctx->source_id = g_idle_add ((GSourceFunc) wdm_probe, self); + mm_port_qmi_close (ctx->port_qmi, + (GAsyncReadyCallback) qmi_port_close_ready, + self); } #endif /* WITH_QMI */ diff --git a/src/mm-port-qmi.c b/src/mm-port-qmi.c index 25a1916e..844075ea 100644 --- a/src/mm-port-qmi.c +++ b/src/mm-port-qmi.c @@ -33,7 +33,7 @@ typedef struct { } ServiceInfo; struct _MMPortQmiPrivate { - gboolean opening; + gboolean in_progress; QmiDevice *qmi_device; GList *services; gboolean llp_is_raw_ip; @@ -244,7 +244,7 @@ port_open_complete_with_error (GTask *task) ctx = g_task_get_task_data (task); g_assert (ctx->error); - self->priv->opening = FALSE; + self->priv->in_progress = FALSE; g_task_return_error (task, g_steal_pointer (&ctx->error)); g_object_unref (task); } @@ -401,11 +401,11 @@ port_open_step (GTask *task) case PORT_OPEN_STEP_CHECK_OPENING: mm_dbg ("Checking if QMI device already opening..."); - if (self->priv->opening) { + if (self->priv->in_progress) { g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_IN_PROGRESS, - "QMI device already being opened"); + "QMI device open/close operation in progress"); g_object_unref (task); return; } @@ -432,7 +432,7 @@ port_open_step (GTask *task) /* We flag in this point that we're opening. From now on, if we stop * for whatever reason, we should clear this flag. We do this by ensuring * that all callbacks go through the LAST step for completing. */ - self->priv->opening = TRUE; + self->priv->in_progress = TRUE; mm_dbg ("Creating QMI device..."); qmi_device_new (file, @@ -585,8 +585,8 @@ port_open_step (GTask *task) /* Store device in private info */ g_assert (ctx->device); g_assert (!self->priv->qmi_device); - self->priv->qmi_device = g_steal_pointer (&ctx->device); - self->priv->opening = FALSE; + self->priv->qmi_device = g_object_ref (ctx->device); + self->priv->in_progress = FALSE; g_task_return_boolean (task, TRUE); g_object_unref (task); return; @@ -617,6 +617,8 @@ mm_port_qmi_open (MMPortQmi *self, port_open_step (task); } +/*****************************************************************************/ + gboolean mm_port_qmi_is_open (MMPortQmi *self) { @@ -625,23 +627,88 @@ mm_port_qmi_is_open (MMPortQmi *self) return !!self->priv->qmi_device; } +/*****************************************************************************/ + +typedef struct { + QmiDevice *qmi_device; +} PortQmiCloseContext; + +static void +port_qmi_close_context_free (PortQmiCloseContext *ctx) +{ + g_clear_object (&ctx->qmi_device); + g_slice_free (PortQmiCloseContext, ctx); +} + +gboolean +mm_port_qmi_close_finish (MMPortQmi *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +qmi_device_close_ready (QmiDevice *qmi_device, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + MMPortQmi *self; + + self = g_task_get_source_object (task); + + g_assert (!self->priv->qmi_device); + self->priv->in_progress = FALSE; + + if (!qmi_device_close_finish (qmi_device, res, &error)) + g_task_return_error (task, error); + else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + void -mm_port_qmi_close (MMPortQmi *self) +mm_port_qmi_close (MMPortQmi *self, + GAsyncReadyCallback callback, + gpointer user_data) { - GList *l; - GError *error = NULL; + PortQmiCloseContext *ctx; + GTask *task; + GList *l; g_return_if_fail (MM_IS_PORT_QMI (self)); - if (!self->priv->qmi_device) + task = g_task_new (self, NULL, callback, user_data); + + if (self->priv->in_progress) { + g_task_return_new_error (task, + MM_CORE_ERROR, + MM_CORE_ERROR_IN_PROGRESS, + "QMI device open/close operation in progress"); + g_object_unref (task); + return; + } + + if (!self->priv->qmi_device) { + g_task_return_boolean (task, TRUE); + g_object_unref (task); return; + } + + self->priv->in_progress = TRUE; + + /* Store device to close in the context */ + ctx = g_slice_new0 (PortQmiCloseContext); + ctx->qmi_device = g_steal_pointer (&self->priv->qmi_device); + g_task_set_task_data (task, ctx, (GDestroyNotify)port_qmi_close_context_free); /* Release all allocated clients */ for (l = self->priv->services; l; l = g_list_next (l)) { ServiceInfo *info = l->data; mm_dbg ("Releasing client for service '%s'...", qmi_service_get_string (info->service)); - qmi_device_release_client (self->priv->qmi_device, + qmi_device_release_client (ctx->qmi_device, info->client, QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID, 3, NULL, NULL, NULL); @@ -650,14 +717,11 @@ mm_port_qmi_close (MMPortQmi *self) g_list_free_full (self->priv->services, g_free); self->priv->services = NULL; - /* Close and release the device */ - if (!qmi_device_close (self->priv->qmi_device, &error)) { - mm_warn ("Couldn't properly close QMI device: %s", - error->message); - g_error_free (error); - } - - g_clear_object (&self->priv->qmi_device); + qmi_device_close_async (ctx->qmi_device, + 5, + NULL, + (GAsyncReadyCallback)qmi_device_close_ready, + task); } /*****************************************************************************/ diff --git a/src/mm-port-qmi.h b/src/mm-port-qmi.h index 26818c84..f8ea9eec 100644 --- a/src/mm-port-qmi.h +++ b/src/mm-port-qmi.h @@ -48,16 +48,21 @@ GType mm_port_qmi_get_type (void); MMPortQmi *mm_port_qmi_new (const gchar *name); -void mm_port_qmi_open (MMPortQmi *self, - gboolean set_data_format, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_port_qmi_open_finish (MMPortQmi *self, - GAsyncResult *res, - GError **error); -gboolean mm_port_qmi_is_open (MMPortQmi *self); -void mm_port_qmi_close (MMPortQmi *self); +void mm_port_qmi_open (MMPortQmi *self, + gboolean set_data_format, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_port_qmi_open_finish (MMPortQmi *self, + GAsyncResult *res, + GError **error); +gboolean mm_port_qmi_is_open (MMPortQmi *self); +void mm_port_qmi_close (MMPortQmi *self, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_port_qmi_close_finish (MMPortQmi *self, + GAsyncResult *res, + GError **error); typedef enum { MM_PORT_QMI_FLAG_DEFAULT = 0, |