diff options
author | Stephan Gerhold <stephan.gerhold@kernkonzept.com> | 2022-08-03 14:59:34 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2022-08-18 13:13:25 +0000 |
commit | 8b8b5c22f7e6498e12a5319ae95a5edb18bd8fdb (patch) | |
tree | 01bb34f68965162ea8cf443142c3f1382fa4e9e9 | |
parent | 5cc34d5f86bad12382d97e1daea894d8666a527d (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.c | 18 |
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); |