summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2018-06-19 11:55:10 +0200
committerDan Williams <dcbw@redhat.com>2018-08-21 13:26:08 +0000
commitc0cc694c67d9e71f200fb23e20473cc9b31d9ec0 (patch)
treed4cd449bebd292f3aa59c4684f218e182468dc4c
parentf6a2d01c7ee99204644db030a09fbd71566b7af7 (diff)
downloadModemManager-c0cc694c67d9e71f200fb23e20473cc9b31d9ec0.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.c3
-rw-r--r--src/mm-port-mbim.c158
-rw-r--r--src/mm-port-mbim.h3
-rw-r--r--src/mm-port-probe.c3
4 files changed, 150 insertions, 17 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 9ec0c04b9..29c239ff9 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -1953,6 +1953,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);