From cfd6cf61c59205abb1810c2dd83a6c70c1fcefbc Mon Sep 17 00:00:00 2001 From: RobMeades Date: Mon, 23 Sep 2024 15:23:41 +0100 Subject: [PATCH] Handle case where the module changes RAT on us: when this happens between 2G and LTE the module reactivates the context internally but doesn't say that it has done so, it just drops the PPP connection when we next try to use it. In order to handle this, if we spot a RAT change when PPP is active we reconnect the PDP context/PPP at that point. --- cell/src/u_cell_net.c | 20 ++++++++++++++------ cell/src/u_cell_ppp.c | 20 ++++++++++++++++---- cell/src/u_cell_ppp_private.h | 9 +++++++++ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/cell/src/u_cell_net.c b/cell/src/u_cell_net.c index 6694b955..88c3085c 100644 --- a/cell/src/u_cell_net.c +++ b/cell/src/u_cell_net.c @@ -67,6 +67,7 @@ #include "u_cell_mno_db.h" #include "u_cell_ppp_shared.h" +#include "u_cell_ppp_private.h" #include "u_cell_pwr_private.h" /* ---------------------------------------------------------------- @@ -316,6 +317,7 @@ static void setNetworkStatus(uCellPrivateInstance_t *pInstance, { uCellNetRegistationStatus_t *pStatus; bool printAllowed = true; + uCellNetRat_t previousRat = pInstance->rat[regType]; #if U_CFG_OS_CLIB_LEAKS // If we're in a URC and the C library leaks memory // when printf() is called from a dynamically @@ -429,12 +431,18 @@ static void setNetworkStatus(uCellPrivateInstance_t *pInstance, // support LTE but does support Cat-M1, switch it pInstance->rat[regType] = U_CELL_NET_RAT_CATM1; } - if (pInstance->profileState == U_CELL_PRIVATE_PROFILE_STATE_REQUIRES_REACTIVATION) { - // This flag will be set if we had been knocked out - // of our PDP context by a network outage and need - // to get it back again; make sure to get this in the - // queue before any user registratioon status callback - // so that everything is sorted for them + if ((pInstance->profileState == U_CELL_PRIVATE_PROFILE_STATE_REQUIRES_REACTIVATION) || + ((previousRat != U_CELL_NET_RAT_UNKNOWN_OR_NOT_USED) && + (pInstance->rat[regType] != previousRat) && (uCellPppPrivateIsOpen(pInstance)))) { + // profileState will have been set to "reactivation required" + // if we had been knocked out of our PDP context by a network + // outage and need to get it back again. We also need to do + // this if the module has changed RAT underneath us, potentially + // between 2G and LTE, and we have a PPP connection up; the PPP + // connection could have become inactive, without notification, + // on such a RAT change, activateContextCallback() will reconnect it. + // Make sure this is in the queue before any user registration + // status callback so that everything is sorted for the user. if (!U_CELL_PRIVATE_HAS(pInstance->pModule, U_CELL_PRIVATE_FEATURE_USE_UPSD_CONTEXT_ACTIVATION)) { // Use the AT client's callback mechanism to do the operation diff --git a/cell/src/u_cell_ppp.c b/cell/src/u_cell_ppp.c index 1127ee09..c2cc0e77 100644 --- a/cell/src/u_cell_ppp.c +++ b/cell/src/u_cell_ppp.c @@ -406,6 +406,20 @@ void uCellPppPrivateRemoveContext(uCellPrivateInstance_t *pInstance) } } +// Determine if PPP is up and running. +bool uCellPppPrivateIsOpen(uCellPrivateInstance_t *pInstance) +{ + bool isRunning = false; + uCellPppContext_t *pContext; + + if ((pInstance != NULL) && (pInstance->pPppContext != NULL)) { + pContext = (uCellPppContext_t *) pInstance->pPppContext; + isRunning = pContext->pDeviceSerial != NULL; + } + + return isRunning; +} + /* ---------------------------------------------------------------- * PUBLIC FUNCTIONS KEPT WITHIN THE SRC DIRECTORY * -------------------------------------------------------------- */ @@ -550,16 +564,14 @@ bool uCellPppIsOpen(uDeviceHandle_t cellHandle) { bool isRunning = false; uCellPrivateInstance_t *pInstance; - uCellPppContext_t *pContext; if (gUCellPrivateMutex != NULL) { U_PORT_MUTEX_LOCK(gUCellPrivateMutex); pInstance = pUCellPrivateGetInstance(cellHandle); - if ((pInstance != NULL) && (pInstance->pPppContext != NULL)) { - pContext = (uCellPppContext_t *) pInstance->pPppContext; - isRunning = pContext->pDeviceSerial != NULL; + if (pInstance != NULL) { + isRunning = uCellPppPrivateIsOpen(pInstance); } U_PORT_MUTEX_UNLOCK(gUCellPrivateMutex); diff --git a/cell/src/u_cell_ppp_private.h b/cell/src/u_cell_ppp_private.h index 45a21f3d..79097d59 100644 --- a/cell/src/u_cell_ppp_private.h +++ b/cell/src/u_cell_ppp_private.h @@ -57,6 +57,15 @@ extern "C" { */ void uCellPppPrivateRemoveContext(uCellPrivateInstance_t *pInstance); +/** Determine if a PPP connection is currently up. + * + * Note: gUCellPrivateMutex should be locked before this is called. + * + * @param[in] pInstance a pointer to the cellular instance. + * @return true if a PPP connection is up, else false. + */ +bool uCellPppPrivateIsOpen(uCellPrivateInstance_t *pInstance); + #ifdef __cplusplus } #endif