[PATCH 2/2] Added WDS Bind Mux Data Port message

Carlo Lobrano c.lobrano at gmail.com
Wed Feb 15 14:44:03 UTC 2017


This message is used to bind a muxed data port to a controller device.
The Muxed data port has to be managed by qmi_wwan driver.

The Muxed data port is identified by:
- mux_id: the numeric ID given to qmi_wwan once created
- interface number: the interface number of the qmi controller device on
  the modem

Once the binding is completed, all the commands sent (and I expect also
received, but I could not test it) using the same Client ID are for the
binded data port instead of the real one.
---
 data/qmi-service-wds.json       |  34 ++++++++-
 src/libqmi-glib/qmi-enums-wds.h |  19 +++++
 src/libqmi-glib/qmi-enums.h     |  10 ++-
 src/qmicli/qmicli-wds.c         | 155 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 215 insertions(+), 3 deletions(-)

diff --git a/data/qmi-service-wds.json b/data/qmi-service-wds.json
index dc29998..d037481 100644
--- a/data/qmi-service-wds.json
+++ b/data/qmi-service-wds.json
@@ -1707,6 +1707,38 @@
                                                           "format"        : "guint32" },
                                                         { "name"          : "APN",
                                                           "format"        : "string" } ] },
-                     "prerequisites": [ { "common-ref" : "Success" } ] } ] }
+                     "prerequisites": [ { "common-ref" : "Success" } ] } ] },
 
+// *********************************************************************************
+    {   "name"    : "Bind Mux Data Port",
+        "type"    : "Message",
+        "service" : "WDS",
+        "id"      : "0x00A2",
+        "since"   : "1.18",
+        "input"   : [ { "name"          : "Endpoint Info",
+                        "id"            : "0x10",
+                        "mandatory"     : "no",
+                        "type"          : "TLV",
+                        "since"         : "1.18",
+                        "format"        : "sequence",
+                        "contents"  : [ { "name" : "Endpoint Type",
+                                          "format" : "guint32",
+                                          "public-format" : "QmiDataEndpointType"},
+                                        { "name" : "Interface Number",
+                                          "format" : "guint32" }]},
+                      { "name"          : "Mux ID",
+                        "id"            : "0x11",
+                        "type"          : "TLV",
+                        "since"         : "1.18",
+                        "mandatory"     : "no",
+                        "format"        : "guint8"},
+                      { "name"          : "Client Type",
+                        "id"            : "0x13",
+                        "type"          : "TLV",
+                        "since"         : "1.18",
+                        "mandatory"     : "no",
+                        "format"        : "guint32",
+                        "public-format" : "QmiWdsClientType"}
+                      ],
+        "output"  : [ { "common-ref" : "Operation Result" } ] }
 ]
diff --git a/src/libqmi-glib/qmi-enums-wds.h b/src/libqmi-glib/qmi-enums-wds.h
index 49edb82..e3bd6e2 100644
--- a/src/libqmi-glib/qmi-enums-wds.h
+++ b/src/libqmi-glib/qmi-enums-wds.h
@@ -1904,4 +1904,23 @@ typedef enum { /*< underscore_name=qmi_wds_qos_class_identifier >*/
  * Since: 1.18
  */
 
+/**
+ * QmiWdsClientType:
+ * @QMI_CLIENT_TYPE_UNDEFINED: no client type defined
+ * @WDS_CLIENT_TYPE_TETHERED: client type tethered
+ *
+ * Client Type
+ *
+ * Since: 1.18
+ */
+typedef enum { /*< underscore_name=qmi_wds_client_type > */
+    WDS_CLIENT_TYPE_TETHERED = 0x01,
+    WDS_CLIENT_TYPE_UNDEFINED = 0xFF,
+} QmiWdsClientType;
+
+/**
+ * qmi_wds_client_type_get_string:
+ *
+ * Since: 1.18
+ */
 #endif /* _LIBQMI_GLIB_QMI_ENUMS_WDS_H_ */
diff --git a/src/libqmi-glib/qmi-enums.h b/src/libqmi-glib/qmi-enums.h
index 77ee5c3..bda2aed 100644
--- a/src/libqmi-glib/qmi-enums.h
+++ b/src/libqmi-glib/qmi-enums.h
@@ -151,11 +151,17 @@ typedef enum {
  * @QMI_DATA_EP_TYPE_HSUSB: Data Endpoint Type HSUSB.
  *
  * Data Endpoint Type.
+ *
+ * Since: 1.18
  */
-typedef enum {
+typedef enum { /*< underscore_name=qmi_data_endpoint_type > */
     QMI_DATA_EP_TYPE_HSUSB     = 0X02,
     QMI_DATA_EP_TYPE_UNDEFINED = 0XFF,
 } QmiDataEndpointType;
 
-
+/**
+ * qmi_data_endpoint_type_get_string:
+ *
+ * Since: 1.18
+ */
 #endif /* _LIBQMI_GLIB_QMI_ENUMS_H_ */
diff --git a/src/qmicli/qmicli-wds.c b/src/qmicli/qmicli-wds.c
index 224cb7c..add736e 100644
--- a/src/qmicli/qmicli-wds.c
+++ b/src/qmicli/qmicli-wds.c
@@ -35,6 +35,9 @@
 #include "qmicli.h"
 #include "qmicli-helpers.h"
 
+#define QMI_WDS_MUX_ID_UNDEFINED 0xFF
+#define QMI_WDS_ENDPOINT_INTERFACE_NUMBER_UNDEFINED -1
+
 /* Context */
 typedef struct {
     QmiDevice *device;
@@ -68,6 +71,7 @@ static gchar *set_autoconnect_settings_str;
 static gboolean get_supported_messages_flag;
 static gboolean reset_flag;
 static gboolean noop_flag;
+static gchar *bind_mux_str;
 
 static GOptionEntry entries[] = {
     { "wds-start-network", 0, 0, G_OPTION_ARG_STRING, &start_network_str,
@@ -138,6 +142,10 @@ static GOptionEntry entries[] = {
       "Reset the service state",
       NULL
     },
+    { "wds-bind-mux-data-port", 0, 0, G_OPTION_ARG_STRING, &bind_mux_str,
+      "Bind qmux data port to controller device (allowed keys: mux-id, ep-iface-number) to be used with `--client-no-release-cid'",
+      "[\"key=value,...\"]"
+    },
     { "wds-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
       "Just allocate or release a WDS client. Use with `--client-no-release-cid' and/or `--client-cid'",
       NULL
@@ -171,6 +179,7 @@ qmicli_wds_options_enabled (void)
 
     n_actions = (!!start_network_str +
                  !!stop_network_str +
+                 !!bind_mux_str +
                  get_current_settings_flag +
                  get_packet_service_status_flag +
                  get_packet_statistics_flag +
@@ -1552,6 +1561,136 @@ noop_cb (gpointer unused)
     return FALSE;
 }
 
+typedef struct {
+    guint32 mux_id;
+    guint8 ep_type;
+    guint32 ep_iface_number;
+    guint32 client_type;
+} BindMuxDataPortProperties;
+
+
+static gboolean
+bind_mux_data_port_properties_handle (const gchar *key,
+                                      const gchar *value,
+                                      GError     **error,
+                                      gpointer     user_data)
+{
+    BindMuxDataPortProperties *props = user_data;
+    if (!value || !value[0]) {
+        g_set_error (error,
+                     QMI_CORE_ERROR,
+                     QMI_CORE_ERROR_FAILED,
+                     "key '%s' requires a value",
+                     key);
+        return FALSE;
+    }
+
+    if (g_ascii_strcasecmp (key, "mux-id") == 0) {
+        props->mux_id = atoi(value);
+        return TRUE;
+    }
+
+    if (g_ascii_strcasecmp (key, "ep-iface-number") == 0) {
+        props->ep_iface_number = atoi(value);
+        return TRUE;
+    }
+
+    g_set_error (error,
+                 QMI_CORE_ERROR,
+                 QMI_CORE_ERROR_FAILED,
+                 "Unrecognized option '%s'",
+                 key);
+
+    return FALSE;
+}
+
+static QmiMessageWdsBindMuxDataPortInput *
+bind_mux_data_port_input_create (const gchar *str)
+{
+    QmiMessageWdsBindMuxDataPortInput *input = NULL;
+    GError *error = NULL;
+    BindMuxDataPortProperties props = {
+        .mux_id = QMI_WDS_MUX_ID_UNDEFINED,
+        .ep_type = QMI_DATA_EP_TYPE_HSUSB,
+        .ep_iface_number = QMI_WDS_ENDPOINT_INTERFACE_NUMBER_UNDEFINED,
+        .client_type = WDS_CLIENT_TYPE_TETHERED,
+    };
+
+    if (!str[0])
+        return NULL;
+
+    /* New key=value format */
+    if (strchr (str, '=')) {
+        if (!qmicli_parse_key_value_string (str,
+                                            &error,
+                                            bind_mux_data_port_properties_handle,
+                                            &props)) {
+            g_printerr ("error: could not parse input string '%s'\n", error->message);
+            g_error_free (error);
+            return NULL;
+        }
+    }
+
+
+    if ((props.mux_id == QMI_WDS_MUX_ID_UNDEFINED) ^
+        (props.ep_iface_number == QMI_WDS_ENDPOINT_INTERFACE_NUMBER_UNDEFINED)) {
+        g_printerr ("error: Mux ID and Endpoint Iface Number are both needed\n");
+        return NULL;
+    }
+
+    input = qmi_message_wds_bind_mux_data_port_input_new ();
+
+    if (!qmi_message_wds_bind_mux_data_port_input_set_endpoint_info (input, props.ep_type, props.ep_iface_number, &error)) {
+        g_printerr ("error: couldn't set endpoint info: '%s'\n", error->message);
+        goto error_out;
+    }
+
+    if (!qmi_message_wds_bind_mux_data_port_input_set_mux_id (input, props.mux_id, &error)) {
+        g_printerr ("error: couldn't set mux ID %d: '%s'\n", props.mux_id, error->message);
+        goto error_out;
+    }
+
+    if (!qmi_message_wds_bind_mux_data_port_input_set_client_type (input, props.client_type , &error)) {
+        g_printerr ("error: couldn't set client type: '%s'\n", error->message);
+        goto error_out;
+    }
+
+    return input;
+
+error_out:
+    if (error)
+        g_error_free (error);
+    qmi_message_wds_bind_mux_data_port_input_unref (input);
+    return NULL;
+}
+
+static void
+bind_mux_data_port_ready (QmiClientWds *client,
+                          GAsyncResult *res) {
+    QmiMessageWdsBindMuxDataPortOutput *output;
+    GError *error = NULL;
+    g_print ("[%s]\n", __FUNCTION__);
+
+    output = qmi_client_wds_bind_mux_data_port_finish (client, res, &error);
+    if (!output) {
+        g_printerr ("error: operation failed: %s\n", error->message);
+        g_error_free (error);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    if (!qmi_message_wds_bind_mux_data_port_output_get_result (output, &error)) {
+        g_printerr ("error: couldn't bind mux data port: %s\n", error->message);
+        g_error_free (error);
+        qmi_message_wds_bind_mux_data_port_output_unref (output);
+        operation_shutdown (FALSE);
+        return;
+    }
+
+    qmi_message_wds_bind_mux_data_port_output_unref (output);
+    operation_shutdown (TRUE);
+}
+
 void
 qmicli_wds_run (QmiDevice *device,
                 QmiClientWds *client,
@@ -1610,6 +1749,22 @@ qmicli_wds_run (QmiDevice *device,
         return;
     }
 
+    /* Request to bind mux port? */
+    if (bind_mux_str) {
+        QmiMessageWdsBindMuxDataPortInput *input;
+        g_print ("Bind mux data port");
+
+        input = bind_mux_data_port_input_create (bind_mux_str);
+
+        qmi_client_wds_bind_mux_data_port (client,
+                                           input,
+                                           10,
+                                           ctx->cancellable,
+                                           (GAsyncReadyCallback) bind_mux_data_port_ready,
+                                           NULL);
+        return;
+    }
+
     /* Request to get current settings? */
     if (get_current_settings_flag) {
         QmiMessageWdsGetCurrentSettingsInput *input;
-- 
2.7.4



More information about the ModemManager-devel mailing list