summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2013-04-06 19:54:55 +0200
committerAleksander Morgado <aleksander@lanedo.com>2013-04-12 14:52:44 +0200
commit1f3f02684eb38c57466a257c13bf692d464b47e7 (patch)
tree6b7dc98e075959248f56ac270b505fbe71d63f21
parentd8bfc0aeb0f6763ee3373fa591c2618ebdeb7e5c (diff)
downloadModemManager-1f3f02684eb38c57466a257c13bf692d464b47e7.tar.gz
port-probe: include MBIM port probing logic
-rw-r--r--src/Makefile.am15
-rw-r--r--src/mm-mbim-port.c226
-rw-r--r--src/mm-mbim-port.h61
-rw-r--r--src/mm-port-probe.c207
-rw-r--r--src/mm-port-probe.h13
-rw-r--r--src/mm-port.h3
6 files changed, 500 insertions, 25 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8df350b86..73046c3fd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,7 +83,7 @@ libserial_la_SOURCES = \
mm-gps-serial-port.c \
mm-gps-serial-port.h
-# Additional QMI support in libmodem-helpers
+# Additional QMI support in libserial
if WITH_QMI
libserial_la_SOURCES += \
mm-qmi-port.c \
@@ -91,6 +91,14 @@ libserial_la_SOURCES += \
libserial_la_CPPFLAGS += $(QMI_CFLAGS)
endif
+# Additional MBIM support in libserial
+if WITH_MBIM
+libserial_la_SOURCES += \
+ mm-mbim-port.c \
+ mm-mbim-port.h
+libserial_la_CPPFLAGS += $(MBIM_CFLAGS)
+endif
+
# Daemon specific enum types
DAEMON_ENUMS = \
$(srcdir)/mm-bearer.h \
@@ -239,6 +247,11 @@ ModemManager_CPPFLAGS += $(QMI_CFLAGS)
ModemManager_LDADD += $(QMI_LIBS)
endif
+# Additional MBIM support in ModemManager
+if WITH_MBIM
+ModemManager_CPPFLAGS += $(MBIM_CFLAGS)
+ModemManager_LDADD += $(MBIM_LIBS)
+endif
EXTRA_DIST = \
$(udevrules_DATA) \
diff --git a/src/mm-mbim-port.c b/src/mm-mbim-port.c
new file mode 100644
index 000000000..ad278b1c5
--- /dev/null
+++ b/src/mm-mbim-port.c
@@ -0,0 +1,226 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <ModemManager.h>
+#include <mm-errors-types.h>
+
+#include "mm-mbim-port.h"
+#include "mm-log.h"
+
+G_DEFINE_TYPE (MMMbimPort, mm_mbim_port, MM_TYPE_PORT)
+
+struct _MMMbimPortPrivate {
+ gboolean opening;
+ MbimDevice *mbim_device;
+};
+
+/*****************************************************************************/
+
+typedef struct {
+ MMMbimPort *self;
+ GSimpleAsyncResult *result;
+ GCancellable *cancellable;
+} PortOpenContext;
+
+static void
+port_open_context_complete_and_free (PortOpenContext *ctx)
+{
+ g_simple_async_result_complete_in_idle (ctx->result);
+ if (ctx->cancellable)
+ g_object_unref (ctx->cancellable);
+ g_object_unref (ctx->result);
+ g_object_unref (ctx->self);
+ g_slice_free (PortOpenContext, ctx);
+}
+
+gboolean
+mm_mbim_port_open_finish (MMMbimPort *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+mbim_device_open_ready (MbimDevice *mbim_device,
+ GAsyncResult *res,
+ PortOpenContext *ctx)
+{
+ GError *error = NULL;
+
+ /* Reset the opening flag */
+ ctx->self->priv->opening = FALSE;
+
+ if (!mbim_device_open_finish (mbim_device, res, &error)) {
+ g_clear_object (&ctx->self->priv->mbim_device);
+ g_simple_async_result_take_error (ctx->result, error);
+ } else
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+
+ port_open_context_complete_and_free (ctx);
+}
+
+static void
+mbim_device_new_ready (GObject *unused,
+ GAsyncResult *res,
+ PortOpenContext *ctx)
+{
+ GError *error = NULL;
+
+ ctx->self->priv->mbim_device = mbim_device_new_finish (res, &error);
+ if (!ctx->self->priv->mbim_device) {
+ g_simple_async_result_take_error (ctx->result, error);
+ port_open_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* Now open the MBIM device */
+ mbim_device_open (ctx->self->priv->mbim_device,
+ 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)mbim_device_open_ready,
+ ctx);
+}
+
+void
+mm_mbim_port_open (MMMbimPort *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GFile *file;
+ gchar *fullpath;
+ PortOpenContext *ctx;
+
+ g_return_if_fail (MM_IS_MBIM_PORT (self));
+
+ ctx = g_slice_new0 (PortOpenContext);
+ ctx->self = g_object_ref (self);
+ ctx->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ mm_mbim_port_open);
+ ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+ if (self->priv->opening) {
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_IN_PROGRESS,
+ "MBIM device already being opened");
+ port_open_context_complete_and_free (ctx);
+ return;
+ }
+
+ if (self->priv->mbim_device) {
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ port_open_context_complete_and_free (ctx);
+ return;
+ }
+
+ fullpath = g_strdup_printf ("/dev/%s", mm_port_get_device (MM_PORT (self)));
+ file = g_file_new_for_path (fullpath);
+
+ self->priv->opening = TRUE;
+ mbim_device_new (file,
+ ctx->cancellable,
+ (GAsyncReadyCallback)mbim_device_new_ready,
+ ctx);
+
+ g_free (fullpath);
+ g_object_unref (file);
+}
+
+gboolean
+mm_mbim_port_is_open (MMMbimPort *self)
+{
+ g_return_val_if_fail (MM_IS_MBIM_PORT (self), FALSE);
+
+ return !!self->priv->mbim_device;
+}
+
+static void
+mbim_device_close_ready (MbimDevice *device,
+ GAsyncResult *res)
+{
+ GError *error = NULL;
+
+ if (!mbim_device_close_finish (device, res, &error)) {
+ mm_warn ("Couldn't properly close MBIM device: %s",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+void
+mm_mbim_port_close (MMMbimPort *self)
+{
+ g_return_if_fail (MM_IS_MBIM_PORT (self));
+
+ if (!self->priv->mbim_device)
+ return;
+
+ /* Close and release the device. This method is async,
+ * but we don't really care about the result. */
+ mbim_device_close (self->priv->mbim_device,
+ 5,
+ NULL,
+ (GAsyncReadyCallback)mbim_device_close_ready,
+ NULL);
+
+ g_clear_object (&self->priv->mbim_device);
+}
+
+/*****************************************************************************/
+
+MMMbimPort *
+mm_mbim_port_new (const gchar *name)
+{
+ return MM_MBIM_PORT (g_object_new (MM_TYPE_MBIM_PORT,
+ MM_PORT_DEVICE, name,
+ MM_PORT_SUBSYS, MM_PORT_SUBSYS_USB,
+ MM_PORT_TYPE, MM_PORT_TYPE_MBIM,
+ NULL));
+}
+
+static void
+mm_mbim_port_init (MMMbimPort *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_MBIM_PORT, MMMbimPortPrivate);
+}
+
+static void
+dispose (GObject *object)
+{
+ MMMbimPort *self = MM_MBIM_PORT (object);
+
+ /* Clear device object */
+ g_clear_object (&self->priv->mbim_device);
+
+ G_OBJECT_CLASS (mm_mbim_port_parent_class)->dispose (object);
+}
+
+static void
+mm_mbim_port_class_init (MMMbimPortClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMMbimPortPrivate));
+
+ /* Virtual methods */
+ object_class->dispose = dispose;
+}
diff --git a/src/mm-mbim-port.h b/src/mm-mbim-port.h
new file mode 100644
index 000000000..0ea639494
--- /dev/null
+++ b/src/mm-mbim-port.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ */
+
+#ifndef MM_MBIM_PORT_H
+#define MM_MBIM_PORT_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include <libmbim-glib.h>
+
+#include "mm-port.h"
+
+#define MM_TYPE_MBIM_PORT (mm_mbim_port_get_type ())
+#define MM_MBIM_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MBIM_PORT, MMMbimPort))
+#define MM_MBIM_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_MBIM_PORT, MMMbimPortClass))
+#define MM_IS_MBIM_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MBIM_PORT))
+#define MM_IS_MBIM_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_MBIM_PORT))
+#define MM_MBIM_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_MBIM_PORT, MMMbimPortClass))
+
+typedef struct _MMMbimPort MMMbimPort;
+typedef struct _MMMbimPortClass MMMbimPortClass;
+typedef struct _MMMbimPortPrivate MMMbimPortPrivate;
+
+struct _MMMbimPort {
+ MMPort parent;
+ MMMbimPortPrivate *priv;
+};
+
+struct _MMMbimPortClass {
+ MMPortClass parent;
+};
+
+GType mm_mbim_port_get_type (void);
+
+MMMbimPort *mm_mbim_port_new (const gchar *name);
+
+void mm_mbim_port_open (MMMbimPort *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mm_mbim_port_open_finish (MMMbimPort *self,
+ GAsyncResult *res,
+ GError **error);
+gboolean mm_mbim_port_is_open (MMMbimPort *self);
+void mm_mbim_port_close (MMMbimPort *self);
+
+#endif /* MM_MBIM_PORT_H */
diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c
index ebeb33a45..9f55a0a5b 100644
--- a/src/mm-port-probe.c
+++ b/src/mm-port-probe.c
@@ -40,6 +40,10 @@
#include "mm-qmi-port.h"
#endif
+#if defined WITH_MBIM
+#include "mm-mbim-port.h"
+#endif
+
/*
* Steps and flow of the Probing process:
* ----> AT Serial Open
@@ -52,6 +56,8 @@
* |----> QCDM?
* ----> QMI Device Open
* |----> QMI Version Info check
+ * ----> MBIM Device Open
+ * |----> MBIM capabilities check
*/
G_DEFINE_TYPE (MMPortProbe, mm_port_probe, G_TYPE_OBJECT)
@@ -106,6 +112,11 @@ typedef struct {
MMQmiPort *qmi_port;
#endif
+#if defined WITH_MBIM
+ /* ---- MBIM probing specific context ---- */
+ MMMbimPort *mbim_port;
+#endif
+
} PortProbeRunTask;
struct _MMPortProbePrivate {
@@ -121,6 +132,7 @@ struct _MMPortProbePrivate {
gchar *product;
gboolean is_icera;
gboolean is_qmi;
+ gboolean is_mbim;
/* Current probing task. Only one can be available at a time */
PortProbeRunTask *task;
@@ -138,10 +150,11 @@ mm_port_probe_set_result_at (MMPortProbe *self,
g_udev_device_get_subsystem (self->priv->port),
g_udev_device_get_name (self->priv->port));
- /* Also set as not a QCDM/QMI port */
+ /* Also set as not a QCDM/QMI/MBIM port */
self->priv->is_qcdm = FALSE;
self->priv->is_qmi = FALSE;
- self->priv->flags |= (MM_PORT_PROBE_QCDM | MM_PORT_PROBE_QMI);
+ self->priv->is_mbim = FALSE;
+ self->priv->flags |= (MM_PORT_PROBE_QCDM | MM_PORT_PROBE_QMI | MM_PORT_PROBE_MBIM);
} else {
mm_dbg ("(%s/%s) port is not AT-capable",
g_udev_device_get_subsystem (self->priv->port),
@@ -225,9 +238,10 @@ mm_port_probe_set_result_qcdm (MMPortProbe *self,
g_udev_device_get_subsystem (self->priv->port),
g_udev_device_get_name (self->priv->port));
- /* Also set as not an AT/QMI port */
+ /* Also set as not an AT/QMI/MBIM port */
self->priv->is_at = FALSE;
self->priv->is_qmi = FALSE;
+ self->priv->is_mbim = FALSE;
self->priv->vendor = NULL;
self->priv->product = NULL;
self->priv->is_icera = FALSE;
@@ -235,7 +249,8 @@ mm_port_probe_set_result_qcdm (MMPortProbe *self,
MM_PORT_PROBE_AT_VENDOR |
MM_PORT_PROBE_AT_PRODUCT |
MM_PORT_PROBE_AT_ICERA |
- MM_PORT_PROBE_QMI);
+ MM_PORT_PROBE_QMI |
+ MM_PORT_PROBE_MBIM);
} else
mm_dbg ("(%s/%s) port is not QCDM-capable",
g_udev_device_get_subsystem (self->priv->port),
@@ -254,22 +269,54 @@ mm_port_probe_set_result_qmi (MMPortProbe *self,
g_udev_device_get_subsystem (self->priv->port),
g_udev_device_get_name (self->priv->port));
- /* Also set as not an AT/QCDM port */
+ /* Also set as not an AT/QCDM/MBIM port */
self->priv->is_at = FALSE;
self->priv->is_qcdm = FALSE;
+ self->priv->is_mbim = FALSE;
self->priv->vendor = NULL;
self->priv->product = NULL;
self->priv->flags |= (MM_PORT_PROBE_AT |
MM_PORT_PROBE_AT_VENDOR |
MM_PORT_PROBE_AT_PRODUCT |
MM_PORT_PROBE_AT_ICERA |
- MM_PORT_PROBE_QCDM);
+ MM_PORT_PROBE_QCDM |
+ MM_PORT_PROBE_MBIM);
} else
mm_dbg ("(%s/%s) port is not QMI-capable",
g_udev_device_get_subsystem (self->priv->port),
g_udev_device_get_name (self->priv->port));
}
+void
+mm_port_probe_set_result_mbim (MMPortProbe *self,
+ gboolean mbim)
+{
+ self->priv->is_mbim = mbim;
+ self->priv->flags |= MM_PORT_PROBE_MBIM;
+
+ if (self->priv->is_mbim) {
+ mm_dbg ("(%s/%s) port is MBIM-capable",
+ g_udev_device_get_subsystem (self->priv->port),
+ g_udev_device_get_name (self->priv->port));
+
+ /* Also set as not an AT/QCDM/QMI port */
+ self->priv->is_at = FALSE;
+ self->priv->is_qcdm = FALSE;
+ self->priv->is_qmi = FALSE;
+ self->priv->vendor = NULL;
+ self->priv->product = NULL;
+ self->priv->flags |= (MM_PORT_PROBE_AT |
+ MM_PORT_PROBE_AT_VENDOR |
+ MM_PORT_PROBE_AT_PRODUCT |
+ MM_PORT_PROBE_AT_ICERA |
+ MM_PORT_PROBE_QCDM |
+ MM_PORT_PROBE_QMI);
+ } else
+ mm_dbg ("(%s/%s) port is not MBIM-capable",
+ g_udev_device_get_subsystem (self->priv->port),
+ g_udev_device_get_name (self->priv->port));
+}
+
static gboolean serial_probe_at (MMPortProbe *self);
static gboolean serial_probe_qcdm (MMPortProbe *self);
static void serial_probe_schedule (MMPortProbe *self);
@@ -296,6 +343,14 @@ port_probe_run_task_free (PortProbeRunTask *task)
}
#endif
+#if defined WITH_MBIM
+ if (task->mbim_port) {
+ if (mm_mbim_port_is_open (task->mbim_port))
+ mm_mbim_port_close (task->mbim_port);
+ g_object_unref (task->mbim_port);
+ }
+#endif
+
if (task->cancellable)
g_object_unref (task->cancellable);
if (task->at_probing_cancellable)
@@ -352,7 +407,9 @@ port_probe_run_is_cancelled (MMPortProbe *self)
}
/***************************************************************/
-/* QMI */
+/* QMI & MBIM */
+
+static gboolean wdm_probe (MMPortProbe *self);
#if defined WITH_QMI
@@ -379,21 +436,17 @@ qmi_port_open_ready (MMQmiPort *qmi_port,
mm_qmi_port_close (qmi_port);
- /* All done! Finish asynchronously */
- port_probe_run_task_complete (task, TRUE, NULL);
+ /* Keep on */
+ task->source_id = g_idle_add ((GSourceFunc)wdm_probe, self);
}
#endif /* WITH_QMI */
-static gboolean
+static void
wdm_probe_qmi (MMPortProbe *self)
{
PortProbeRunTask *task = self->priv->task;
- /* If already cancelled, do nothing else */
- if (port_probe_run_is_cancelled (self))
- return FALSE;
-
#if defined WITH_QMI
mm_dbg ("(%s/%s) probing QMI...",
g_udev_device_get_subsystem (self->priv->port),
@@ -409,8 +462,86 @@ wdm_probe_qmi (MMPortProbe *self)
#else
/* If not compiled with QMI support, just assume we won't have any QMI port */
mm_port_probe_set_result_qmi (self, FALSE);
- port_probe_run_task_complete (task, TRUE, NULL);
+ task->source_id = g_idle_add ((GSourceFunc)wdm_probe, self);
#endif /* WITH_QMI */
+}
+
+#if defined WITH_MBIM
+
+static void
+mbim_port_open_ready (MMMbimPort *mbim_port,
+ GAsyncResult *res,
+ MMPortProbe *self)
+{
+ PortProbeRunTask *task = self->priv->task;
+ GError *error = NULL;
+ gboolean is_mbim;
+
+ is_mbim = mm_mbim_port_open_finish (mbim_port, res, &error);
+ if (!is_mbim) {
+ mm_dbg ("(%s/%s) error checking MBIM support: '%s'",
+ g_udev_device_get_subsystem (self->priv->port),
+ g_udev_device_get_name (self->priv->port),
+ error ? error->message : "unknown error");
+ g_clear_error (&error);
+ }
+
+ /* Set probing result */
+ mm_port_probe_set_result_mbim (self, is_mbim);
+
+ mm_mbim_port_close (mbim_port);
+
+ /* Keep on */
+ task->source_id = g_idle_add ((GSourceFunc)wdm_probe, self);
+}
+
+#endif /* WITH_MBIM */
+
+static void
+wdm_probe_mbim (MMPortProbe *self)
+{
+ PortProbeRunTask *task = self->priv->task;
+
+#if defined WITH_MBIM
+ mm_dbg ("(%s/%s) probing MBIM...",
+ g_udev_device_get_subsystem (self->priv->port),
+ g_udev_device_get_name (self->priv->port));
+
+ /* Create a port and try to open it */
+ task->mbim_port = mm_mbim_port_new (g_udev_device_get_name (self->priv->port));
+ mm_mbim_port_open (task->mbim_port,
+ NULL,
+ (GAsyncReadyCallback)mbim_port_open_ready,
+ self);
+#else
+ /* If not compiled with MBIM support, just assume we won't have any MBIM port */
+ mm_port_probe_set_result_mbim (self, FALSE);
+ task->source_id = g_idle_add ((GSourceFunc)wdm_probe, self);
+#endif /* WITH_MBIM */
+}
+
+static gboolean
+wdm_probe (MMPortProbe *self)
+{
+ PortProbeRunTask *task = self->priv->task;
+
+ task->source_id = 0;
+
+ /* If already cancelled, do nothing else */
+ if (port_probe_run_is_cancelled (self))
+ return FALSE;
+
+ if ((task->flags & MM_PORT_PROBE_QMI) &&
+ !(self->priv->flags & MM_PORT_PROBE_QMI))
+ /* QMI probing needed */
+ wdm_probe_qmi (self);
+ else if ((task->flags & MM_PORT_PROBE_MBIM) &&
+ !(self->priv->flags & MM_PORT_PROBE_MBIM))
+ /* MBIM probing needed */
+ wdm_probe_mbim (self);
+ else
+ /* All done now */
+ port_probe_run_task_complete (task, TRUE, NULL);
return FALSE;
}
@@ -1151,7 +1282,7 @@ mm_port_probe_run (MMPortProbe *self,
/* Check if we already have the requested probing results.
* We will fix here the 'task->flags' so that we only request probing
* for the missing things. */
- for (i = MM_PORT_PROBE_AT; i <= MM_PORT_PROBE_QMI; i = (i << 1)) {
+ for (i = MM_PORT_PROBE_AT; i <= MM_PORT_PROBE_MBIM; i = (i << 1)) {
if ((flags & i) && !(self->priv->flags & i)) {
task->flags += i;
}
@@ -1193,9 +1324,9 @@ mm_port_probe_run (MMPortProbe *self,
return;
}
- /* If QMI probing needed, start by opening as a QMI port */
- if (task->flags & MM_PORT_PROBE_QMI) {
- task->source_id = g_idle_add ((GSourceFunc)wdm_probe_qmi, self);
+ /* If QMI/MBIM probing needed, go on */
+ if (task->flags & MM_PORT_PROBE_QMI || task->flags & MM_PORT_PROBE_MBIM) {
+ task->source_id = g_idle_add ((GSourceFunc)wdm_probe, self);
return;
}
@@ -1289,6 +1420,37 @@ mm_port_probe_list_has_qmi_port (GList *list)
return FALSE;
}
+gboolean
+mm_port_probe_is_mbim (MMPortProbe *self)
+{
+ const gchar *subsys;
+ const gchar *name;
+
+ g_return_val_if_fail (MM_IS_PORT_PROBE (self), FALSE);
+
+ subsys = g_udev_device_get_subsystem (self->priv->port);
+ name = g_udev_device_get_name (self->priv->port);
+ if (!g_str_has_prefix (subsys, "usb") ||
+ !name ||
+ !g_str_has_prefix (name, "cdc-wdm"))
+ return FALSE;
+
+ return self->priv->is_mbim;
+}
+
+gboolean
+mm_port_probe_list_has_mbim_port (GList *list)
+{
+ GList *l;
+
+ for (l = list; l; l = g_list_next (l)) {
+ if (mm_port_probe_is_mbim (MM_PORT_PROBE (l->data)))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
MMPortType
mm_port_probe_get_port_type (MMPortProbe *self)
{
@@ -1310,6 +1472,13 @@ mm_port_probe_get_port_type (MMPortProbe *self)
return MM_PORT_TYPE_QMI;
#endif
+#if defined WITH_MBIM
+ if (g_str_has_prefix (subsys, "usb") &&
+ g_str_has_prefix (name, "cdc-wdm") &&
+ self->priv->is_mbim)
+ return MM_PORT_TYPE_MBIM;
+#endif
+
if (self->priv->flags & MM_PORT_PROBE_QCDM &&
self->priv->is_qcdm)
return MM_PORT_TYPE_QCDM;
diff --git a/src/mm-port-probe.h b/src/mm-port-probe.h
index dfce77a86..74bf84dec 100644
--- a/src/mm-port-probe.h
+++ b/src/mm-port-probe.h
@@ -43,7 +43,8 @@ typedef enum { /*< underscore_name=mm_port_probe_flag >*/
MM_PORT_PROBE_AT_PRODUCT = 1 << 2,
MM_PORT_PROBE_AT_ICERA = 1 << 3,
MM_PORT_PROBE_QCDM = 1 << 4,
- MM_PORT_PROBE_QMI = 1 << 5
+ MM_PORT_PROBE_QMI = 1 << 5,
+ MM_PORT_PROBE_MBIM = 1 << 6
} MMPortProbeFlag;
typedef struct _MMPortProbe MMPortProbe;
@@ -100,6 +101,8 @@ void mm_port_probe_set_result_qcdm (MMPortProbe *self,
gboolean qcdm);
void mm_port_probe_set_result_qmi (MMPortProbe *self,
gboolean qmi);
+void mm_port_probe_set_result_mbim (MMPortProbe *self,
+ gboolean mbim);
/* Run probing */
void mm_port_probe_run (MMPortProbe *self,
@@ -123,13 +126,15 @@ MMPortType mm_port_probe_get_port_type (MMPortProbe *self);
gboolean mm_port_probe_is_at (MMPortProbe *self);
gboolean mm_port_probe_is_qcdm (MMPortProbe *self);
gboolean mm_port_probe_is_qmi (MMPortProbe *self);
+gboolean mm_port_probe_is_mbim (MMPortProbe *self);
const gchar *mm_port_probe_get_vendor (MMPortProbe *self);
const gchar *mm_port_probe_get_product (MMPortProbe *self);
gboolean mm_port_probe_is_icera (MMPortProbe *self);
/* Additional helpers */
-gboolean mm_port_probe_list_has_at_port (GList *list);
-gboolean mm_port_probe_list_has_qmi_port (GList *list);
-gboolean mm_port_probe_list_is_icera (GList *list);
+gboolean mm_port_probe_list_has_at_port (GList *list);
+gboolean mm_port_probe_list_has_qmi_port (GList *list);
+gboolean mm_port_probe_list_has_mbim_port (GList *list);
+gboolean mm_port_probe_list_is_icera (GList *list);
#endif /* MM_PORT_PROBE_H */
diff --git a/src/mm-port.h b/src/mm-port.h
index 195148234..e5395b473 100644
--- a/src/mm-port.h
+++ b/src/mm-port.h
@@ -37,7 +37,8 @@ typedef enum { /*< underscore_name=mm_port_type >*/
MM_PORT_TYPE_QCDM,
MM_PORT_TYPE_GPS,
MM_PORT_TYPE_QMI,
- MM_PORT_TYPE_LAST = MM_PORT_TYPE_QMI /*< skip >*/
+ MM_PORT_TYPE_MBIM,
+ MM_PORT_TYPE_LAST = MM_PORT_TYPE_MBIM /*< skip >*/
} MMPortType;
#define MM_TYPE_PORT (mm_port_get_type ())