diff options
-rw-r--r-- | src/mm-port-probe.c | 311 |
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 |