aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2016-04-04 14:44:01 +0200
committerAleksander Morgado <aleksander@aleksander.es>2016-07-07 19:16:17 +0200
commitfb4b2c56198c15fed771e91500919b8734f5453e (patch)
tree2948d45ffdbbc038fe059c4ea674d151da11596b
parentfafafd023675ad337d71b7c92e85f397e659929d (diff)
libqmi: support MBIM EXT_QMUX service
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--configure.ac13
-rw-r--r--src/libqmi-glib/Makefile.am4
-rw-r--r--src/libqmi-glib/qmi-device.c155
-rw-r--r--src/libqmi-glib/qmi-device.h4
4 files changed, 171 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac
index 3e05993..fe6225e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,6 +95,18 @@ fi
AM_CONDITIONAL([QMI_USERNAME_ENABLED], [test "x$QMI_USERNAME_ENABLED" = "xyes"])
+# MBIM QMUX service support
+AC_ARG_ENABLE(mbim-qmux,
+ AS_HELP_STRING([--enable-mbim-qmux], [support QMI over MBIM QMUX service]))
+if test -n "$enable_mbim_qmux"; then
+ PKG_CHECK_MODULES(MBIM, mbim-glib >= 1.13)
+ MBIM_CFLAGS="$MBIM_CFLAGS -DMBIM_QMUX"
+ AC_SUBST(MBIM_CFLAGS)
+ AC_SUBST(MBIM_LIBS)
+fi
+
+AM_CONDITIONAL(MBIM_QMUX, [test -n "$MBIM_CFLAGS"])
+
# udev base directory
AC_ARG_WITH(udev-base-dir, AS_HELP_STRING([--with-udev-base-dir=DIR], [where udev base directory is]))
if test -n "$with_udev_base_dir" ; then
@@ -146,4 +158,5 @@ echo "
udev base directory: ${UDEV_BASE_DIR}
Documentation: ${enable_gtk_doc}
QMI username: ${QMI_USERNAME_ENABLED} (${QMI_USERNAME})
+ QMUX over MBIM: ${enable_mbim_qmux}
"
diff --git a/src/libqmi-glib/Makefile.am b/src/libqmi-glib/Makefile.am
index b24e3ae..6ff4e66 100644
--- a/src/libqmi-glib/Makefile.am
+++ b/src/libqmi-glib/Makefile.am
@@ -5,6 +5,7 @@ lib_LTLIBRARIES = libqmi-glib.la
libqmi_glib_la_CPPFLAGS = \
$(GLIB_CFLAGS) \
+ $(MBIM_CFLAGS) \
-I$(top_srcdir) \
-I$(top_builddir) \
-I$(top_srcdir)/src/libqmi-glib \
@@ -39,7 +40,8 @@ libqmi_glib_la_SOURCES = \
libqmi_glib_la_LIBADD = \
${top_builddir}/src/libqmi-glib/generated/libqmi-glib-generated.la \
- $(GLIB_LIBS)
+ $(GLIB_LIBS) \
+ $(MBIM_LIBS)
libqmi_glib_la_LDFLAGS = \
-version-info $(QMI_GLIB_LT_CURRENT):$(QMI_GLIB_LT_REVISION):$(QMI_GLIB_LT_AGE)
diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c
index c4abbbc..7479fcd 100644
--- a/src/libqmi-glib/qmi-device.c
+++ b/src/libqmi-glib/qmi-device.c
@@ -32,6 +32,10 @@
#include <gio/gunixoutputstream.h>
#include <gio/gunixsocketaddress.h>
+#ifdef MBIM_QMUX
+#include <libmbim-glib.h>
+#endif
+
#include "qmi-device.h"
#include "qmi-message.h"
#include "qmi-ctl.h"
@@ -92,6 +96,10 @@ struct _QmiDevicePrivate {
gchar *path_display;
gboolean no_file_check;
gchar *proxy_path;
+ gboolean mbim_qmux;
+#ifdef MBIM_QMUX
+ MbimDevice *mbimdev;
+#endif
/* WWAN interface */
gboolean no_wwan_check;
@@ -1689,7 +1697,6 @@ input_ready_cb (GInputStream *istream,
self->priv->buffer = g_byte_array_sized_new (r);
g_byte_array_append (self->priv->buffer, buffer, r);
- /* Try to parse input messages */
parse_response (self);
return TRUE;
@@ -2134,6 +2141,56 @@ internal_proxy_open_ready (QmiClientCtl *client_ctl,
device_open_context_step (ctx);
}
+#ifdef MBIM_QMUX
+static void
+mbim_device_open_ready (MbimDevice *dev,
+ GAsyncResult *res,
+ DeviceOpenContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!mbim_device_open_finish (dev, res, &error)) {
+ g_simple_async_result_take_error (ctx->result, error);
+ device_open_context_complete_and_free (ctx);
+ return;
+ }
+ g_debug ("[%s] MBIM device Open..",
+ ctx->self->priv->path_display);
+
+ /* Go on */
+ ctx->step++;
+ device_open_context_step (ctx);
+ return;
+}
+
+static void
+mbim_device_new_ready (GObject *source,
+ GAsyncResult *res,
+ DeviceOpenContext *ctx)
+{
+ MbimDeviceOpenFlags open_flags = MBIM_DEVICE_OPEN_FLAGS_NONE;
+ GError *error = NULL;
+ MbimDevice *device;
+
+ if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_PROXY)
+ open_flags |= MBIM_DEVICE_OPEN_FLAGS_PROXY;
+ device = mbim_device_new_finish (res, &error);
+ if (!device) {
+ g_simple_async_result_take_error (ctx->result, error);
+ device_open_context_complete_and_free (ctx);
+ return;
+ }
+ ctx->self->priv->mbimdev = device;
+
+ mbim_device_open_full(device,
+ open_flags,
+ 30,
+ ctx->cancellable,
+ (GAsyncReadyCallback)mbim_device_open_ready,
+ ctx);
+}
+#endif
+
static void
create_iostream_ready (QmiDevice *self,
GAsyncResult *res,
@@ -2166,6 +2223,20 @@ device_open_context_step (DeviceOpenContext *ctx)
/* Fall down */
case DEVICE_OPEN_CONTEXT_STEP_CREATE_IOSTREAM:
+#ifdef MBIM_QMUX
+ if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_MBIM) {
+ GFile *file;
+
+ ctx->self->priv->mbim_qmux = TRUE;
+ file = g_file_new_for_path (ctx->self->priv->path);
+ mbim_device_new (file,
+ ctx->cancellable,
+ (GAsyncReadyCallback)mbim_device_new_ready,
+ ctx);
+ g_object_unref (file);
+ return;
+ }
+#endif
create_iostream (ctx->self,
!!(ctx->flags & QMI_DEVICE_OPEN_FLAGS_PROXY),
(GAsyncReadyCallback)create_iostream_ready,
@@ -2174,7 +2245,8 @@ device_open_context_step (DeviceOpenContext *ctx)
case DEVICE_OPEN_CONTEXT_STEP_FLAGS_PROXY:
/* Initialize communication with proxy? */
- if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_PROXY) {
+ if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_PROXY &&
+ !(ctx->flags & QMI_DEVICE_OPEN_FLAGS_MBIM)) {
QmiMessageCtlInternalProxyOpenInput *input;
input = qmi_message_ctl_internal_proxy_open_input_new ();
@@ -2369,6 +2441,21 @@ destroy_iostream (QmiDevice *self,
return TRUE;
}
+#ifdef MBIM_QMUX
+static void
+mbim_device_close_ready (MbimDevice *dev,
+ GAsyncResult *res)
+{
+ GError *error = NULL;
+
+ if (!mbim_device_close_finish (dev, res, &error)) {
+ g_printerr ("error: couldn't close device: %s", error->message);
+ g_error_free (error);
+ } else
+ g_debug ("Device closed");
+}
+#endif
+
/**
* qmi_device_close:
* @self: a #QmiDevice
@@ -2386,6 +2473,15 @@ qmi_device_close (QmiDevice *self,
{
g_return_val_if_fail (QMI_IS_DEVICE (self), FALSE);
+#ifdef MBIM_QMUX
+ if (self->priv->mbim_qmux)
+ mbim_device_close (self->priv->mbimdev,
+ 15,
+ NULL,
+ (GAsyncReadyCallback) mbim_device_close_ready,
+ NULL);
+ else
+#endif
if (!destroy_iostream (self, error)) {
g_prefix_error (error, "Cannot close QMI device: ");
return FALSE;
@@ -2394,6 +2490,41 @@ qmi_device_close (QmiDevice *self,
return TRUE;
}
+#ifdef MBIM_QMUX
+static void
+mbim_device_command_ready (MbimDevice *dev,
+ GAsyncResult *res,
+ QmiDevice *qmidev)
+{
+ MbimMessage *response;
+ GError *error = NULL;
+ const guint8 *buf;
+ guint32 len;
+
+ response = mbim_device_command_finish (dev, res, &error);
+ if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
+ g_prefix_error (&error, "MBIM error: ");
+ // transaction_complete_and_free (tr, NULL, error);
+ g_error_free (error);
+ mbim_message_unref (response);
+ return;
+ }
+
+ g_debug ("[%s] Received MBIM message\n", qmidev->priv->path_display);
+
+ /* get the information buffer */
+ buf = mbim_message_command_done_get_raw_information_buffer (response, &len);
+ if (!G_UNLIKELY (qmidev->priv->buffer))
+ qmidev->priv->buffer = g_byte_array_sized_new (len);
+ g_byte_array_append (qmidev->priv->buffer, buf, len);
+
+ /* and parse it as QMI */
+ parse_response(qmidev);
+ mbim_message_unref (response);
+ return;
+}
+#endif
+
/*****************************************************************************/
/* Command */
@@ -2462,7 +2593,7 @@ qmi_device_command (QmiDevice *self,
tr = transaction_new (self, message, cancellable, callback, user_data);
/* Device must be open */
- if (!self->priv->istream || !self->priv->ostream) {
+ if ((!self->priv->istream || !self->priv->ostream) && !self->priv->mbim_qmux) {
error = g_error_new (QMI_CORE_ERROR,
QMI_CORE_ERROR_WRONG_STATE,
"Device must be open to send commands");
@@ -2531,6 +2662,24 @@ qmi_device_command (QmiDevice *self,
g_free (printable);
}
+#ifdef MBIM_QMUX
+ /* wrap QMUX in MBIM? */
+ if (self->priv->mbim_qmux) {
+ MbimMessage *mbim;
+
+ mbim = (mbim_message_qmi_msg_set_new (raw_message_len, raw_message, &error));
+ mbim_device_command (self->priv->mbimdev,
+ mbim,
+ 30,
+ NULL, /* cancellable */
+ (GAsyncReadyCallback)mbim_device_command_ready,
+ self);
+ g_debug ("[%s] Message sent as MBIM\n", self->priv->path_display);
+
+ /* FIXME: check errors, set proper MBIM TID */
+ return;
+ }
+#endif
if (!g_output_stream_write_all (self->priv->ostream,
raw_message,
raw_message_len,
diff --git a/src/libqmi-glib/qmi-device.h b/src/libqmi-glib/qmi-device.h
index 58651e1..957efac 100644
--- a/src/libqmi-glib/qmi-device.h
+++ b/src/libqmi-glib/qmi-device.h
@@ -97,6 +97,7 @@ gboolean qmi_device_is_open (QmiDevice *self);
* @QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER: set network port to transmit/receive QoS headers; mutually exclusive with @QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER
* @QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER: set network port to not transmit/receive QoS headers; mutually exclusive with @QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER
* @QMI_DEVICE_OPEN_FLAGS_PROXY: Try to open the port through the 'qmi-proxy'.
+ * @QMI_DEVICE_OPEN_FLAGS_MBIM: open an MBIM port with QMUX tunneling service
*
* Flags to specify which actions to be performed when the device is open.
*/
@@ -108,7 +109,8 @@ typedef enum {
QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP = 1 << 3,
QMI_DEVICE_OPEN_FLAGS_NET_QOS_HEADER = 1 << 4,
QMI_DEVICE_OPEN_FLAGS_NET_NO_QOS_HEADER = 1 << 5,
- QMI_DEVICE_OPEN_FLAGS_PROXY = 1 << 6
+ QMI_DEVICE_OPEN_FLAGS_PROXY = 1 << 6,
+ QMI_DEVICE_OPEN_FLAGS_MBIM = 1 << 7
} QmiDeviceOpenFlags;
void qmi_device_open (QmiDevice *self,