aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Williams <dan@ioncontrol.co>2024-11-06 08:38:53 -0600
committerAleksander Morgado <aleksander@aleksander.es>2024-11-20 11:50:43 +0000
commited13e053cd42b5462cce56fd985b0bd0c87d6498 (patch)
treefe8ed4f621d2474d0aa1e04c78f15a112b619646 /src
parent1d43bb0dacb9019a7681ae80cd02a7f2959b11f0 (diff)
port-probe: fix custom init probing not having open AT port
Referenced commit broke custom init flows because the AT port was not opened when custom inits were run, which was the case before the commit landed. Rework probing flow to follow a step model like much of our other code, and ensure that the AT port is opened as part of the custom init flow. Fixes: 7937a89a37e941e9a77cddcce8226c316fe70821 port-probe: rework and consolidate port probe flow for AT/QCDM/QMI/MBIM Signed-off-by: Dan Williams <dan@ioncontrol.co>
Diffstat (limited to 'src')
-rw-r--r--src/mm-port-probe.c311
1 files changed, 197 insertions, 114 deletions
diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c
index a5d2207d..b7c51fd8 100644
--- a/src/mm-port-probe.c
+++ b/src/mm-port-probe.c
@@ -371,11 +371,28 @@ mm_port_probe_set_result_mbim (MMPortProbe *self,
/*****************************************************************************/
+typedef enum {
+ PROBE_STEP_FIRST,
+ PROBE_STEP_CUSTOM_INIT_OPEN_PORT,
+ PROBE_STEP_CUSTOM_INIT,
+ PROBE_STEP_AT_OPEN_PORT,
+ PROBE_STEP_AT,
+ PROBE_STEP_AT_VENDOR,
+ PROBE_STEP_AT_PRODUCT,
+ PROBE_STEP_AT_ICERA,
+ PROBE_STEP_AT_XMM,
+ PROBE_STEP_QCDM,
+ PROBE_STEP_QMI,
+ PROBE_STEP_MBIM,
+ PROBE_STEP_LAST
+} ProbeStep;
+
typedef struct {
/* ---- Generic task context ---- */
- guint32 flags;
- guint source_id;
+ guint32 flags;
+ guint source_id;
GCancellable *cancellable;
+ ProbeStep step;
/* ---- Serial probing specific context ---- */
@@ -395,7 +412,6 @@ typedef struct {
/* Number of times we tried to open the AT port */
guint at_open_tries;
/* Custom initialization setup */
- gboolean at_custom_init_run;
MMPortProbeAtCustomInit at_custom_init;
MMPortProbeAtCustomInitFinish at_custom_init_finish;
/* Custom commands to look for AT support */
@@ -422,8 +438,8 @@ typedef struct {
gboolean qcdm_required;
} PortProbeRunContext;
-static gboolean serial_probe_at (MMPortProbe *self);
-static void serial_probe_schedule (MMPortProbe *self);
+static gboolean serial_probe_at (MMPortProbe *self);
+static void serial_probe_step_next (MMPortProbe *self);
static void
clear_probe_serial_port (PortProbeRunContext *ctx)
@@ -491,8 +507,8 @@ qmi_port_close_ready (MMPortQmi *qmi_port,
mm_port_qmi_close_finish (qmi_port, res, NULL);
- /* Keep on */
- serial_probe_schedule (self);
+ /* Continue with remaining probings */
+ serial_probe_step_next (self);
}
static void
@@ -565,7 +581,7 @@ wdm_probe_qmi (MMPortProbe *self)
#else
/* If not compiled with QMI support, just assume we won't have any QMI port */
mm_port_probe_set_result_qmi (self, FALSE);
- serial_probe_schedule (self);
+ serial_probe_step_next (self);
#endif /* WITH_QMI */
return G_SOURCE_REMOVE;
@@ -580,8 +596,8 @@ mbim_port_close_ready (MMPortMbim *mbim_port,
{
mm_port_mbim_close_finish (mbim_port, res, NULL);
- /* Keep on */
- serial_probe_schedule (self);
+ /* Continue with remaining probings */
+ serial_probe_step_next (self);
}
static void
@@ -638,7 +654,7 @@ wdm_probe_mbim (MMPortProbe *self)
#else
/* If not compiled with MBIM support, just assume we won't have any MBIM port */
mm_port_probe_set_result_mbim (self, FALSE);
- serial_probe_schedule (self);
+ serial_probe_step_next (self);
#endif /* WITH_MBIM */
return G_SOURCE_REMOVE;
@@ -746,8 +762,9 @@ serial_probe_qcdm_parse_response (MMPortSerialQcdm *port,
/* Set probing result */
mm_port_probe_set_result_qcdm (self, is_qcdm);
- /* Reschedule probing */
- serial_probe_schedule (self);
+
+ /* Continue with remaining probings */
+ serial_probe_step_next (self);
}
static gboolean
@@ -782,8 +799,9 @@ serial_probe_qcdm (MMPortProbe *self)
self->priv->is_ignored = TRUE;
} else
mm_port_probe_set_result_qcdm (self, FALSE);
- /* Reschedule probing */
- serial_probe_schedule (self);
+
+ /* Continue with remaining probings */
+ serial_probe_step_next (self);
return G_SOURCE_REMOVE;
}
@@ -1012,7 +1030,7 @@ serial_probe_at_parse_response (MMPortSerialAt *port,
if (g_cancellable_is_cancelled (ctx->at_probing_cancellable)) {
mm_obj_dbg (self, "no need to keep on probing the port for AT support");
ctx->at_result_processor (self, NULL);
- serial_probe_schedule (self);
+ serial_probe_step_next (self);
return;
}
@@ -1042,8 +1060,7 @@ serial_probe_at_parse_response (MMPortSerialAt *port,
/* Was it the last command in the group? If so,
* end this partial probing */
ctx->at_result_processor (self, NULL);
- /* Reschedule */
- serial_probe_schedule (self);
+ serial_probe_step_next (self);
return;
}
@@ -1061,9 +1078,7 @@ serial_probe_at_parse_response (MMPortSerialAt *port,
/* Run result processor.
* Note that custom init commands are allowed to not return anything */
ctx->at_result_processor (self, result);
-
- /* Reschedule probing */
- serial_probe_schedule (self);
+ serial_probe_step_next (self);
}
static gboolean
@@ -1083,7 +1098,7 @@ serial_probe_at (MMPortProbe *self)
if (g_cancellable_is_cancelled (ctx->at_probing_cancellable)) {
mm_obj_dbg (self, "no need to launch probing for AT support");
ctx->at_result_processor (self, NULL);
- serial_probe_schedule (self);
+ serial_probe_step_next (self);
return G_SOURCE_REMOVE;
}
@@ -1151,9 +1166,8 @@ at_custom_init_ready (MMPortProbe *self,
return;
}
- /* Keep on with remaining probings */
- ctx->at_custom_init_run = TRUE;
- serial_probe_schedule (self);
+ /* Continue with remaining probings */
+ serial_probe_step_next (self);
}
/***************************************************************/
@@ -1165,8 +1179,8 @@ serial_flash_ready (MMPortSerial *port,
{
mm_port_serial_flash_finish (port, res, NULL);
- /* Schedule probing */
- serial_probe_schedule (self);
+ /* Continue with remaining probings */
+ serial_probe_step_next (self);
}
static void
@@ -1305,7 +1319,7 @@ serial_open_at (MMPortProbe *self)
}
static void
-serial_probe_schedule (MMPortProbe *self)
+serial_probe_step (MMPortProbe *self)
{
PortProbeRunContext *ctx;
@@ -1316,103 +1330,172 @@ serial_probe_schedule (MMPortProbe *self)
if (port_probe_task_return_error_if_cancelled (self))
return;
- /* If we got some custom initialization setup requested, go on with it
- * first. We completely ignore the custom initialization if the serial port
- * that we receive in the context isn't an AT port (e.g. if it was flagged
- * as not being an AT port early) */
- if (!ctx->at_custom_init_run &&
- ctx->at_custom_init &&
- ctx->at_custom_init_finish &&
- MM_IS_PORT_SERIAL_AT (ctx->serial)) {
- ctx->at_custom_init (self,
- MM_PORT_SERIAL_AT (ctx->serial),
- ctx->at_probing_cancellable,
- (GAsyncReadyCallback) at_custom_init_ready,
- NULL);
- return;
- }
-
- /* Cleanup */
+ /* Cleanup from previous iterations */
ctx->at_result_processor = NULL;
ctx->at_commands = NULL;
ctx->at_commands_wait_secs = 0;
- /* AT check requested and not already probed? */
- if ((ctx->flags & MM_PORT_PROBE_AT) &&
- !(self->priv->flags & MM_PORT_PROBE_AT)) {
- /* Prepare AT probing */
- if (ctx->at_custom_probe)
- ctx->at_commands = ctx->at_custom_probe;
- else
- ctx->at_commands = at_probing;
- ctx->at_result_processor = serial_probe_at_result_processor;
- }
- /* Vendor requested and not already probed? */
- else if ((ctx->flags & MM_PORT_PROBE_AT_VENDOR) &&
- !(self->priv->flags & MM_PORT_PROBE_AT_VENDOR)) {
- /* Prepare AT vendor probing */
- ctx->at_result_processor = serial_probe_at_vendor_result_processor;
- ctx->at_commands = vendor_probing;
- }
- /* Product requested and not already probed? */
- else if ((ctx->flags & MM_PORT_PROBE_AT_PRODUCT) &&
- !(self->priv->flags & MM_PORT_PROBE_AT_PRODUCT)) {
- /* Prepare AT product probing */
- ctx->at_result_processor = serial_probe_at_product_result_processor;
- ctx->at_commands = product_probing;
- }
- /* Icera support check requested and not already done? */
- else if ((ctx->flags & MM_PORT_PROBE_AT_ICERA) &&
- !(self->priv->flags & MM_PORT_PROBE_AT_ICERA)) {
- /* Prepare AT product probing */
- ctx->at_result_processor = serial_probe_at_icera_result_processor;
- ctx->at_commands = icera_probing;
- /* By default, wait 2 seconds between ICERA probing retries */
- ctx->at_commands_wait_secs = 2;
- }
- /* XMM support check requested and not already done? */
- else if ((ctx->flags & MM_PORT_PROBE_AT_XMM) &&
- !(self->priv->flags & MM_PORT_PROBE_AT_XMM)) {
- /* Prepare AT product probing */
- ctx->at_result_processor = serial_probe_at_xmm_result_processor;
- ctx->at_commands = xmm_probing;
- }
+ switch (ctx->step) {
+ case PROBE_STEP_FIRST:
+ mm_obj_msg (self, "probe step: start");
+ ctx->step++;
+ /* Fall through */
- /* If a next AT group detected, go for it */
- if (ctx->at_result_processor &&
- ctx->at_commands) {
- if (ctx->serial && !MM_IS_PORT_SERIAL_AT (ctx->serial))
- clear_probe_serial_port (ctx);
- if (!ctx->serial)
+ case PROBE_STEP_CUSTOM_INIT_OPEN_PORT:
+ if (ctx->at_custom_init && ctx->at_custom_init_finish) {
+ mm_obj_msg (self, "probe step: custom init open port");
+ ctx->source_id = g_idle_add ((GSourceFunc) serial_open_at, self);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_CUSTOM_INIT:
+ /* If we got some custom initialization setup requested, go on with it
+ * first. We completely ignore the custom initialization if the serial port
+ * that we receive in the context isn't an AT port (e.g. if it was flagged
+ * as not being an AT port early) */
+ if (ctx->at_custom_init && ctx->at_custom_init_finish) {
+ mm_obj_msg (self, "probe step: custom init run");
+ g_assert (MM_IS_PORT_SERIAL_AT (ctx->serial));
+ ctx->at_custom_init (self,
+ MM_PORT_SERIAL_AT (ctx->serial),
+ ctx->at_probing_cancellable,
+ (GAsyncReadyCallback) at_custom_init_ready,
+ NULL);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_AT_OPEN_PORT:
+ if ((ctx->flags & MM_PORT_PROBE_AT) && !(self->priv->flags & MM_PORT_PROBE_AT)) {
+ mm_obj_msg (self, "probe step: AT open port");
+ /* We might end up back here after later probe types fail, so make
+ * sure we have a usable AT port.
+ */
+ if (ctx->serial && !MM_IS_PORT_SERIAL_AT (ctx->serial))
+ clear_probe_serial_port (ctx);
ctx->source_id = g_idle_add ((GSourceFunc) serial_open_at, self);
- else
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_AT:
+ if ((ctx->flags & MM_PORT_PROBE_AT) && !(self->priv->flags & MM_PORT_PROBE_AT)) {
+ mm_obj_msg (self, "probe step: AT");
+ /* Prepare AT probing */
+ ctx->at_commands = ctx->at_custom_probe ? ctx->at_custom_probe : at_probing;
+ ctx->at_result_processor = serial_probe_at_result_processor;
ctx->source_id = g_idle_add ((GSourceFunc) serial_probe_at, self);
- return;
- }
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_AT_VENDOR:
+ /* Vendor requested and not already probed? */
+ if ((ctx->flags & MM_PORT_PROBE_AT_VENDOR) && !(self->priv->flags & MM_PORT_PROBE_AT_VENDOR)) {
+ mm_obj_msg (self, "probe step: AT vendor");
+ ctx->at_result_processor = serial_probe_at_vendor_result_processor;
+ ctx->at_commands = vendor_probing;
+ ctx->source_id = g_idle_add ((GSourceFunc) serial_probe_at, self);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_AT_PRODUCT:
+ /* Product requested and not already probed? */
+ if ((ctx->flags & MM_PORT_PROBE_AT_PRODUCT) && !(self->priv->flags & MM_PORT_PROBE_AT_PRODUCT)) {
+ mm_obj_msg (self, "probe step: AT product");
+ ctx->at_result_processor = serial_probe_at_product_result_processor;
+ ctx->at_commands = product_probing;
+ ctx->source_id = g_idle_add ((GSourceFunc) serial_probe_at, self);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_AT_ICERA:
+ /* Icera support check requested and not already done? */
+ if ((ctx->flags & MM_PORT_PROBE_AT_ICERA) && !(self->priv->flags & MM_PORT_PROBE_AT_ICERA)) {
+ mm_obj_msg (self, "probe step: Icera");
+ ctx->at_result_processor = serial_probe_at_icera_result_processor;
+ ctx->at_commands = icera_probing;
+ /* By default, wait 2 seconds between ICERA probing retries */
+ ctx->at_commands_wait_secs = 2;
+ ctx->source_id = g_idle_add ((GSourceFunc) serial_probe_at, self);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_AT_XMM:
+ /* XMM support check requested and not already done? */
+ if ((ctx->flags & MM_PORT_PROBE_AT_XMM) && !(self->priv->flags & MM_PORT_PROBE_AT_XMM)) {
+ mm_obj_msg (self, "probe step: XMM");
+ /* Prepare AT product probing */
+ ctx->at_result_processor = serial_probe_at_xmm_result_processor;
+ ctx->at_commands = xmm_probing;
+ ctx->source_id = g_idle_add ((GSourceFunc) serial_probe_at, self);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_QCDM:
+ /* QCDM requested and not already probed? */
+ if ((ctx->flags & MM_PORT_PROBE_QCDM) && !(self->priv->flags & MM_PORT_PROBE_QCDM)) {
+ mm_obj_msg (self, "probe step: QCDM");
+ ctx->source_id = g_idle_add ((GSourceFunc) serial_probe_qcdm, self);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_QMI:
+ /* QMI probing needed? */
+ if ((ctx->flags & MM_PORT_PROBE_QMI) && !(self->priv->flags & MM_PORT_PROBE_QMI)) {
+ mm_obj_msg (self, "probe step: QMI");
+ ctx->source_id = g_idle_add ((GSourceFunc) wdm_probe_qmi, self);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
+
+ case PROBE_STEP_MBIM:
+ /* MBIM probing needed */
+ if ((ctx->flags & MM_PORT_PROBE_MBIM) && !(self->priv->flags & MM_PORT_PROBE_MBIM)) {
+ mm_obj_msg (self, "probe step: MBIM");
+ ctx->source_id = g_idle_add ((GSourceFunc) wdm_probe_mbim, self);
+ return;
+ }
+ ctx->step++;
+ /* Fall through */
- /* QCDM requested and not already probed? */
- if ((ctx->flags & MM_PORT_PROBE_QCDM) &&
- !(self->priv->flags & MM_PORT_PROBE_QCDM)) {
- ctx->source_id = g_idle_add ((GSourceFunc) serial_probe_qcdm, self);
+ case PROBE_STEP_LAST:
+ /* All done! */
+ mm_obj_msg (self, "probe step: done");
+ port_probe_task_return_boolean (self, TRUE);
return;
- }
- /* QMI probing needed? */
- if ((ctx->flags & MM_PORT_PROBE_QMI) &&
- !(self->priv->flags & MM_PORT_PROBE_QMI)) {
- ctx->source_id = g_idle_add ((GSourceFunc) wdm_probe_qmi, self);
- return;
+ default:
+ g_assert_not_reached ();
}
+}
- /* MBIM probing needed */
- if ((ctx->flags & MM_PORT_PROBE_MBIM) &&
- !(self->priv->flags & MM_PORT_PROBE_MBIM)) {
- ctx->source_id = g_idle_add ((GSourceFunc) wdm_probe_mbim, self);
- return;
- }
+static void
+serial_probe_step_next (MMPortProbe *self)
+{
+ PortProbeRunContext *ctx;
+
+ g_assert (self->priv->task);
+ ctx = g_task_get_task_data (self->priv->task);
- /* All done! */
- port_probe_task_return_boolean (self, TRUE);
+ ctx->step++;
+ serial_probe_step (self);
}
static void
@@ -1481,6 +1564,7 @@ mm_port_probe_run (MMPortProbe *self,
/* Task context */
ctx = g_slice_new0 (PortProbeRunContext);
+ ctx->step = PROBE_STEP_FIRST;
ctx->at_send_delay = at_send_delay;
ctx->at_remove_echo = at_remove_echo;
ctx->at_send_lf = at_send_lf;
@@ -1580,7 +1664,6 @@ mm_port_probe_run (MMPortProbe *self,
mm_obj_dbg (self, "launching port probing: '%s'", probe_list_str);
g_free (probe_list_str);
- /* If any AT probing is needed, start by opening as AT port */
if (ctx->flags & MM_PORT_PROBE_AT ||
ctx->flags & MM_PORT_PROBE_AT_VENDOR ||
ctx->flags & MM_PORT_PROBE_AT_PRODUCT ||
@@ -1595,7 +1678,7 @@ mm_port_probe_run (MMPortProbe *self,
NULL);
}
- serial_probe_schedule (self);
+ serial_probe_step (self);
}
gboolean