>From 4ffa5693bcaf283bc3c8ea7808226eb6e92aaaf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 4 Apr 2016 14:44:01 +0200 Subject: [PATCH 1/2] libqmi: support MBIM EXT_QMUX service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork --- configure.ac | 13 ++++ src/libqmi-glib/Makefile.am | 4 +- src/libqmi-glib/qmi-device.c | 156 ++++++++++++++++++++++++++++++++++++++++++- src/libqmi-glib/qmi-device.h | 4 +- 4 files changed, 172 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..6c46bca 100644 --- a/src/libqmi-glib/qmi-device.c +++ b/src/libqmi-glib/qmi-device.c @@ -32,6 +32,10 @@ #include #include +#ifdef MBIM_QMUX +#include +#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,42 @@ 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 +2594,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 +2663,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, -- 2.1.4