aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Gerhold <stephan.gerhold@kernkonzept.com>2022-08-03 14:59:34 +0200
committerAleksander Morgado <aleksander@aleksander.es>2022-08-18 13:13:25 +0000
commit8b8b5c22f7e6498e12a5319ae95a5edb18bd8fdb (patch)
tree01bb34f68965162ea8cf443142c3f1382fa4e9e9
parent5cc34d5f86bad12382d97e1daea894d8666a527d (diff)
bearer-qmi: Add fallback for firmware with broken "Bind Data Port"
"Bind Data Port" does not work correctly on newer platforms with BAM-DMUX (e.g. MSM8909). It returns "device unsupported" even for valid SIO port numbers. As an alternative, it seems to be possible to use the newer "Bind *Mux* Data Port" instead. This works even when QMAP multiplexing is disabled (using WDA "Set Data Format"). In this case the mux-id seems to be entirely ignored and can be a dummy value such as MUX_ID_UNBOUND. Implement this by checking for the error code of "Bind Data Port" and fallback to "Bind Mux Data Port" instead. The important part in this case is that the endpoint type and interface number are set correctly. At the moment this works only for the "wwan0" interface because the endpoint information is currently maintained globally as part of the QMI control port instead of being handled separately per data/net port. Further refactoring is needed to enable multiplexing on these platforms.
-rw-r--r--src/mm-bearer-qmi.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index b0a86bc4..79433def 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -493,6 +493,7 @@ typedef struct {
MMPort *data;
MMPortQmi *qmi;
QmiSioPort sio_port;
+ gboolean sio_port_failed;
gint profile_id;
MMBearerIpMethod ip_method;
@@ -1363,6 +1364,15 @@ bind_data_port_ready (QmiClientWds *client,
output = qmi_client_wds_bind_data_port_finish (client, res, &error);
if (!output || !qmi_message_wds_bind_data_port_output_get_result (output, &error)) {
+ if (g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_DEVICE_UNSUPPORTED)) {
+ /* Some firmwares only support this through "Bind Mux Data Port",
+ * even if multiplexing is disabled. Try again with that. */
+ g_error_free (error);
+ ctx->sio_port_failed = TRUE;
+ connect_context_step (task);
+ return;
+ }
+
g_prefix_error (&error, "Couldn't bind data port: ");
complete_connect (task, NULL, error);
return;
@@ -1810,7 +1820,7 @@ connect_context_step (GTask *task)
case CONNECT_STEP_BIND_DATA_PORT_IPV4:
/* If SIO port given, bind client to it */
- if (ctx->sio_port != QMI_SIO_PORT_NONE) {
+ if (!ctx->sio_port_failed && ctx->sio_port != QMI_SIO_PORT_NONE) {
g_autoptr(QmiMessageWdsBindDataPortInput) input = NULL;
mm_obj_dbg (self, "binding to data port: %s", qmi_sio_port_get_string (ctx->sio_port));
@@ -1826,7 +1836,7 @@ connect_context_step (GTask *task)
}
/* If mux id given, bind mux data port */
- if (ctx->mux_id != QMI_DEVICE_MUX_ID_UNBOUND) {
+ if (ctx->sio_port_failed || ctx->mux_id != QMI_DEVICE_MUX_ID_UNBOUND) {
g_autoptr(QmiMessageWdsBindMuxDataPortInput) input = NULL;
mm_obj_dbg (self, "binding to mux id %d", ctx->mux_id);
@@ -1946,7 +1956,7 @@ connect_context_step (GTask *task)
case CONNECT_STEP_BIND_DATA_PORT_IPV6:
/* If SIO port given, bind client to it */
- if (ctx->sio_port != QMI_SIO_PORT_NONE) {
+ if (!ctx->sio_port_failed && ctx->sio_port != QMI_SIO_PORT_NONE) {
g_autoptr(QmiMessageWdsBindDataPortInput) input = NULL;
mm_obj_dbg (self, "binding to data port: %s", qmi_sio_port_get_string (ctx->sio_port));
@@ -1962,7 +1972,7 @@ connect_context_step (GTask *task)
}
/* If mux id given, bind mux data port */
- if (ctx->mux_id != QMI_DEVICE_MUX_ID_UNBOUND) {
+ if (ctx->sio_port_failed || ctx->mux_id != QMI_DEVICE_MUX_ID_UNBOUND) {
g_autoptr(QmiMessageWdsBindMuxDataPortInput) input = NULL;
mm_obj_dbg (self, "binding to mux id %d", ctx->mux_id);