<div dir="ltr">LGTM, for syntax & control flow. Like the idea but I'm biased on this one ;)</div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, May 21, 2017 at 1:49 PM, Aleksander Morgado <span dir="ltr"><<a href="mailto:aleksander@aleksander.es" target="_blank">aleksander@aleksander.es</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Plugins have two ways to update signal quality and access technology<br>
values: via unsolicited messages or via polling periodically.<br>
<br>
Instead of keeping separate contexts for polling signal quality and<br>
access technology values, we setup a common timeout to trigger<br>
both. This allows us to simplify in which case the explicit update is<br>
required, whenever one is needed to be explicitly updated, the other<br>
one should also be.<br>
<br>
The logic now also allows plugins to return an UNSUPPORTED error in<br>
either load_signal_quality() and/or load_access_technologies() to tell<br>
the interface logic that the polling of the specific item shouldn't be<br>
performed (e.g. if the updates are expected via unsolicited messages).<br>
<br>
If both signal quality and access technology polling is flagged as<br>
disabled, we totally disable the polling logic internally.<br>
<br>
The new SignalCheckContext is bound to the lifetime of the object so<br>
that we can keep the value of the supported flags until the object is<br>
destroyed.<br>
---<br>
plugins/cinterion/mm-<wbr>broadband-modem-cinterion.c | 8 +-<br>
src/mm-iface-modem-3gpp.c | 7 +-<br>
src/mm-iface-modem.c | 587 ++++++++++++-----------<br>
src/mm-iface-modem.h | 6 +-<br>
4 files changed, 310 insertions(+), 298 deletions(-)<br>
<br>
diff --git a/plugins/cinterion/mm-<wbr>broadband-modem-cinterion.c b/plugins/cinterion/mm-<wbr>broadband-modem-cinterion.c<br>
index 1509debf..3037ee9a 100644<br>
--- a/plugins/cinterion/mm-<wbr>broadband-modem-cinterion.c<br>
+++ b/plugins/cinterion/mm-<wbr>broadband-modem-cinterion.c<br>
@@ -850,8 +850,8 @@ allowed_access_technology_<wbr>update_ready (MMBroadbandModemCinterion *self,<br>
/* Let the error be critical. */<br>
g_simple_async_result_take_<wbr>error (operation_result, error);<br>
else {<br>
- /* Request immediate access tech update */<br>
- mm_iface_modem_refresh_access_<wbr>technologies (MM_IFACE_MODEM (self));<br>
+ /* Request immediate signal update */<br>
+ mm_iface_modem_refresh_signal (MM_IFACE_MODEM (self));<br>
g_simple_async_result_set_op_<wbr>res_gboolean (operation_result, TRUE);<br>
}<br>
g_simple_async_result_complete (operation_result);<br>
@@ -1148,8 +1148,8 @@ scfg_set_ready (MMBaseModem *self,<br>
/* Let the error be critical */<br>
g_simple_async_result_take_<wbr>error (operation_result, error);<br>
else {<br>
- /* Request immediate access tech update */<br>
- mm_iface_modem_refresh_access_<wbr>technologies (MM_IFACE_MODEM (self));<br>
+ /* Request immediate signal update */<br>
+ mm_iface_modem_refresh_signal (MM_IFACE_MODEM (self));<br>
g_simple_async_result_set_op_<wbr>res_gboolean (operation_result, TRUE);<br>
}<br>
<br>
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c<br>
index 8b93550a..bcd12e85 100644<br>
--- a/src/mm-iface-modem-3gpp.c<br>
+++ b/src/mm-iface-modem-3gpp.c<br>
@@ -307,8 +307,11 @@ run_registration_checks_ready (MMIfaceModem3gpp *self,<br>
current_registration_state == MM_MODEM_3GPP_REGISTRATION_<wbr>STATE_ROAMING_SMS_ONLY ||<br>
current_registration_state == MM_MODEM_3GPP_REGISTRATION_<wbr>STATE_HOME_CSFB_NOT_PREFERRED ||<br>
current_registration_state == MM_MODEM_3GPP_REGISTRATION_<wbr>STATE_ROAMING_CSFB_NOT_<wbr>PREFERRED) {<br>
- /* Request immediate access tech update */<br>
- mm_iface_modem_refresh_access_<wbr>technologies (MM_IFACE_MODEM (ctx->self));<br>
+ /* Request immediate access tech and signal update: we may have changed<br>
+ * from home to roaming or viceversa, both registered states, so there<br>
+ * wouldn't be an explicit refresh triggered from the modem interface as<br>
+ * the modem never got un-registered during the sequence. */<br>
+ mm_iface_modem_refresh_signal (MM_IFACE_MODEM (ctx->self));<br>
mm_dbg ("Modem is currently registered in a 3GPP network");<br>
g_simple_async_result_set_op_<wbr>res_gboolean (ctx->result, TRUE);<br>
register_in_network_context_<wbr>complete_and_free (ctx);<br>
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c<br>
index ecb351a0..bbf0fdc4 100644<br>
--- a/src/mm-iface-modem.c<br>
+++ b/src/mm-iface-modem.c<br>
@@ -29,21 +29,20 @@<br>
#include "mm-log.h"<br>
#include "mm-context.h"<br>
<br>
-#define SIGNAL_QUALITY_RECENT_TIMEOUT_<wbr>SEC 60<br>
-#define SIGNAL_QUALITY_INITIAL_CHECK_<wbr>TIMEOUT_SEC 3<br>
-#define SIGNAL_QUALITY_CHECK_TIMEOUT_<wbr>SEC 30<br>
-#define ACCESS_TECHNOLOGIES_CHECK_<wbr>TIMEOUT_SEC 30<br>
+#define SIGNAL_QUALITY_RECENT_TIMEOUT_<wbr>SEC 60<br>
<br>
-#define STATE_UPDATE_CONTEXT_TAG "state-update-context-tag"<br>
-#define SIGNAL_QUALITY_UPDATE_CONTEXT_<wbr>TAG "signal-quality-update-<wbr>context-tag"<br>
-#define SIGNAL_QUALITY_CHECK_CONTEXT_<wbr>TAG "signal-quality-check-context-<wbr>tag"<br>
-#define ACCESS_TECHNOLOGIES_CHECK_<wbr>CONTEXT_TAG "access-technologies-check-<wbr>context-tag"<br>
-#define RESTART_INITIALIZE_IDLE_TAG "restart-initialize-tag"<br>
+#define SIGNAL_CHECK_INITIAL_RETRIES 5<br>
+#define SIGNAL_CHECK_INITIAL_TIMEOUT_<wbr>SEC 3<br>
+#define SIGNAL_CHECK_TIMEOUT_SEC 30<br>
+<br>
+#define STATE_UPDATE_CONTEXT_TAG "state-update-context-tag"<br>
+#define SIGNAL_QUALITY_UPDATE_CONTEXT_<wbr>TAG "signal-quality-update-<wbr>context-tag"<br>
+#define SIGNAL_CHECK_CONTEXT_TAG "signal-check-context-tag"<br>
+#define RESTART_INITIALIZE_IDLE_TAG "restart-initialize-tag"<br>
<br>
static GQuark state_update_context_quark;<br>
static GQuark signal_quality_update_context_<wbr>quark;<br>
-static GQuark signal_quality_check_context_<wbr>quark;<br>
-static GQuark access_technologies_check_<wbr>context_quark;<br>
+static GQuark signal_check_context_quark;<br>
static GQuark restart_initialize_idle_quark;<br>
<br>
/*****************************<wbr>******************************<wbr>******************/<br>
@@ -943,152 +942,6 @@ mm_iface_modem_update_access_<wbr>technologies (MMIfaceModem *self,<br>
/*****************************<wbr>******************************<wbr>******************/<br>
<br>
typedef struct {<br>
- guint timeout_source;<br>
- gboolean running;<br>
-} AccessTechnologiesCheckContext<wbr>;<br>
-<br>
-static void<br>
-access_technologies_check_<wbr>context_free (<wbr>AccessTechnologiesCheckContext *ctx)<br>
-{<br>
- if (ctx->timeout_source)<br>
- g_source_remove (ctx->timeout_source);<br>
- g_free (ctx);<br>
-}<br>
-<br>
-static void<br>
-access_technologies_check_<wbr>ready (MMIfaceModem *self,<br>
- GAsyncResult *res)<br>
-{<br>
- GError *error = NULL;<br>
- MMModemAccessTechnology access_technologies = MM_MODEM_ACCESS_TECHNOLOGY_<wbr>UNKNOWN;<br>
- guint mask = MM_MODEM_ACCESS_TECHNOLOGY_<wbr>ANY;<br>
- AccessTechnologiesCheckContext *ctx;<br>
-<br>
- if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_<wbr>technologies_finish (<br>
- self,<br>
- res,<br>
- &access_technologies,<br>
- &mask,<br>
- &error)) {<br>
- /* Ignore issues when the operation is unsupported, don't even log */<br>
- if (!g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED))<br>
- mm_dbg ("Couldn't refresh access technologies: '%s'", error->message);<br>
- g_error_free (error);<br>
- } else<br>
- mm_iface_modem_update_access_<wbr>technologies (self, access_technologies, mask);<br>
-<br>
- /* Remove the running tag. Note that the context may have been removed by<br>
- * mm_iface_modem_shutdown when this function is invoked as a callback of<br>
- * load_access_technologies. */<br>
- ctx = g_object_get_qdata (G_OBJECT (self), access_technologies_check_<wbr>context_quark);<br>
- if (ctx)<br>
- ctx->running = FALSE;<br>
-}<br>
-<br>
-static gboolean<br>
-periodic_access_technologies_<wbr>check (MMIfaceModem *self)<br>
-{<br>
- AccessTechnologiesCheckContext *ctx;<br>
-<br>
- ctx = g_object_get_qdata (G_OBJECT (self), access_technologies_check_<wbr>context_quark);<br>
-<br>
- /* Only launch a new one if not one running already OR if the last one run<br>
- * was more than 15s ago. */<br>
- if (!ctx->running) {<br>
- ctx->running = TRUE;<br>
- MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_<wbr>technologies (<br>
- self,<br>
- (GAsyncReadyCallback)access_<wbr>technologies_check_ready,<br>
- NULL);<br>
- }<br>
-<br>
- return G_SOURCE_CONTINUE;<br>
-}<br>
-<br>
-void<br>
-mm_iface_modem_refresh_<wbr>access_technologies (MMIfaceModem *self)<br>
-{<br>
- AccessTechnologiesCheckContext *ctx;<br>
-<br>
- if (G_UNLIKELY (!access_technologies_check_<wbr>context_quark))<br>
- access_technologies_check_<wbr>context_quark = (g_quark_from_static_string (<br>
- ACCESS_TECHNOLOGIES_CHECK_<wbr>CONTEXT_TAG));<br>
-<br>
- ctx = g_object_get_qdata (G_OBJECT (self), access_technologies_check_<wbr>context_quark);<br>
- if (!ctx)<br>
- return;<br>
-<br>
- /* Re-set timeout */<br>
- if (ctx->timeout_source)<br>
- g_source_remove (ctx->timeout_source);<br>
- ctx->timeout_source = g_timeout_add_seconds (ACCESS_TECHNOLOGIES_CHECK_<wbr>TIMEOUT_SEC,<br>
- (GSourceFunc)periodic_access_<wbr>technologies_check,<br>
- self);<br>
-<br>
- /* Get first access technology value */<br>
- periodic_access_technologies_<wbr>check (self);<br>
-}<br>
-<br>
-static void<br>
-periodic_access_technologies_<wbr>check_disable (MMIfaceModem *self)<br>
-{<br>
- if (G_UNLIKELY (!access_technologies_check_<wbr>context_quark))<br>
- access_technologies_check_<wbr>context_quark = (g_quark_from_static_string (<br>
- ACCESS_TECHNOLOGIES_CHECK_<wbr>CONTEXT_TAG));<br>
-<br>
- /* Clear access technology */<br>
- mm_iface_modem_update_access_<wbr>technologies (self,<br>
- MM_MODEM_ACCESS_TECHNOLOGY_<wbr>UNKNOWN,<br>
- MM_MODEM_ACCESS_TECHNOLOGY_<wbr>ANY);<br>
-<br>
- /* Overwriting the data will free the previous context */<br>
- g_object_set_qdata (G_OBJECT (self),<br>
- access_technologies_check_<wbr>context_quark,<br>
- NULL);<br>
-<br>
- mm_dbg ("Periodic access technology checks disabled");<br>
-}<br>
-<br>
-static void<br>
-periodic_access_technologies_<wbr>check_enable (MMIfaceModem *self)<br>
-{<br>
- AccessTechnologiesCheckContext *ctx;<br>
-<br>
- if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_<wbr>technologies ||<br>
- !MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_<wbr>technologies_finish) {<br>
- /* If loading access technology not supported, don't even bother setting up<br>
- * a timeout */<br>
- return;<br>
- }<br>
-<br>
- if (G_UNLIKELY (!access_technologies_check_<wbr>context_quark))<br>
- access_technologies_check_<wbr>context_quark = (g_quark_from_static_string (<br>
- ACCESS_TECHNOLOGIES_CHECK_<wbr>CONTEXT_TAG));<br>
-<br>
- ctx = g_object_get_qdata (G_OBJECT (self), access_technologies_check_<wbr>context_quark);<br>
-<br>
- /* If context is already there, we're already enabled */<br>
- if (ctx) {<br>
- periodic_access_technologies_<wbr>check (self);<br>
- return;<br>
- }<br>
-<br>
- /* Create context and keep it as object data */<br>
- mm_dbg ("Periodic access technology checks enabled");<br>
- ctx = g_new0 (<wbr>AccessTechnologiesCheckContext<wbr>, 1);<br>
- g_object_set_qdata_full (G_OBJECT (self),<br>
- access_technologies_check_<wbr>context_quark,<br>
- ctx,<br>
- (GDestroyNotify)access_<wbr>technologies_check_context_<wbr>free);<br>
-<br>
- /* Get first and setup timeout */<br>
- mm_iface_modem_refresh_access_<wbr>technologies (self);<br>
-}<br>
-<br>
-/****************************<wbr>******************************<wbr>*******************/<br>
-<br>
-typedef struct {<br>
- time_t last_update;<br>
guint recent_timeout_source;<br>
} SignalQualityUpdateContext;<br>
<br>
@@ -1100,20 +953,6 @@ signal_quality_update_context_<wbr>free (SignalQualityUpdateContext *ctx)<br>
g_free (ctx);<br>
}<br>
<br>
-static time_t<br>
-get_last_signal_quality_<wbr>update_time (MMIfaceModem *self)<br>
-{<br>
- SignalQualityUpdateContext *ctx;<br>
-<br>
- if (G_UNLIKELY (!signal_quality_update_<wbr>context_quark))<br>
- signal_quality_update_context_<wbr>quark = (g_quark_from_static_string (<br>
- SIGNAL_QUALITY_UPDATE_CONTEXT_<wbr>TAG));<br>
-<br>
- ctx = g_object_get_qdata (G_OBJECT (self), signal_quality_update_context_<wbr>quark);<br>
-<br>
- return (ctx ? ctx->last_update : 0);<br>
-}<br>
-<br>
static gboolean<br>
expire_signal_quality (MMIfaceModem *self)<br>
{<br>
@@ -1187,9 +1026,6 @@ update_signal_quality (MMIfaceModem *self,<br>
(GDestroyNotify)signal_<wbr>quality_update_context_free);<br>
}<br>
<br>
- /* Keep current timestamp */<br>
- ctx->last_update = time (NULL);<br>
-<br>
/* Note: we always set the new value, even if the signal quality level<br>
* is the same, in order to provide an up to date 'recent' flag.<br>
* The only exception being if 'expire' is FALSE; in that case we assume<br>
@@ -1229,142 +1065,334 @@ mm_iface_modem_update_signal_<wbr>quality (MMIfaceModem *self,<br>
}<br>
<br>
/*****************************<wbr>******************************<wbr>******************/<br>
+/* Signal info (quality and access technology) polling */<br>
+<br>
+typedef enum {<br>
+ SIGNAL_CHECK_STEP_NONE,<br>
+ SIGNAL_CHECK_STEP_FIRST,<br>
+ SIGNAL_CHECK_STEP_SIGNAL_<wbr>QUALITY,<br>
+ SIGNAL_CHECK_STEP_ACCESS_<wbr>TECHNOLOGIES,<br>
+ SIGNAL_CHECK_STEP_LAST,<br>
+} SignalCheckStep;<br>
<br>
typedef struct {<br>
- guint interval;<br>
- guint initial_retries;<br>
- guint timeout_source;<br>
- gboolean running;<br>
-} SignalQualityCheckContext;<br>
+ gboolean enabled;<br>
+ guint interval;<br>
+ guint initial_retries;<br>
+ guint timeout_source;<br>
+<br>
+ /* Values polled in this iteration */<br>
+ guint signal_quality;<br>
+ MMModemAccessTechnology access_technologies;<br>
+ guint access_technologies_mask;<br>
+<br>
+ /* If both these are unset we'll automatically stop polling */<br>
+ gboolean signal_quality_polling_<wbr>supported;<br>
+ gboolean access_technology_polling_<wbr>supported;<br>
+<br>
+ /* Steps triggered when polling active */<br>
+ SignalCheckStep running_step;<br>
+} SignalCheckContext;<br>
<br>
static void<br>
-signal_quality_check_context_<wbr>free (SignalQualityCheckContext *ctx)<br>
+signal_check_context_free (SignalCheckContext *ctx)<br>
{<br>
if (ctx->timeout_source)<br>
g_source_remove (ctx->timeout_source);<br>
- g_free (ctx);<br>
+ g_slice_free (SignalCheckContext, ctx);<br>
}<br>
<br>
-static gboolean periodic_signal_quality_check (MMIfaceModem *self);<br>
+static SignalCheckContext *<br>
+get_signal_check_context (MMIfaceModem *self)<br>
+{<br>
+ SignalCheckContext *ctx;<br>
+<br>
+ if (G_UNLIKELY (!signal_check_context_quark))<br>
+ signal_check_context_quark = (g_quark_from_static_string (<br>
+ SIGNAL_CHECK_CONTEXT_TAG));<br>
+<br>
+ ctx = g_object_get_qdata (G_OBJECT (self), signal_check_context_quark);<br>
+ if (!ctx) {<br>
+ /* Create context and attach it to the object */<br>
+ ctx = g_slice_new0 (SignalCheckContext);<br>
+ ctx->running_step = SIGNAL_CHECK_STEP_NONE;<br>
+<br>
+ /* Initially assume supported if load_access_technologies() is<br>
+ * implemented. If the plugin reports an UNSUPPORTED error we'll clear<br>
+ * this flag and no longer poll. */<br>
+ ctx->access_technology_<wbr>polling_supported = (MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_<wbr>technologies &&<br>
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_<wbr>technologies_finish);<br>
+<br>
+ /* Initially assume supported if load_signal_quality() is<br>
+ * implemented. If the plugin reports an UNSUPPORTED error we'll clear<br>
+ * this flag and no longer poll. */<br>
+ ctx->signal_quality_polling_<wbr>supported = (MM_IFACE_MODEM_GET_INTERFACE (self)->load_signal_quality &&<br>
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_signal_quality_<wbr>finish);<br>
+<br>
+ g_object_set_qdata_full (G_OBJECT (self), signal_check_context_quark,<br>
+ ctx, (GDestroyNotify) signal_check_context_free);<br>
+ }<br>
+<br>
+ g_assert (ctx);<br>
+ return ctx;<br>
+}<br>
+<br>
+static void periodic_signal_check_disable (MMIfaceModem *self,<br>
+ gboolean clear);<br>
+static gboolean periodic_signal_check_cb (MMIfaceModem *self);<br>
+static void peridic_signal_check_step (MMIfaceModem *self);<br>
+<br>
+static void<br>
+access_technologies_check_<wbr>ready (MMIfaceModem *self,<br>
+ GAsyncResult *res)<br>
+{<br>
+ GError *error = NULL;<br>
+ SignalCheckContext *ctx;<br>
+<br>
+ ctx = get_signal_check_context (self);<br>
+<br>
+ if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_<wbr>technologies_finish (<br>
+ self,<br>
+ res,<br>
+ &ctx->access_technologies,<br>
+ &ctx->access_technologies_<wbr>mask,<br>
+ &error)) {<br>
+ /* Did the plugin report that polling access technology is unsupported? */<br>
+ if (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED)) {<br>
+ mm_dbg ("Polling to refresh access technologies is unsupported");<br>
+ ctx->access_technology_<wbr>polling_supported = FALSE;<br>
+ } else<br>
+ mm_dbg ("Couldn't refresh access technologies: '%s'", error->message);<br>
+ g_error_free (error);<br>
+ }<br>
+ /* We may have been disabled while this command was running. */<br>
+ else if (ctx->enabled)<br>
+ mm_iface_modem_update_access_<wbr>technologies (self, ctx->access_technologies, ctx->access_technologies_mask)<wbr>;<br>
+<br>
+ /* Go on */<br>
+ ctx->running_step++;<br>
+ peridic_signal_check_step (self);<br>
+}<br>
<br>
static void<br>
signal_quality_check_ready (MMIfaceModem *self,<br>
GAsyncResult *res)<br>
{<br>
- GError *error = NULL;<br>
- guint signal_quality;<br>
- SignalQualityCheckContext *ctx;<br>
+ GError *error = NULL;<br>
+ SignalCheckContext *ctx;<br>
+<br>
+ ctx = get_signal_check_context (self);<br>
<br>
- signal_quality = MM_IFACE_MODEM_GET_INTERFACE (self)->load_signal_quality_<wbr>finish (self,<br>
- res,<br>
- &error);<br>
+ ctx->signal_quality = MM_IFACE_MODEM_GET_INTERFACE (self)->load_signal_quality_<wbr>finish (self, res, &error);<br>
if (error) {<br>
- mm_dbg ("Couldn't refresh signal quality: '%s'", error->message);<br>
+ /* Did the plugin report that polling signal quality is unsupported? */<br>
+ if (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED)) {<br>
+ mm_dbg ("Polling to refresh signal quality is unsupported");<br>
+ ctx->signal_quality_polling_<wbr>supported = FALSE;<br>
+ } else<br>
+ mm_dbg ("Couldn't refresh signal quality: '%s'", error->message);<br>
g_error_free (error);<br>
- } else<br>
- update_signal_quality (self, signal_quality, TRUE);<br>
-<br>
- /* Remove the running tag. Note that the context may have been removed by<br>
- * mm_iface_modem_shutdown when this function is invoked as a callback of<br>
- * load_signal_quality. */<br>
- ctx = g_object_get_qdata (G_OBJECT (self), signal_quality_check_context_<wbr>quark);<br>
- if (ctx) {<br>
- if (ctx->interval == SIGNAL_QUALITY_INITIAL_CHECK_<wbr>TIMEOUT_SEC &&<br>
- (signal_quality != 0 || --ctx->initial_retries == 0)) {<br>
- ctx->interval = SIGNAL_QUALITY_CHECK_TIMEOUT_<wbr>SEC;<br>
- if (ctx->timeout_source) {<br>
- mm_dbg ("Periodic signal quality checks rescheduled (interval = %ds)", ctx->interval);<br>
- g_source_remove(ctx->timeout_<wbr>source);<br>
- ctx->timeout_source = g_timeout_add_seconds (ctx->interval,<br>
- (GSourceFunc)periodic_signal_<wbr>quality_check,<br>
- self);<br>
+ }<br>
+ /* We may have been disabled while this command was running. */<br>
+ else if (ctx->enabled)<br>
+ update_signal_quality (self, ctx->signal_quality, TRUE);<br>
+<br>
+ /* Go on */<br>
+ ctx->running_step++;<br>
+ peridic_signal_check_step (self);<br>
+}<br>
+<br>
+static void<br>
+peridic_signal_check_step (MMIfaceModem *self)<br>
+{<br>
+ SignalCheckContext *ctx;<br>
+<br>
+ ctx = get_signal_check_context (self);<br>
+<br>
+ switch (ctx->running_step) {<br>
+ case SIGNAL_CHECK_STEP_NONE:<br>
+ g_assert_not_reached ();<br>
+<br>
+ case SIGNAL_CHECK_STEP_FIRST:<br>
+ /* Fall down to next step */<br>
+ ctx->running_step++;<br>
+<br>
+ case SIGNAL_CHECK_STEP_SIGNAL_<wbr>QUALITY:<br>
+ if (ctx->enabled && ctx->signal_quality_polling_<wbr>supported) {<br>
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_signal_quality (<br>
+ self, (GAsyncReadyCallback)signal_<wbr>quality_check_ready, NULL);<br>
+ return;<br>
+ }<br>
+ /* Fall down to next step */<br>
+ ctx->running_step++;<br>
+<br>
+ case SIGNAL_CHECK_STEP_ACCESS_<wbr>TECHNOLOGIES:<br>
+ if (ctx->enabled && ctx->access_technology_<wbr>polling_supported) {<br>
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_<wbr>technologies (<br>
+ self, (GAsyncReadyCallback)access_<wbr>technologies_check_ready, NULL);<br>
+ return;<br>
+ }<br>
+ /* Fall down to next step */<br>
+ ctx->running_step++;<br>
+<br>
+ case SIGNAL_CHECK_STEP_LAST:<br>
+ /* Flag as sequence finished */<br>
+ ctx->running_step = SIGNAL_CHECK_STEP_NONE;<br>
+<br>
+ /* If we have been disabled while we were running the steps, we don't<br>
+ * do anything else. */<br>
+ if (!ctx->enabled) {<br>
+ mm_dbg ("Periodic signal checks not rescheduled: disabled");<br>
+ return;<br>
+ }<br>
+<br>
+ /* If both tasks are unsupported, implicitly disable. Do NOT clear the<br>
+ * values, because if we're told they are unsupported it may be that<br>
+ * they're really updated via unsolicited messages. */<br>
+ if (!ctx->access_technology_<wbr>polling_supported && !ctx->signal_quality_polling_<wbr>supported) {<br>
+ mm_dbg ("Periodic signal checks not supported");<br>
+ periodic_signal_check_disable (self, FALSE);<br>
+ return;<br>
+ }<br>
+<br>
+ /* Schedule when we poll next time.<br>
+ * Initially we poll at a higher frequency until we get valid signal<br>
+ * quality and access technology values. As soon as we get them, OR if<br>
+ * we made too many retries at a high frequency, we fallback to the<br>
+ * slower polling. */<br>
+ if (ctx->interval == SIGNAL_CHECK_INITIAL_TIMEOUT_<wbr>SEC) {<br>
+ gboolean signal_quality_ready;<br>
+ gboolean access_technology_ready;<br>
+<br>
+ /* Signal quality is ready if unsupported or if we got a valid<br>
+ * value reported */<br>
+ signal_quality_ready = (!ctx->signal_quality_polling_<wbr>supported || (ctx->signal_quality != 0));<br>
+ /* Access technology is ready if unsupported or if we got a valid<br>
+ * value reported */<br>
+ access_technology_ready = (!ctx->access_technology_<wbr>polling_supported ||<br>
+ ((ctx->access_technologies & ctx->access_technologies_mask) != MM_MODEM_ACCESS_TECHNOLOGY_<wbr>UNKNOWN));<br>
+<br>
+ if (signal_quality_ready && access_technology_ready) {<br>
+ mm_dbg ("Initial signal quality and access technology ready: fallback to default frequency");<br>
+ ctx->interval = SIGNAL_CHECK_TIMEOUT_SEC;<br>
+ } else if (--ctx->initial_retries == 0) {<br>
+ mm_dbg ("Too many periodic signal checks at high frequency: fallback to default frequency");<br>
+ ctx->interval = SIGNAL_CHECK_TIMEOUT_SEC;<br>
}<br>
}<br>
- ctx->running = FALSE;<br>
+<br>
+ mm_dbg ("Periodic signal quality checks scheduled in %ds", ctx->interval);<br>
+ g_assert (!ctx->timeout_source);<br>
+ ctx->timeout_source = g_timeout_add_seconds (ctx->interval, (GSourceFunc) periodic_signal_check_cb, self);<br>
+ return;<br>
}<br>
}<br>
<br>
static gboolean<br>
-periodic_signal_quality_check (MMIfaceModem *self)<br>
+periodic_signal_check_cb (MMIfaceModem *self)<br>
{<br>
- SignalQualityCheckContext *ctx;<br>
+ SignalCheckContext *ctx;<br>
<br>
- ctx = g_object_get_qdata (G_OBJECT (self), signal_quality_check_context_<wbr>quark);<br>
+ ctx = get_signal_check_context (self);<br>
+ g_assert (ctx->enabled);<br>
<br>
- /* Only launch a new one if not one running already OR if the last one run<br>
- * was more than 15s ago. */<br>
- if (!ctx->running ||<br>
- (time (NULL) - get_last_signal_quality_<wbr>update_time (self) > (ctx->interval / 2))) {<br>
- ctx->running = TRUE;<br>
- MM_IFACE_MODEM_GET_INTERFACE (self)->load_signal_quality (<br>
- self,<br>
- (GAsyncReadyCallback)signal_<wbr>quality_check_ready,<br>
- NULL);<br>
- }<br>
+ /* Start the sequence */<br>
+ ctx->running_step = SIGNAL_CHECK_STEP_FIRST;<br>
+ ctx->signal_quality = 0;<br>
+ ctx->access_technologies = MM_MODEM_ACCESS_TECHNOLOGY_<wbr>UNKNOWN;<br>
+ ctx->access_technologies_mask = MM_MODEM_ACCESS_TECHNOLOGY_<wbr>ANY;<br>
+ peridic_signal_check_step (self);<br>
<br>
- return G_SOURCE_CONTINUE;<br>
+ /* Remove the timeout and clear the source id */<br>
+ if (ctx->timeout_source)<br>
+ ctx->timeout_source = 0;<br>
+ return G_SOURCE_REMOVE;<br>
}<br>
<br>
-static void<br>
-periodic_signal_quality_<wbr>check_disable (MMIfaceModem *self)<br>
+void<br>
+mm_iface_modem_refresh_signal (MMIfaceModem *self)<br>
{<br>
- if (G_UNLIKELY (!signal_quality_check_<wbr>context_quark))<br>
- signal_quality_check_context_<wbr>quark = (g_quark_from_static_string (<br>
- SIGNAL_QUALITY_CHECK_CONTEXT_<wbr>TAG));<br>
+ SignalCheckContext *ctx;<br>
<br>
- /* Clear signal quality */<br>
- update_signal_quality (self, 0, FALSE);<br>
+ /* Don't refresh polling if we're not enabled */<br>
+ ctx = get_signal_check_context (self);<br>
+ if (!ctx->enabled) {<br>
+ mm_dbg ("Periodic signal check refresh ignored: checks not enabled");<br>
+ return;<br>
+ }<br>
<br>
- /* Overwriting the data will free the previous context */<br>
- g_object_set_qdata (G_OBJECT (self),<br>
- signal_quality_check_context_<wbr>quark,<br>
- NULL);<br>
+ /* Don't refresh if we're already doing it */<br>
+ if (ctx->running_step != SIGNAL_CHECK_STEP_NONE) {<br>
+ mm_dbg ("Periodic signal check refresh ignored: check already running");<br>
+ return;<br>
+ }<br>
+<br>
+ mm_dbg ("Periodic signal check refresh requested");<br>
+<br>
+ /* Remove the scheduled timeout as we're going to refresh<br>
+ * right away */<br>
+ if (ctx->timeout_source) {<br>
+ g_source_remove (ctx->timeout_source);<br>
+ ctx->timeout_source = 0;<br>
+ }<br>
<br>
- mm_dbg ("Periodic signal quality checks disabled");<br>
+ /* Start sequence */<br>
+ periodic_signal_check_cb (self);<br>
}<br>
<br>
static void<br>
-periodic_signal_quality_<wbr>check_enable (MMIfaceModem *self)<br>
+periodic_signal_check_disable (MMIfaceModem *self,<br>
+ gboolean clear)<br>
{<br>
- SignalQualityCheckContext *ctx;<br>
+ SignalCheckContext *ctx;<br>
<br>
- if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_signal_quality ||<br>
- !MM_IFACE_MODEM_GET_INTERFACE (self)->load_signal_quality_<wbr>finish) {<br>
- /* If loading signal quality not supported, don't even bother setting up<br>
- * a timeout */<br>
+ ctx = get_signal_check_context (self);<br>
+ if (!ctx->enabled)<br>
return;<br>
+<br>
+ /* Clear access technology and signal quality */<br>
+ if (clear) {<br>
+ update_signal_quality (self, 0, FALSE);<br>
+ mm_iface_modem_update_access_<wbr>technologies (self,<br>
+ MM_MODEM_ACCESS_TECHNOLOGY_<wbr>UNKNOWN,<br>
+ MM_MODEM_ACCESS_TECHNOLOGY_<wbr>ANY);<br>
}<br>
<br>
- if (G_UNLIKELY (!signal_quality_check_<wbr>context_quark))<br>
- signal_quality_check_context_<wbr>quark = (g_quark_from_static_string (<br>
- SIGNAL_QUALITY_CHECK_CONTEXT_<wbr>TAG));<br>
+ /* Remove scheduled timeout */<br>
+ if (ctx->timeout_source) {<br>
+ g_source_remove (ctx->timeout_source);<br>
+ ctx->timeout_source = 0;<br>
+ }<br>
<br>
- ctx = g_object_get_qdata (G_OBJECT (self), signal_quality_check_context_<wbr>quark);<br>
+ ctx->enabled = FALSE;<br>
+ mm_dbg ("Periodic signal checks disabled");<br>
+}<br>
<br>
- /* If context is already there, we're already enabled */<br>
- if (ctx) {<br>
- periodic_signal_quality_check (self);<br>
+static void<br>
+periodic_signal_check_enable (MMIfaceModem *self)<br>
+{<br>
+ SignalCheckContext *ctx;<br>
+<br>
+ ctx = get_signal_check_context (self);<br>
+<br>
+ /* If polling access technology and signal quality not supported, don't even<br>
+ * bother trying. */<br>
+ if (!ctx->signal_quality_polling_<wbr>supported && !ctx->access_technology_<wbr>polling_supported) {<br>
+ mm_dbg ("Not enabling periodic signal checks: unsupported");<br>
return;<br>
}<br>
<br>
- /* Create context and keep it as object data */<br>
- ctx = g_new0 (SignalQualityCheckContext, 1);<br>
- /* Schedule the signal quality check using a shorter period, up to 5<br>
- * periods, initially until a non-zero signal quality value is obtained<br>
- * and then switch back to the normal period. */<br>
- ctx->interval = SIGNAL_QUALITY_INITIAL_CHECK_<wbr>TIMEOUT_SEC;<br>
- ctx->initial_retries = 5;<br>
- mm_dbg ("Periodic signal quality checks enabled (interval = %ds)", ctx->interval);<br>
- ctx->timeout_source = g_timeout_add_seconds (ctx->interval,<br>
- (GSourceFunc)periodic_signal_<wbr>quality_check,<br>
- self);<br>
- g_object_set_qdata_full (G_OBJECT (self),<br>
- signal_quality_check_context_<wbr>quark,<br>
- ctx,<br>
- (GDestroyNotify)signal_<wbr>quality_check_context_free);<br>
+ /* Log and flag as enabled */<br>
+ if (!ctx->enabled) {<br>
+ mm_dbg ("Periodic signal checks enabled");<br>
+ ctx->enabled = TRUE;<br>
+ /* As soon as it is started, poll at a higher frequency */<br>
+ ctx->interval = SIGNAL_CHECK_INITIAL_TIMEOUT_<wbr>SEC;<br>
+ ctx->initial_retries = SIGNAL_CHECK_INITIAL_RETRIES;<br>
+ }<br>
<br>
- /* Get first signal quality value */<br>
- periodic_signal_quality_check (self);<br>
+ /* And refresh, which will trigger the first check */<br>
+ mm_iface_modem_refresh_signal (self);<br>
}<br>
<br>
/*****************************<wbr>******************************<wbr>******************/<br>
@@ -1456,18 +1484,12 @@ __iface_modem_update_state_<wbr>internal (MMIfaceModem *self,<br>
<br>
/* If we go to a registered/connected state (from unregistered), setup<br>
* signal quality and access technologies periodic retrieval */<br>
- if (new_state >= MM_MODEM_STATE_REGISTERED &&<br>
- old_state < MM_MODEM_STATE_REGISTERED) {<br>
- periodic_signal_quality_check_<wbr>enable (self);<br>
- periodic_access_technologies_<wbr>check_enable (self);<br>
- }<br>
+ if (new_state >= MM_MODEM_STATE_REGISTERED && old_state < MM_MODEM_STATE_REGISTERED)<br>
+ periodic_signal_check_enable (self);<br>
/* If we go from a registered/connected state to unregistered,<br>
* cleanup signal quality retrieval */<br>
- else if (old_state >= MM_MODEM_STATE_REGISTERED &&<br>
- new_state < MM_MODEM_STATE_REGISTERED) {<br>
- periodic_signal_quality_check_<wbr>disable (self);<br>
- periodic_access_technologies_<wbr>check_disable (self);<br>
- }<br>
+ else if (old_state >= MM_MODEM_STATE_REGISTERED && new_state < MM_MODEM_STATE_REGISTERED)<br>
+ periodic_signal_check_disable (self, TRUE);<br>
}<br>
<br>
if (skeleton)<br>
@@ -4906,14 +4928,9 @@ mm_iface_modem_initialize (MMIfaceModem *self,<br>
void<br>
mm_iface_modem_shutdown (MMIfaceModem *self)<br>
{<br>
- /* Remove SignalQualityCheckContext object to make sure any pending<br>
- * invocation of periodic_signal_quality_check is cancelled before<br>
- * SignalQualityUpdateContext is removed (as signal_quality_check_ready may<br>
- * call update_signal_quality). */<br>
- if (G_LIKELY (signal_quality_check_context_<wbr>quark))<br>
- g_object_set_qdata (G_OBJECT (self),<br>
- signal_quality_check_context_<wbr>quark,<br>
- NULL);<br>
+ /* Make sure signal polling is disabled. No real need to clear values, as<br>
+ * we're shutting down the interface anyway. */<br>
+ periodic_signal_check_disable (self, FALSE);<br>
<br>
/* Remove SignalQualityUpdateContext object to make sure any pending<br>
* invocation of expire_signal_quality is canceled before the DBus skeleton<br>
@@ -4923,14 +4940,6 @@ mm_iface_modem_shutdown (MMIfaceModem *self)<br>
signal_quality_update_context_<wbr>quark,<br>
NULL);<br>
<br>
- /* Remove AccessTechnologiesCheckContext object to make sure any pending<br>
- * invocation of periodic_access_technologies_<wbr>check is canceled before the<br>
- * DBus skeleton is removed. */<br>
- if (G_LIKELY (access_technologies_check_<wbr>context_quark))<br>
- g_object_set_qdata (G_OBJECT (self),<br>
- access_technologies_check_<wbr>context_quark,<br>
- NULL);<br>
-<br>
/* Remove running restart initialization idle, if any */<br>
if (G_LIKELY (restart_initialize_idle_<wbr>quark))<br>
g_object_set_qdata (G_OBJECT (self),<br>
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h<br>
index 517c651d..17ded5bc 100644<br>
--- a/src/mm-iface-modem.h<br>
+++ b/src/mm-iface-modem.h<br>
@@ -444,13 +444,13 @@ void mm_iface_modem_update_access_<wbr>technologies (MMIfaceModem *self,<br>
MMModemAccessTechnology access_tech,<br>
guint32 mask);<br>
<br>
-/* Allow requesting to refresh access tech */<br>
-void mm_iface_modem_refresh_access_<wbr>technologies (MMIfaceModem *self);<br>
-<br>
/* Allow updating signal quality */<br>
void mm_iface_modem_update_signal_<wbr>quality (MMIfaceModem *self,<br>
guint signal_quality);<br>
<br>
+/* Allow requesting to refresh signal via polling */<br>
+void mm_iface_modem_refresh_signal (MMIfaceModem *self);<br>
+<br>
/* Allow setting allowed modes */<br>
void mm_iface_modem_set_current_<wbr>modes (MMIfaceModem *self,<br>
MMModemMode allowed,<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.12.2<br>
<br>
______________________________<wbr>_________________<br>
ModemManager-devel mailing list<br>
<a href="mailto:ModemManager-devel@lists.freedesktop.org">ModemManager-devel@lists.<wbr>freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/modemmanager-<wbr>devel</a><br>
</font></span></blockquote></div><br></div>