aboutsummaryrefslogtreecommitdiff
path: root/src/mm-port-probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-port-probe.c')
-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