summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlo Lobrano <c.lobrano@gmail.com>2017-02-21 16:04:01 +0100
committerAleksander Morgado <aleksander@aleksander.es>2017-02-28 23:40:52 +0100
commit041f022ff81e72aea748e5b01824ce2de1354ae7 (patch)
tree742d3e6a87d4f9af20e9205f391fc2a5fb1f0aef
parenta04525d9e167a44b8295af922114d34062e9feaf (diff)
wds: added WDS Bind Mux Data Port message
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.
-rw-r--r--data/qmi-service-wds.json34
-rw-r--r--src/libqmi-glib/qmi-enums-wds.h19
-rw-r--r--src/qmicli/qmicli-completion4
-rw-r--r--src/qmicli/qmicli-wds.c157
4 files changed, 213 insertions, 1 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..6f75812 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_WDS_CLIENT_TYPE_TETHERED: client type tethered
+ * @QMI_WDS_CLIENT_TYPE_UNDEFINED: no client type defined
+ *
+ * Client Type
+ *
+ * Since: 1.18
+ */
+typedef enum { /*< underscore_name=qmi_wds_client_type > */
+ QMI_WDS_CLIENT_TYPE_TETHERED = 0x01,
+ QMI_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/qmicli/qmicli-completion b/src/qmicli/qmicli-completion
index f35927f..1a1b4b5 100644
--- a/src/qmicli/qmicli-completion
+++ b/src/qmicli/qmicli-completion
@@ -114,6 +114,10 @@ _qmicli()
COMPREPLY=( $(compgen -W "[3gpp|3gpp2]" -- $cur) )
return 0
;;
+ '--wds-bind-mux-data-port')
+ COMPREPLY=( $(compgen -W "[(MuxId),(Ep-Iface-Number)]" -- $cur) )
+ return 0
+ ;;
'--uim-read-transparent')
COMPREPLY=( $(compgen -W "[0xNNNN,0xNNNN,...]" -- $cur) )
return 0
diff --git a/src/qmicli/qmicli-wds.c b/src/qmicli/qmicli-wds.c
index 224cb7c..75d7992 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,137 @@ 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_ENDPOINT_TYPE_HSUSB,
+ .ep_iface_number = QMI_WDS_ENDPOINT_INTERFACE_NUMBER_UNDEFINED,
+ .client_type = QMI_WDS_CLIENT_TYPE_TETHERED,
+ };
+
+ if (!str[0])
+ return NULL;
+
+ 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;
+ }
+ } else {
+ g_printerr ("error: malformed input string, key=value format expected.\n");
+ goto error_out;
+ }
+
+
+ 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;
+
+ 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 +1750,23 @@ 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);
+ qmi_message_wds_bind_mux_data_port_input_unref (input);
+ return;
+ }
+
/* Request to get current settings? */
if (get_current_settings_flag) {
QmiMessageWdsGetCurrentSettingsInput *input;