port-probe: include MBIM port probing logic
This commit is contained in:
+14
-1
@@ -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) \
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
+188
-19
@@ -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;
|
||||
|
||||
+9
-4
@@ -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 */
|
||||
|
||||
+2
-1
@@ -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 ())
|
||||
|
||||
Reference in New Issue
Block a user