aboutsummaryrefslogtreecommitdiffstats
path: root/src/libqmi-glib
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2017-02-08 23:44:58 +0100
committerAleksander Morgado <aleksander@aleksander.es>2017-02-09 10:19:53 +0100
commitd29bfb5a22339d883e5f7448371c3bbb71610945 (patch)
tree0e1e6de94b196f2f7d08a62dfae6b078f5d7f955 /src/libqmi-glib
parent2801fb42fd585bb82a54c053d5a27f62e8df9dfe (diff)
downloadexternal_libqmi-d29bfb5a22339d883e5f7448371c3bbb71610945.zip
external_libqmi-d29bfb5a22339d883e5f7448371c3bbb71610945.tar.gz
external_libqmi-d29bfb5a22339d883e5f7448371c3bbb71610945.tar.bz2
libqmi-glib,device: new qmi_device_close_async() operation
The sync close operation that was implemented was partially useless because the source responsible for I/O was scheduled in the main context, so we were really relying on that main context to be still running to properly finish the operation. i.e. a qmi_device_close() after the default main loop was stopped would always end up with a timeout error, as the response was never read. So, we now modify the sync operation so that it doesn't do any explicit wait for the response, we just issue the MBIM close command. And we provide a new async operation that may be used to wait for the MBIM close response.
Diffstat (limited to 'src/libqmi-glib')
-rw-r--r--src/libqmi-glib/qmi-device.c140
-rw-r--r--src/libqmi-glib/qmi-device.h10
2 files changed, 97 insertions, 53 deletions
diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c
index f01406a..e10da21 100644
--- a/src/libqmi-glib/qmi-device.c
+++ b/src/libqmi-glib/qmi-device.c
@@ -2622,61 +2622,95 @@ destroy_iostream (QmiDevice *self)
#if defined MBIM_QMUX_ENABLED
-typedef struct {
- GError *error;
- GMainLoop *loop;
-} SyncMbimClose;
-
static void
-mbim_device_close_ready (MbimDevice *dev,
- GAsyncResult *res,
- SyncMbimClose *ctx)
+mbim_device_close_ready (MbimDevice *dev,
+ GAsyncResult *res,
+ GTask *task)
{
- mbim_device_close_finish (dev, res, &ctx->error);
- g_main_loop_quit (ctx->loop);
+ GError *error = NULL;
+
+ if (!mbim_device_close_finish (dev, res, &error))
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
}
-static gboolean
-destroy_mbim_device (QmiDevice *self,
- GError **error)
-{
- GMainContext *main_ctx;
- SyncMbimClose ctx;
-
- main_ctx = g_main_context_new ();
- g_main_context_push_thread_default (main_ctx);
-
- ctx.loop = g_main_loop_new (main_ctx, FALSE);
- ctx.error = NULL;
-
- /* Schedule in new main context */
- mbim_device_close (self->priv->mbimdev,
- 15,
- NULL,
- (GAsyncReadyCallback) mbim_device_close_ready,
- &ctx);
-
- /* Cleanup right away, we don't want multiple close attempts on the
- * device */
- g_clear_object (&self->priv->mbimdev);
-
- /* Run */
- g_main_loop_run (ctx.loop);
- g_main_loop_unref (ctx.loop);
- g_main_context_pop_thread_default (main_ctx);
- g_main_context_unref (main_ctx);
-
- /* Report error, if any found */
- if (ctx.error) {
- g_propagate_error (error, ctx.error);
- return FALSE;
- }
+#endif
- return TRUE;
+/**
+ * qmi_device_close_finish:
+ * @self: a #QmiDevice.
+ * @res: a #GAsyncResult.
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with qmi_device_close_async().
+ *
+ * Returns: %TRUE if successful, %FALSE if @error is set.
+ *
+ * Since: 1.18
+ */
+gboolean
+qmi_device_close_finish (QmiDevice *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
}
+/**
+ * qmi_device_close_async:
+ * @self: a #QmiDevice.
+ * @timeout: maximum time, in seconds, to wait for the device to be closed.
+ * @cancellable: a #GCancellable, or %NULL.
+ * @callback: a #GAsyncReadyCallback to call when the operation is finished.
+ * @user_data: the data to pass to callback function.
+ *
+ * Asynchronously closes a #QmiDevice, preventing any further I/O.
+ *
+ * If this device was opened with @QMI_DEVICE_OPEN_FLAGS_MBIM, this
+ * operation will wait for the response of the underlying MBIM close
+ * sequence.
+ *
+ * Closing a #QmiDevice multiple times will not return an error.
+ *
+ * When the operation is finished @callback will be called. You can then call
+ * qmi_device_close_finish() to get the result of the operation.
+ *
+ * Since: 1.18
+ */
+void
+qmi_device_close_async (QmiDevice *self,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+#if defined MBIM_QMUX_ENABLED
+ if (self->priv->mbimdev) {
+ /* Schedule in new main context */
+ mbim_device_close (self->priv->mbimdev,
+ timeout,
+ NULL,
+ (GAsyncReadyCallback) mbim_device_close_ready,
+ task);
+ /* Cleanup right away, we don't want multiple close attempts on the
+ * device */
+ g_clear_object (&self->priv->mbimdev);
+ return;
+ }
#endif
+ destroy_iostream (self);
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
/**
* qmi_device_close:
* @self: a #QmiDevice
@@ -2684,22 +2718,22 @@ destroy_mbim_device (QmiDevice *self,
*
* Synchronously closes a #QmiDevice, preventing any further I/O.
*
+ * If this device was opened with @QMI_DEVICE_OPEN_FLAGS_MBIM, this
+ * operation will not wait for the response of the underlying MBIM
+ * close sequence.
+ *
* Closing a #QmiDevice multiple times will not return an error.
*
* Returns: %TRUE if successful, %FALSE if @error is set.
+ *
+ * Deprecated: 1.18: Use qmi_device_close_async() instead.
*/
gboolean
qmi_device_close (QmiDevice *self,
GError **error)
{
g_return_val_if_fail (QMI_IS_DEVICE (self), FALSE);
-
-#if defined MBIM_QMUX_ENABLED
- if (self->priv->mbimdev)
- return destroy_mbim_device (self, error);
-#endif
-
- destroy_iostream (self);
+ qmi_device_close_async (self, 0, NULL, NULL, NULL);
return TRUE;
}
diff --git a/src/libqmi-glib/qmi-device.h b/src/libqmi-glib/qmi-device.h
index 22f32c6..6ed832a 100644
--- a/src/libqmi-glib/qmi-device.h
+++ b/src/libqmi-glib/qmi-device.h
@@ -126,9 +126,19 @@ gboolean qmi_device_open_finish (QmiDevice *self,
GAsyncResult *res,
GError **error);
+G_DEPRECATED
gboolean qmi_device_close (QmiDevice *self,
GError **error);
+void qmi_device_close_async (QmiDevice *self,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean qmi_device_close_finish (QmiDevice *self,
+ GAsyncResult *res,
+ GError **error);
+
void qmi_device_allocate_client (QmiDevice *self,
QmiService service,
guint8 cid,