diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-01-22 12:55:23 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-15 14:14:56 +0100 |
commit | 8321bd5875a5aedb845d8b196ae6db75c3f769d2 (patch) | |
tree | 981105c238fd6aec22426762a6ed464c3fd2b509 | |
parent | 59e903820d21dc041443ebb05348ee305d269429 (diff) |
iface-modem: periodically request to update current access technologies
-rw-r--r-- | src/mm-iface-modem.c | 136 | ||||
-rw-r--r-- | src/mm-iface-modem.h | 10 |
2 files changed, 140 insertions, 6 deletions
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c index 946e6397..87a2eeb7 100644 --- a/src/mm-iface-modem.c +++ b/src/mm-iface-modem.c @@ -24,16 +24,19 @@ #include "mm-bearer-list.h" #include "mm-log.h" -#define SIGNAL_QUALITY_RECENT_TIMEOUT_SEC 60 -#define SIGNAL_QUALITY_CHECK_TIMEOUT_SEC 30 +#define SIGNAL_QUALITY_RECENT_TIMEOUT_SEC 60 +#define SIGNAL_QUALITY_CHECK_TIMEOUT_SEC 30 +#define ACCESS_TECHNOLOGIES_CHECK_TIMEOUT_SEC 30 -#define STATE_UPDATE_CONTEXT_TAG "state-update-context-tag" -#define SIGNAL_QUALITY_UPDATE_CONTEXT_TAG "signal-quality-update-context-tag" -#define SIGNAL_QUALITY_CHECK_CONTEXT_TAG "signal-quality-check-context-tag" +#define STATE_UPDATE_CONTEXT_TAG "state-update-context-tag" +#define SIGNAL_QUALITY_UPDATE_CONTEXT_TAG "signal-quality-update-context-tag" +#define SIGNAL_QUALITY_CHECK_CONTEXT_TAG "signal-quality-check-context-tag" +#define ACCESS_TECHNOLOGIES_CHECK_CONTEXT_TAG "access-technologies-check-context-tag" static GQuark state_update_context_quark; static GQuark signal_quality_update_context_quark; static GQuark signal_quality_check_context_quark; +static GQuark access_technologies_check_context_quark; /*****************************************************************************/ @@ -392,6 +395,125 @@ mm_iface_modem_update_access_technologies (MMIfaceModem *self, /*****************************************************************************/ typedef struct { + guint timeout_source; + gboolean running; +} AccessTechnologiesCheckContext; + +static void +access_technologies_check_context_free (AccessTechnologiesCheckContext *ctx) +{ + if (ctx->timeout_source) + g_source_remove (ctx->timeout_source); + g_free (ctx); +} + +static void +access_technologies_check_ready (MMIfaceModem *self, + GAsyncResult *res) +{ + GError *error = NULL; + MMModemAccessTechnology access_technologies = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; + guint mask = MM_MODEM_ACCESS_TECHNOLOGY_ANY; + AccessTechnologiesCheckContext *ctx; + + if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_technologies_finish ( + self, + res, + &access_technologies, + &mask, + &error)) { + mm_dbg ("Couldn't refresh access technologies: '%s'", error->message); + g_error_free (error); + } else + mm_iface_modem_update_access_technologies (self, access_technologies, mask); + + /* Remove the running tag */ + ctx = g_object_get_qdata (G_OBJECT (self), access_technologies_check_context_quark); + ctx->running = FALSE; +} + +static gboolean +periodic_access_technologies_check (MMIfaceModem *self) +{ + AccessTechnologiesCheckContext *ctx; + + ctx = g_object_get_qdata (G_OBJECT (self), access_technologies_check_context_quark); + + /* Only launch a new one if not one running already OR if the last one run + * was more than 15s ago. */ + if (!ctx->running) { + ctx->running = TRUE; + MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_technologies ( + self, + (GAsyncReadyCallback)access_technologies_check_ready, + NULL); + } + + return TRUE; +} + +static void +periodic_access_technologies_check_disable (MMIfaceModem *self) +{ + if (G_UNLIKELY (!access_technologies_check_context_quark)) + access_technologies_check_context_quark = (g_quark_from_static_string ( + ACCESS_TECHNOLOGIES_CHECK_CONTEXT_TAG)); + + /* Clear access technology */ + mm_iface_modem_update_access_technologies (self, + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + MM_MODEM_ACCESS_TECHNOLOGY_ANY); + + /* Overwriting the data will free the previous context */ + g_object_set_qdata (G_OBJECT (self), + access_technologies_check_context_quark, + NULL); + + mm_dbg ("Periodic access technology checks disabled"); +} + +static void +periodic_access_technologies_check_enable (MMIfaceModem *self) +{ + AccessTechnologiesCheckContext *ctx; + + if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_technologies || + !MM_IFACE_MODEM_GET_INTERFACE (self)->load_access_technologies_finish) { + /* If loading access technology not supported, don't even bother setting up + * a timeout */ + return; + } + + if (G_UNLIKELY (!access_technologies_check_context_quark)) + access_technologies_check_context_quark = (g_quark_from_static_string ( + ACCESS_TECHNOLOGIES_CHECK_CONTEXT_TAG)); + + ctx = g_object_get_qdata (G_OBJECT (self), access_technologies_check_context_quark); + + /* If context is already there, we're already enabled */ + if (ctx) { + periodic_access_technologies_check (self); + return; + } + + /* Create context and keep it as object data */ + mm_dbg ("Periodic access technology checks enabled"); + ctx = g_new0 (AccessTechnologiesCheckContext, 1); + ctx->timeout_source = g_timeout_add_seconds (ACCESS_TECHNOLOGIES_CHECK_TIMEOUT_SEC, + (GSourceFunc)periodic_access_technologies_check, + self); + g_object_set_qdata_full (G_OBJECT (self), + access_technologies_check_context_quark, + ctx, + (GDestroyNotify)access_technologies_check_context_free); + + /* Get first access technology value */ + periodic_access_technologies_check (self); +} + +/*****************************************************************************/ + +typedef struct { time_t last_update; guint recent_timeout_source; } SignalQualityUpdateContext; @@ -705,16 +827,18 @@ mm_iface_modem_update_state (MMIfaceModem *self, reason); /* If we go to registered state (from unregistered), setup signal - * quality retrieval */ + * quality and access technologies periodic retrieval */ if (new_state == MM_MODEM_STATE_REGISTERED && old_state < MM_MODEM_STATE_REGISTERED) { periodic_signal_quality_check_enable (self); + periodic_access_technologies_check_enable (self); } /* If we go from a registered/connected state to unregistered, * cleanup signal quality retrieval */ else if (old_state >= MM_MODEM_STATE_REGISTERED && new_state < MM_MODEM_STATE_REGISTERED) { periodic_signal_quality_check_disable (self); + periodic_access_technologies_check_disable (self); } } diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h index 1ef3fd83..010a3476 100644 --- a/src/mm-iface-modem.h +++ b/src/mm-iface-modem.h @@ -136,6 +136,16 @@ struct _MMIfaceModem { GAsyncResult *res, GError **error); + /* Loading of the AccessTechnologies property */ + void (*load_access_technologies) (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*load_access_technologies_finish) (MMIfaceModem *self, + GAsyncResult *res, + MMModemAccessTechnology *access_technologies, + guint *mask, + GError **error); + /* Asynchronous reset operation */ void (*reset) (MMIfaceModem *self, GAsyncReadyCallback callback, |