[PATCH] iface-modem-3gpp: if EPS is unregistered, report disconnection

Aleksander Morgado aleksander at aleksander.es
Thu Jun 7 21:33:58 UTC 2018

When a modem is registered in LTE, there is an implicit data
connection established with the network, regardless of whether the
user has e.g. requested to connect to a specific APN.

Whenever the modem gets unregistered from LTE, if there is an ongoing
data connection established, we'll explicitly report that it's
disconnected, without needing to wait for the connection state
polling (if there is one).

Note that this logic won't do anything if module is PS attached to
GERAN or UTRAN (as these don't have an implicit data connection when
just registered).


What do you think of this change?

This seems to be the only way to reliably get reported of a disconnection of the default EPS bearer in e.g. the u-blox TOBY modules, because the connection state polling may end up querying the state just before and after a default EPS bearer disconnection and reconnection has happened (so both before and after would report that the context is connected, ignoring the reconnection).

The information that a reconnection has happened may be needed by the user because there's runtime state within the module that is cleared whenever this reconnection happens, so any previously configured state would be completely gone. If the disconnection is reported to the user, the user would be able to set again the desired state.

I was developing this just for the u-blox plugin, but the logic isn't really specific to u-blox, I think it makes sense to have it in the generic interface implementation.

 src/mm-iface-modem-3gpp.c | 47 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 4e19815d..c759edaa 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -24,6 +24,7 @@
 #include "mm-iface-modem-location.h"
 #include "mm-iface-modem-3gpp.h"
 #include "mm-base-modem.h"
+#include "mm-bearer-list.h"
 #include "mm-modem-helpers.h"
 #include "mm-error-helpers.h"
 #include "mm-log.h"
@@ -1408,12 +1409,23 @@ mm_iface_modem_3gpp_update_ps_registration_state (MMIfaceModem3gpp *self,
     update_registration_state (self, get_consolidated_reg_state (ctx), TRUE);

+static void
+bearer_list_report_disconnected (MMBaseBearer *bearer)
+    if (mm_base_bearer_get_status (bearer) == MM_BEARER_STATUS_DISCONNECTED)
+        return;
+    mm_info ("Bearer %s: explicitly disconnected due to LTE unregistration", mm_base_bearer_get_path (bearer));
+    mm_base_bearer_report_connection_status (bearer, MM_BEARER_CONNECTION_STATUS_DISCONNECTED);
 mm_iface_modem_3gpp_update_eps_registration_state (MMIfaceModem3gpp *self,
                                                    MMModem3gppRegistrationState state)
     RegistrationStateContext *ctx;
     gboolean supported = FALSE;
+    MMModem3gppRegistrationState previous_state;

     g_object_get (self,
                   MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, &supported,
@@ -1423,8 +1435,43 @@ mm_iface_modem_3gpp_update_eps_registration_state (MMIfaceModem3gpp *self,

     ctx = get_registration_state_context (self);
+    previous_state = ctx->eps;
     ctx->eps = state;
     update_registration_state (self, get_consolidated_reg_state (ctx), TRUE);
+    /*
+     * If EPS state switches from registered/searching to unregistered, we force
+     * an explicit disconnection report. The EPS registration state is bound to
+     * having data services, so if there is no registration we also consider
+     * there are no data services at all.
+     *
+     * We treat "searching" as a special case: even if it really is unregistered
+     * we don't trigger disconnection, as it may be able to find a new network to
+     * register to right away (so recovering data connection transparently).
+     *
+     * Before triggering disconnections in bearers blindly, also make sure we're
+     * not registered in PS (GERAN/UTRAN). If we're registered in PS, don't
+     * explicitly disconnect anything as the connections are not LTE.
+     */
+    if ((previous_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME       ||
+         previous_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING    ||
+         previous_state == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING) &&
+        (ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_IDLE             ||
+         ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN          ||
+         ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_DENIED)          &&
+        (ctx->ps != MM_MODEM_3GPP_REGISTRATION_STATE_HOME              &&
+        MMBearerList *list = NULL;
+        /* If empty bearer list, nothing else to do */
+        g_object_get (self,
+                      MM_IFACE_MODEM_BEARER_LIST, &list,
+                      NULL);
+        if (list) {
+            mm_bearer_list_foreach (list, (MMBearerListForeachFunc)bearer_list_report_disconnected, NULL);
+            g_object_unref (list);
+        }
+    }


More information about the ModemManager-devel mailing list