diff options
author | Carlo Lobrano <c.lobrano@gmail.com> | 2017-02-21 16:04:01 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-02-28 23:40:52 +0100 |
commit | 041f022ff81e72aea748e5b01824ce2de1354ae7 (patch) | |
tree | 742d3e6a87d4f9af20e9205f391fc2a5fb1f0aef | |
parent | a04525d9e167a44b8295af922114d34062e9feaf (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.json | 34 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-enums-wds.h | 19 | ||||
-rw-r--r-- | src/qmicli/qmicli-completion | 4 | ||||
-rw-r--r-- | src/qmicli/qmicli-wds.c | 157 |
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; |