diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-01-23 21:24:59 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-02-08 18:49:21 +0100 |
commit | 830b6326404e59fb2d4b5733f57c7f1d9fb6e930 (patch) | |
tree | 212cee2ccc5a0af2e6aab7e7d713d16b69bf4583 /src | |
parent | fad2ca074e44cf9dd340e9609ff30c047a5ecc0b (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.c | 52 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-device.h | 6 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-utils.c | 40 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-utils.h | 4 |
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 |