diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2018-06-19 11:55:10 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2018-08-10 15:11:45 +0200 |
commit | bd85cca079c8cdb5b190646cde40071a64ed6334 (patch) | |
tree | 88986d430e1a1d344a31824a6ce079e9f9e64265 | |
parent | 8198289e7019af137014d7a0210a70ef1eb4bfc8 (diff) | |
download | ModemManager-bd85cca079c8cdb5b190646cde40071a64ed6334.tar.gz |
port-mbim: automatically try to open a QMI over MBIM device
Most Qualcomm-based MBIM devices also support QMI over MBIM. We will
try to check in runtime whether the MBIM device supports QMI over
MBIM, and if so, setup a QmiDevice within the MMPortMbim.
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 3 | ||||
-rw-r--r-- | src/mm-port-mbim.c | 158 | ||||
-rw-r--r-- | src/mm-port-mbim.h | 3 | ||||
-rw-r--r-- | src/mm-port-probe.c | 3 |
4 files changed, 150 insertions, 17 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 40ede015e..d508e0311 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -1951,6 +1951,9 @@ initialization_started (MMBroadbandModem *self, /* Now open our MBIM port */ mm_port_mbim_open (ctx->mbim, +#if WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + TRUE, /* With QMI over MBIM support if available */ +#endif NULL, (GAsyncReadyCallback)mbim_port_open_ready, task); diff --git a/src/mm-port-mbim.c b/src/mm-port-mbim.c index a0534fea7..20a72dfc4 100644 --- a/src/mm-port-mbim.c +++ b/src/mm-port-mbim.c @@ -10,12 +10,18 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * - * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org> + * Copyright (C) 2013-2018 Aleksander Morgado <aleksander@gnu.org> */ +#include <config.h> + #include <stdio.h> #include <stdlib.h> +#if defined WITH_QMI +# include <libqmi-glib.h> +#endif + #include <ModemManager.h> #include <mm-errors-types.h> @@ -25,26 +31,98 @@ G_DEFINE_TYPE (MMPortMbim, mm_port_mbim, MM_TYPE_PORT) struct _MMPortMbimPrivate { - gboolean in_progress; + gboolean in_progress; MbimDevice *mbim_device; +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + QmiDevice *qmi_device; +#endif }; /*****************************************************************************/ gboolean -mm_port_mbim_open_finish (MMPortMbim *self, - GAsyncResult *res, - GError **error) +mm_port_mbim_open_finish (MMPortMbim *self, + GAsyncResult *res, + GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + static void -mbim_device_open_ready (MbimDevice *mbim_device, +qmi_device_open_ready (QmiDevice *dev, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + MMPortMbim *self; + + self = g_task_get_source_object (task); + + if (!qmi_device_open_finish (dev, res, &error)) { + mm_dbg ("[%s] error: couldn't open QmiDevice: %s", + mm_port_get_device (MM_PORT (self)), + error->message); + g_error_free (error); + g_clear_object (&self->priv->qmi_device); + /* Ignore error and complete */ + mm_info ("[%s] MBIM device is not QMI capable", + mm_port_get_device (MM_PORT (self))); + } else { + mm_info ("[%s] MBIM device is QMI capable", + mm_port_get_device (MM_PORT (self))); + } + + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +qmi_device_new_ready (GObject *unused, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + MMPortMbim *self; + + self = g_task_get_source_object (task); + + self->priv->qmi_device = qmi_device_new_finish (res, &error); + if (!self->priv->qmi_device) { + mm_dbg ("[%s] error: couldn't create QmiDevice: %s", + mm_port_get_device (MM_PORT (self)), + error->message); + g_error_free (error); + /* Ignore error and complete */ + mm_info ("[%s] MBIM device is not QMI capable", + mm_port_get_device (MM_PORT (self))); + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + /* Try to open using QMI over MBIM */ + mm_dbg ("[%s] trying to open QMI over MBIM device...", + mm_port_get_device (MM_PORT (self))); + qmi_device_open (self->priv->qmi_device, + (QMI_DEVICE_OPEN_FLAGS_PROXY | + QMI_DEVICE_OPEN_FLAGS_MBIM | + QMI_DEVICE_OPEN_FLAGS_VERSION_INFO), + 15, + g_task_get_cancellable (task), + (GAsyncReadyCallback)qmi_device_open_ready, + task); +} + +#endif + +static void +mbim_device_open_ready (MbimDevice *mbim_device, GAsyncResult *res, - GTask *task) + GTask *task) { - GError *error = NULL; + GError *error = NULL; MMPortMbim *self; self = g_task_get_source_object (task); @@ -54,18 +132,40 @@ mbim_device_open_ready (MbimDevice *mbim_device, if (!mbim_device_open_full_finish (mbim_device, res, &error)) { g_clear_object (&self->priv->mbim_device); g_task_return_error (task, error); - } else - g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + mm_dbg ("[%s] MBIM device is now open", + mm_port_get_device (MM_PORT (self))); + +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + { + GFile *file; + + if ((file = G_FILE (g_task_get_task_data (task)))) { + mm_dbg ("[%s] checking if QMI over MBIM is supported", + mm_port_get_device (MM_PORT (self))); + qmi_device_new (file, + g_task_get_cancellable (task), + (GAsyncReadyCallback) qmi_device_new_ready, + task); + return; + } + } +#endif + g_task_return_boolean (task, TRUE); g_object_unref (task); + } static void -mbim_device_new_ready (GObject *unused, +mbim_device_new_ready (GObject *unused, GAsyncResult *res, - GTask *task) + GTask *task) { - GError *error = NULL; + GError *error = NULL; MMPortMbim *self; self = g_task_get_source_object (task); @@ -86,10 +186,13 @@ mbim_device_new_ready (GObject *unused, } void -mm_port_mbim_open (MMPortMbim *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +mm_port_mbim_open (MMPortMbim *self, +#if WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + gboolean try_qmi_over_mbim, +#endif + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { GFile *file; gchar *fullpath; @@ -117,6 +220,10 @@ mm_port_mbim_open (MMPortMbim *self, fullpath = g_strdup_printf ("/dev/%s", mm_port_get_device (MM_PORT (self))); file = g_file_new_for_path (fullpath); + /* If we want to try QMI over MBIM, store the GFile as task data */ + if (try_qmi_over_mbim) + g_task_set_task_data (task, g_object_ref (file), g_object_unref); + self->priv->in_progress = TRUE; mbim_device_new (file, cancellable, @@ -194,6 +301,19 @@ mm_port_mbim_close (MMPortMbim *self, } self->priv->in_progress = TRUE; + +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + if (self->priv->qmi_device) { + GError *error = NULL; + + 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); + } +#endif + mbim_device_close (self->priv->mbim_device, 5, NULL, @@ -235,6 +355,10 @@ dispose (GObject *object) { MMPortMbim *self = MM_PORT_MBIM (object); +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + g_clear_object (&self->priv->qmi_device); +#endif + /* Clear device object */ g_clear_object (&self->priv->mbim_device); diff --git a/src/mm-port-mbim.h b/src/mm-port-mbim.h index 738f1c552..8e1bcff5d 100644 --- a/src/mm-port-mbim.h +++ b/src/mm-port-mbim.h @@ -49,6 +49,9 @@ GType mm_port_mbim_get_type (void); MMPortMbim *mm_port_mbim_new (const gchar *name); void mm_port_mbim_open (MMPortMbim *self, +#if WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + gboolean try_qmi_over_mbim, +#endif GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c index 1739318a8..20c981f20 100644 --- a/src/mm-port-probe.c +++ b/src/mm-port-probe.c @@ -557,6 +557,9 @@ wdm_probe_mbim (MMPortProbe *self) /* Create a port and try to open it */ ctx->mbim_port = mm_port_mbim_new (mm_kernel_device_get_name (self->priv->port)); mm_port_mbim_open (ctx->mbim_port, +#if WITH_QMI + FALSE, /* Don't check QMI over MBIM support at this stage */ +#endif NULL, (GAsyncReadyCallback) mbim_port_open_ready, self); |