summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2017-01-23 21:24:59 +0100
committerAleksander Morgado <aleksander@aleksander.es>2017-02-08 18:49:21 +0100
commit830b6326404e59fb2d4b5733f57c7f1d9fb6e930 (patch)
tree212cee2ccc5a0af2e6aab7e7d713d16b69bf4583 /src
parentfad2ca074e44cf9dd340e9609ff30c047a5ecc0b (diff)
libqmi-glib: new 'auto' flag to select automatically QMI or MBIM mode
Diffstat (limited to 'src')
-rw-r--r--src/libqmi-glib/qmi-device.c52
-rw-r--r--src/libqmi-glib/qmi-device.h6
-rw-r--r--src/libqmi-glib/qmi-utils.c40
-rw-r--r--src/libqmi-glib/qmi-utils.h4
4 files changed, 98 insertions, 4 deletions
diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c
index 1d8890e..409aa72 100644
--- a/src/libqmi-glib/qmi-device.c
+++ b/src/libqmi-glib/qmi-device.c
@@ -2008,6 +2008,7 @@ create_iostream (QmiDevice *self,
typedef enum {
DEVICE_OPEN_CONTEXT_STEP_FIRST = 0,
+ DEVICE_OPEN_CONTEXT_STEP_DRIVER,
#if defined MBIM_QMUX_ENABLED
DEVICE_OPEN_CONTEXT_STEP_DEVICE_MBIM,
DEVICE_OPEN_CONTEXT_STEP_OPEN_DEVICE_MBIM,
@@ -2028,6 +2029,7 @@ typedef struct {
QmiDeviceOpenFlags flags;
guint timeout;
guint version_check_retries;
+ gchar *driver;
} DeviceOpenContext;
static void
@@ -2035,6 +2037,7 @@ device_open_context_complete_and_free (DeviceOpenContext *ctx)
{
g_simple_async_result_complete_in_idle (ctx->result);
g_object_unref (ctx->result);
+ g_free (ctx->driver);
if (ctx->cancellable)
g_object_unref (ctx->cancellable);
g_object_unref (ctx->self);
@@ -2361,6 +2364,55 @@ device_open_context_step (DeviceOpenContext *ctx)
ctx->step++;
/* Fall down */
+ case DEVICE_OPEN_CONTEXT_STEP_DRIVER:
+ ctx->driver = __qmi_utils_get_driver (ctx->self->priv->path);
+ if (ctx->driver)
+ g_debug ("[%s] loaded driver of cdc-wdm port: %s", ctx->self->priv->path_display, ctx->driver);
+
+#if defined MBIM_QMUX_ENABLED
+
+ /* Auto mode requested? */
+ if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_AUTO) {
+ if (!g_strcmp0 (ctx->driver, "cdc_mbim")) {
+ g_debug ("[%s] automatically selecting MBIM mode", ctx->self->priv->path_display);
+ ctx->flags |= QMI_DEVICE_OPEN_FLAGS_MBIM;
+ goto next_step;
+ }
+ if (!g_strcmp0 (ctx->driver, "qmi_wwan")) {
+ g_debug ("[%s] automatically selecting QMI mode", ctx->self->priv->path_display);
+ ctx->flags &= ~QMI_DEVICE_OPEN_FLAGS_MBIM;
+ goto next_step;
+ }
+ g_simple_async_result_set_error (ctx->result, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
+ "Cannot automatically select QMI/MBIM mode: driver %s",
+ ctx->driver ? ctx->driver : "unknown");
+ device_open_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* MBIM mode requested? */
+ if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_MBIM) {
+ if (!g_str_equal (ctx->driver, "cdc_mbim"))
+ g_warning ("[%s] requested MBIM mode but unexpected driver found: %s", ctx->self->priv->path_display, ctx->driver);
+ goto next_step;
+ }
+
+#else
+ if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_AUTO)
+ g_warning ("[%s] requested auto mode but no MBIM QMUX support available", ctx->self->priv->path_display);
+ if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_MBIM)
+ g_warning ("[%s] requested MBIM mode but no MBIM QMUX support available", ctx->self->priv->path_display);
+
+#endif /* MBIM_QMUX_ENABLED */
+
+ /* QMI mode requested? */
+ if (!g_str_equal (ctx->driver, "qmi_wwan"))
+ g_warning ("[%s] requested QMI mode but unexpected driver found: %s", ctx->self->priv->path_display, ctx->driver);
+
+ next_step:
+ ctx->step++;
+ /* Fall down */
+
#if defined MBIM_QMUX_ENABLED
case DEVICE_OPEN_CONTEXT_STEP_DEVICE_MBIM:
if (ctx->flags & QMI_DEVICE_OPEN_FLAGS_MBIM) {
diff --git a/src/libqmi-glib/qmi-device.h b/src/libqmi-glib/qmi-device.h
index 51e07ae..22f32c6 100644
--- a/src/libqmi-glib/qmi-device.h
+++ b/src/libqmi-glib/qmi-device.h
@@ -98,7 +98,8 @@ 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
+ * @QMI_DEVICE_OPEN_FLAGS_MBIM: open an MBIM port with QMUX tunneling service.
+ * @QMI_DEVICE_OPEN_FLAGS_AUTO: open a port either in QMI or MBIM mode, depending on device driver.
*
* Flags to specify which actions to be performed when the device is open.
*/
@@ -111,7 +112,8 @@ typedef enum {
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_MBIM = 1 << 7
+ QMI_DEVICE_OPEN_FLAGS_MBIM = 1 << 7,
+ QMI_DEVICE_OPEN_FLAGS_AUTO = 1 << 8,
} QmiDeviceOpenFlags;
void qmi_device_open (QmiDevice *self,
diff --git a/src/libqmi-glib/qmi-utils.c b/src/libqmi-glib/qmi-utils.c
index a4028cb..813c56d 100644
--- a/src/libqmi-glib/qmi-utils.c
+++ b/src/libqmi-glib/qmi-utils.c
@@ -18,11 +18,14 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
- * Copyright (C) 2012-2015 Aleksander Morgado <aleksander@aleksander.es>
* Copyright (C) 2012-2015 Dan Williams <dcbw@redhat.com>
+ * Copyright (C) 2012-2017 Aleksander Morgado <aleksander@aleksander.es>
*/
#include <config.h>
+
+#define _GNU_SOURCE
+#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
@@ -1078,6 +1081,41 @@ qmi_utils_write_fixed_size_string_to_buffer (guint8 **buffer,
/*****************************************************************************/
+gchar *
+__qmi_utils_get_driver (const gchar *cdc_wdm_path)
+{
+ static const gchar *subsystems[] = { "usbmisc", "usb" };
+ guint i;
+ gchar *device_basename;
+ gchar *driver = NULL;
+
+ device_basename = g_path_get_basename (cdc_wdm_path);
+
+ for (i = 0; !driver && i < G_N_ELEMENTS (subsystems); i++) {
+ gchar *tmp;
+ gchar *path;
+
+ /* driver sysfs can be built directly using subsystem and name; e.g. for subsystem
+ * usbmisc and name cdc-wdm0:
+ * $ realpath /sys/class/usbmisc/cdc-wdm0/device/driver
+ * /sys/bus/usb/drivers/qmi_wwan
+ */
+ tmp = g_strdup_printf ("/sys/class/%s/%s/device/driver", subsystems[i], device_basename);
+ path = canonicalize_file_name (tmp);
+ g_free (tmp);
+
+ if (g_file_test (path, G_FILE_TEST_EXISTS))
+ driver = g_path_get_basename (path);
+ g_free (path);
+ }
+
+ g_free (device_basename);
+
+ return driver;
+}
+
+/*****************************************************************************/
+
static volatile gint __traces_enabled = FALSE;
/**
diff --git a/src/libqmi-glib/qmi-utils.h b/src/libqmi-glib/qmi-utils.h
index 69bf132..c03bd89 100644
--- a/src/libqmi-glib/qmi-utils.h
+++ b/src/libqmi-glib/qmi-utils.h
@@ -18,8 +18,8 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
- * Copyright (C) 2012-2015 Aleksander Morgado <aleksander@aleksander.es>
* Copyright (C) 2012-2015 Dan Williams <dcbw@redhat.com>
+ * Copyright (C) 2012-2017 Aleksander Morgado <aleksander@aleksander.es>
*/
#ifndef _LIBQMI_GLIB_QMI_UTILS_H_
@@ -199,6 +199,8 @@ gchar *__qmi_utils_str_hex (gconstpointer mem,
G_GNUC_INTERNAL
gboolean __qmi_user_allowed (uid_t uid,
GError **error);
+G_GNUC_INTERNAL
+gchar *__qmi_utils_get_driver (const gchar *cdc_wdm_path);
#endif
G_END_DECLS