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.
This commit is contained in:

committed by
Dan Williams

parent
f6a2d01c7e
commit
c0cc694c67
@@ -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);
|
||||
|
@@ -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>
|
||||
|
||||
@@ -27,6 +33,9 @@ G_DEFINE_TYPE (MMPortMbim, mm_port_mbim, MM_TYPE_PORT)
|
||||
struct _MMPortMbimPrivate {
|
||||
gboolean in_progress;
|
||||
MbimDevice *mbim_device;
|
||||
#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
|
||||
QmiDevice *qmi_device;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -39,6 +48,75 @@ mm_port_mbim_open_finish (MMPortMbim *self,
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
|
||||
|
||||
static void
|
||||
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,
|
||||
@@ -54,10 +132,32 @@ 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
|
||||
@@ -87,6 +187,9 @@ mbim_device_new_ready (GObject *unused,
|
||||
|
||||
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)
|
||||
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user