aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-01-05 19:05:15 +0100
committerAleksander Morgado <aleksander@lanedo.com>2012-03-15 14:14:46 +0100
commit0b8d0c697d68efd9cf2828508c06cb03cd4b1145 (patch)
treed74e7444e859242e01dd5258eafd6e2bd7d61b60 /src
parent6d76f1755f480fa9c3a4858e250d8b85d423d1b5 (diff)
iface-modem: get consolidated state from all subsystems
We don't want, e.g., REGISTERED->ENABLED transitions when 3GPP gets unregistered but we're still registered in CDMA.
Diffstat (limited to 'src')
-rw-r--r--src/mm-iface-modem.c110
-rw-r--r--src/mm-iface-modem.h4
2 files changed, 114 insertions, 0 deletions
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 69712db2..855931a3 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -27,9 +27,11 @@
#define SIGNAL_QUALITY_RECENT_TIMEOUT_SEC 60
#define SIGNAL_QUALITY_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"
+static GQuark state_update_context_quark;
static GQuark signal_quality_update_context_quark;
static GQuark signal_quality_check_context_quark;
@@ -746,6 +748,114 @@ mm_iface_modem_update_state (MMIfaceModem *self,
/*****************************************************************************/
+typedef struct {
+ gchar *subsystem;
+ MMModemState state;
+} SubsystemState;
+
+static void
+subsystem_state_array_free (GArray *array)
+{
+ guint i;
+
+ for (i = 0; i < array->len; i++) {
+ SubsystemState *s;
+
+ s = &g_array_index (array, SubsystemState, i);
+ g_free (s->subsystem);
+ }
+
+ g_array_free (array, TRUE);
+}
+
+static MMModemState
+get_consolidated_state (MMIfaceModem *self,
+ const gchar *subsystem,
+ MMModemState subsystem_state)
+{
+ guint i;
+ GArray *subsystem_states;
+ MMModemState consolidated;
+
+ /* Reported subsystem states will be REGISTRATION-related. This means
+ * that we would only expect a subset of the states being reported for
+ * the subystem. Warn if we get others */
+ g_warn_if_fail (subsystem_state == MM_MODEM_STATE_ENABLED ||
+ subsystem_state == MM_MODEM_STATE_SEARCHING ||
+ subsystem_state == MM_MODEM_STATE_REGISTERED);
+
+ if (G_UNLIKELY (!state_update_context_quark))
+ state_update_context_quark = (g_quark_from_static_string (
+ STATE_UPDATE_CONTEXT_TAG));
+
+ subsystem_states = g_object_get_qdata (G_OBJECT (self),
+ state_update_context_quark);
+ if (!subsystem_states) {
+ subsystem_states = g_array_sized_new (FALSE,
+ FALSE,
+ sizeof (SubsystemState),
+ 2);
+ g_object_set_qdata_full (G_OBJECT (self),
+ state_update_context_quark,
+ subsystem_states,
+ (GDestroyNotify)subsystem_state_array_free);
+ }
+
+ /* Store new subsystem state */
+ for (i = 0; i < subsystem_states->len; i++) {
+ SubsystemState *s;
+
+ s = &g_array_index (subsystem_states, SubsystemState, i);
+ if (g_str_equal (s->subsystem, subsystem)) {
+ s->state = subsystem_state;
+ break;
+ }
+ }
+
+ /* If not found, insert new element */
+ if (i == subsystem_states->len) {
+ SubsystemState s;
+
+ mm_dbg ("Will start keeping track of state for subsystem '%s'",
+ subsystem);
+ s.subsystem = g_strdup (subsystem);
+ s.state = subsystem_state;
+ g_array_append_val (subsystem_states, s);
+ }
+
+ /* Build consolidated state, expected fixes are:
+ * - Enabled (meaning unregistered) --> Searching|Registered
+ * - Searching --> Registered
+ */
+ consolidated = MM_MODEM_STATE_UNKNOWN;
+ for (i = 0; i < subsystem_states->len; i++) {
+ SubsystemState *s;
+
+ s = &g_array_index (subsystem_states, SubsystemState, i);
+ if (s->state > consolidated)
+ consolidated = s->state;
+ }
+
+ return consolidated;
+}
+
+void
+mm_iface_modem_update_subsystem_state (MMIfaceModem *self,
+ const gchar *subsystem,
+ MMModemState new_state,
+ MMModemStateReason reason)
+{
+ MMModemState consolidated;
+
+ /* We may have different subsystems being handled (e.g. 3GPP and CDMA), and
+ * the registration status value is unique, so if we get subsystem-specific
+ * state updates, we'll need to merge all to get a consolidated one. */
+ consolidated = get_consolidated_state (self, subsystem, new_state);
+ mm_iface_modem_update_state (self, consolidated, reason);
+}
+
+/*****************************************************************************/
+
static void
enable_disable_ready (MMIfaceModem *self,
GAsyncResult *res,
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index 804f02cb..141a975a 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -310,6 +310,10 @@ guint mm_iface_modem_signal_quality_check_finish (MMIfaceModem *self,
GError **error);
/* Allow reporting new modem state */
+void mm_iface_modem_update_subsystem_state (MMIfaceModem *self,
+ const gchar *subsystem,
+ MMModemState new_state,
+ MMModemStateReason reason);
void mm_iface_modem_update_state (MMIfaceModem *self,
MMModemState new_state,
MMModemStateReason reason);