Skip to content
This repository was archived by the owner on Nov 11, 2024. It is now read-only.

Commit

Permalink
Cellular change only: reboot detection. (#834)
Browse files Browse the repository at this point in the history
A function is added, uCellCfgSetGreetingCallback() which is similar to uCellCfgSetGreeting() but, in addition, allows a callback to be included which will be called when the greeting string is emitted by the module.  This may be used as a "module has [re]booted" detection mechanism.
  • Loading branch information
RobMeades authored Feb 23, 2023
1 parent d78ea2b commit c585e45
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 37 deletions.
49 changes: 48 additions & 1 deletion cell/api/u_cell_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ extern "C" {
# define U_CELL_CFG_GNSS_SERVER_NAME_MAX_LEN_BYTES 256
#endif

/** A greeting message that may be used with
* uCellCfgSetGreetingCallback().
*/
#define U_CELL_CFG_GREETING "+ModuleHasBooted"

#ifndef U_CELL_CFG_GREETING_CALLBACK_MAX_LEN_BYTES
/** The maximum length of a greeting message when a callback is
* going to be used with it.
*/
# define U_CELL_CFG_GREETING_CALLBACK_MAX_LEN_BYTES 64
#endif

/* ----------------------------------------------------------------
* TYPES
* -------------------------------------------------------------- */
Expand Down Expand Up @@ -343,6 +355,40 @@ int32_t uCellCfgFactoryReset(uDeviceHandle_t cellHandle, int32_t fsRestoreType,
*/
int32_t uCellCfgSetGreeting(uDeviceHandle_t cellHandle, const char *pStr);

/** As uCellCfgSetGreeting() but also sets a callback which will be
* called when the greeting message is emitted by the module, allowing
* you to detect when the module has rebooted all by itself (as well as
* by command).
*
* Note: if DTR is being used to control power saving (i.e. a DTR
* pin has been set using uCellPwrSetDtrPowerSavingPin()) then the
* greeting message is NOT emitted by the module at a reboot.
*
* Obviously for this to be useful it is important that the greeting
* message is unique; you may consider using #U_CELL_CFG_GREETING.
*
* The same restrictions concerning auto-bauding apply here as to
* uCellCfgSetGreeting(). Calling uCellCfgSetGreeting() after calling
* this function will remove the callback.
*
* @param cellHandle the handle of the cellular instance.
* @param[in] pStr the null-terminated greeting message; cannot
* be NULL unless pCallback is NULL. Can be
* no more than
* #U_CELL_CFG_GREETING_CALLBACK_MAX_LEN_BYTES
* in length (excluding the null-terminator).
* @param[in] pCallback the callback; use NULL to remove a previous
* callback.
* @param[in] pCallbackParam user parameter which will be passed to pCallback
* as its second parameter; may be NULL.
* @return zero on success or negative error code on
* failure.
*/
int32_t uCellCfgSetGreetingCallback(uDeviceHandle_t cellHandle,
const char *pStr,
void (*pCallback) (uDeviceHandle_t, void *),
void *pCallbackParam);

/** Get the current greeting message.
*
* @param cellHandle the handle of the cellular instance.
Expand All @@ -358,7 +404,8 @@ int32_t uCellCfgSetGreeting(uDeviceHandle_t cellHandle, const char *pStr);
* error code. If there is no greeting message
* zero will be returned.
*/
int32_t uCellCfgGetGreeting(uDeviceHandle_t cellHandle, char *pStr, size_t size);
int32_t uCellCfgGetGreeting(uDeviceHandle_t cellHandle, char *pStr,
size_t size);

/** Switch off auto-bauding in the cellular module. This will fix
* the baud rate of the cellular module to the current baud rate,
Expand Down
206 changes: 171 additions & 35 deletions cell/src/u_cell_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include "u_port_debug.h"
#include "u_port_os.h"
#include "u_port_heap.h"

#include "u_at_client.h"

Expand Down Expand Up @@ -172,6 +173,14 @@ static const uCellNetRat_t gModuleRatBandMaskToCellRatR6[] = {
U_CELL_NET_RAT_LTE // 3: LTE
};

/** All the parameters for the greeting callback.
*/
typedef struct {
uDeviceHandle_t cellHandle;
void (*pCallback) (uDeviceHandle_t, void *);
void *pCallbackParameter;
} uCellCfgGreeting_t;

/* ----------------------------------------------------------------
* STATIC FUNCTIONS: RAT CONVERSION
* -------------------------------------------------------------- */
Expand Down Expand Up @@ -801,6 +810,99 @@ static int32_t setRatRankSaraRx(uCellPrivateInstance_t *pInstance,
return errorCode;
}

/* ----------------------------------------------------------------
* STATIC FUNCTIONS: GREETING MESSAGE RELATED
* -------------------------------------------------------------- */

// Set, or unset, a greeting message.
int32_t setGreeting(uAtClientHandle_t atHandle, const char *pStr)
{
int32_t mode = 0;

if (pStr != NULL) {
mode = 1;
}

uAtClientLock(atHandle);
uAtClientCommandStart(atHandle, "AT+CSGT=");
uAtClientWriteInt(atHandle, mode);
if (pStr != NULL) {
uAtClientWriteString(atHandle, pStr, true);
}
uAtClientCommandStopReadResponse(atHandle);
return uAtClientUnlock(atHandle);
}

// Get the current greeting message.
int32_t getGreeting(uAtClientHandle_t atHandle, char *pStr, size_t size)
{
int32_t errorCodeOrSize;
int32_t mode;
int32_t bytesRead;

uAtClientLock(atHandle);
uAtClientCommandStart(atHandle, "AT+CSGT?");
uAtClientCommandStop(atHandle);
uAtClientResponseStart(atHandle, "+CSGT:");
bytesRead = uAtClientReadString(atHandle, pStr, size, false);
mode = uAtClientReadInt(atHandle);
uAtClientResponseStop(atHandle);
errorCodeOrSize = uAtClientUnlock(atHandle);
if (errorCodeOrSize == 0) {
if (mode == 0) {
bytesRead = 0;
*pStr = 0;
}
errorCodeOrSize = bytesRead;
}

return errorCodeOrSize;
}

// Callback via which the user's greeting callback is called.
// This must be called through the uAtClientCallback() mechanism
// in order to prevent customer code blocking the AT client.
static void greetingCallback(uAtClientHandle_t atHandle, void *pParameter)
{
uCellCfgGreeting_t *pGreeting = (uCellCfgGreeting_t *) pParameter;

(void) atHandle;

if (pGreeting != NULL) {
if (pGreeting->pCallback != NULL) {
pGreeting->pCallback(pGreeting->cellHandle,
pGreeting->pCallbackParameter);
}
uPortFree(pGreeting);
}
}

// URC handler for when the greeting message has been detected.
//lint -esym(818, pParameter) Suppress pParameter could be const, need to
// follow prototype
static void GREETING_urc(uAtClientHandle_t atHandle, void *pParameter)
{
const uCellPrivateInstance_t *pInstance = (uCellPrivateInstance_t *) pParameter;
uCellCfgGreeting_t *pGreeting;

(void) atHandle;

if (pInstance->pGreetingCallback != NULL) {
// Put the data for the callback into a struct to our
// local callback via the AT client's callback mechanism
// to decouple it from any URC handler.
// Note: it is up to greetingCallback() to free the
// allocated memory.
pGreeting = (uCellCfgGreeting_t *) pUPortMalloc(sizeof(*pGreeting));
if (pGreeting != NULL) {
pGreeting->cellHandle = pInstance->cellHandle;
pGreeting->pCallback = pInstance->pGreetingCallback;
pGreeting->pCallbackParameter = pInstance->pGreetingCallbackParameter;
uAtClientCallback(atHandle, greetingCallback, pGreeting);
}
}
}

/* ----------------------------------------------------------------
* STATIC FUNCTIONS: GENERAL
* -------------------------------------------------------------- */
Expand Down Expand Up @@ -832,7 +934,6 @@ int32_t setAndStoreBaudRate(const uCellPrivateInstance_t *pInstance,
return errorCode;
}


/* ----------------------------------------------------------------
* PUBLIC FUNCTIONS
* -------------------------------------------------------------- */
Expand Down Expand Up @@ -1470,11 +1571,8 @@ int32_t uCellCfgSetGreeting(uDeviceHandle_t cellHandle, const char *pStr)
int32_t errorCode = (int32_t) U_ERROR_COMMON_INVALID_PARAMETER;
uCellPrivateInstance_t *pInstance;
uAtClientHandle_t atHandle;
int32_t mode = 0;

if (pStr != NULL) {
mode = 1;
}
size_t size;
char buffer[U_CELL_CFG_GREETING_CALLBACK_MAX_LEN_BYTES + 1]; // +1 for terminator

if (gUCellPrivateMutex != NULL) {

Expand All @@ -1483,14 +1581,69 @@ int32_t uCellCfgSetGreeting(uDeviceHandle_t cellHandle, const char *pStr)
pInstance = pUCellPrivateGetInstance(cellHandle);
if (pInstance != NULL) {
atHandle = pInstance->atHandle;
uAtClientLock(atHandle);
uAtClientCommandStart(atHandle, "AT+CSGT=");
uAtClientWriteInt(atHandle, mode);
if (pStr != NULL) {
uAtClientWriteString(atHandle, pStr, true);
if (pInstance->pGreetingCallback != NULL) {
// If there's already a greeting callback, remove
// it 'cos this is the "non-callback" form
size = getGreeting(atHandle, buffer, sizeof(buffer));
if (size > 0) {
uAtClientRemoveUrcHandler(atHandle, buffer);
}
pInstance->pGreetingCallback = NULL;
pInstance->pGreetingCallbackParameter = NULL;
}
// Now actually set the greeting
errorCode = setGreeting(atHandle, pStr);
}

U_PORT_MUTEX_UNLOCK(gUCellPrivateMutex);
}

return errorCode;
}

// Set a greeting message with a callback.
int32_t uCellCfgSetGreetingCallback(uDeviceHandle_t cellHandle,
const char *pStr,
void (*pCallback) (uDeviceHandle_t, void *),
void *pCallbackParam)
{
int32_t errorCode = (int32_t) U_ERROR_COMMON_INVALID_PARAMETER;
uCellPrivateInstance_t *pInstance;
uAtClientHandle_t atHandle;
size_t size;
char buffer[U_CELL_CFG_GREETING_CALLBACK_MAX_LEN_BYTES + 1]; // +1 for terminator

if (gUCellPrivateMutex != NULL) {

U_PORT_MUTEX_LOCK(gUCellPrivateMutex);

if (((pStr != NULL) && (strlen(pStr) <= U_CELL_CFG_GREETING_CALLBACK_MAX_LEN_BYTES)) ||
(pCallback == NULL)) {
pInstance = pUCellPrivateGetInstance(cellHandle);
if (pInstance != NULL) {
atHandle = pInstance->atHandle;
// Remove any existing greeting and callback
size = getGreeting(atHandle, buffer, sizeof(buffer));
if (size > 0) {
uAtClientRemoveUrcHandler(atHandle, buffer);
}
// Set the new greeting
errorCode = setGreeting(atHandle, pStr);
if (errorCode == 0) {
if (pCallback != NULL) {
errorCode = uAtClientSetUrcHandler(atHandle, pStr,
GREETING_urc, pInstance);
if (errorCode != 0) {
// Clean up on error
setGreeting(atHandle, NULL);
}
}
if (errorCode == 0) {
pInstance->pGreetingCallback = pCallback;
pInstance->pGreetingCallbackParameter = pCallbackParam;
}
}
}
uAtClientCommandStopReadResponse(atHandle);
errorCode = uAtClientUnlock(atHandle);
}

U_PORT_MUTEX_UNLOCK(gUCellPrivateMutex);
Expand All @@ -1504,35 +1657,18 @@ int32_t uCellCfgGetGreeting(uDeviceHandle_t cellHandle, char *pStr, size_t size)
{
int32_t errorCodeOrSize = (int32_t) U_ERROR_COMMON_INVALID_PARAMETER;
uCellPrivateInstance_t *pInstance;
uAtClientHandle_t atHandle;
int32_t mode;
int32_t bytesRead;

if (gUCellPrivateMutex != NULL) {

U_PORT_MUTEX_LOCK(gUCellPrivateMutex);

pInstance = pUCellPrivateGetInstance(cellHandle);
if ((pInstance != NULL) && (pStr != NULL)) {
atHandle = pInstance->atHandle;
uAtClientLock(atHandle);
uAtClientCommandStart(atHandle, "AT+CSGT?");
uAtClientCommandStop(atHandle);
uAtClientResponseStart(atHandle, "+CSGT:");
bytesRead = uAtClientReadString(atHandle, pStr, size, false);
mode = uAtClientReadInt(atHandle);
uAtClientResponseStop(atHandle);
errorCodeOrSize = uAtClientUnlock(atHandle);
if (errorCodeOrSize == 0) {
if (mode == 0) {
bytesRead = 0;
}
errorCodeOrSize = bytesRead;
if (bytesRead > 0) {
uPortLog("U_CELL_CFG: greeting message is \"%s\".\n", pStr);
} else {
uPortLog("U_CELL_CFG: no greeting message is set.\n");
}
errorCodeOrSize = getGreeting(pInstance->atHandle, pStr, size);
if (errorCodeOrSize > 0) {
uPortLog("U_CELL_CFG: greeting message is \"%s\".\n", pStr);
} else if (errorCodeOrSize == 0) {
uPortLog("U_CELL_CFG: no greeting message is set.\n");
} else {
uPortLog("U_CELL_CFG: unable to read greeting message.\n");
}
Expand Down
2 changes: 2 additions & 0 deletions cell/src/u_cell_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ typedef struct uCellPrivateInstance_t {
void *pRegistrationStatusCallbackParameter;
void (*pConnectionStatusCallback) (bool, void *);
void *pConnectionStatusCallbackParameter;
void (*pGreetingCallback) (uDeviceHandle_t, void *);
void *pGreetingCallbackParameter;
uCellPrivateNet_t *pScanResults; /**< Anchor for list of network scan results. */
int32_t sockNextLocalPort;
void *pSecurityC2cContext; /**< Hook for a chip to chip security context. */
Expand Down
Loading

0 comments on commit c585e45

Please sign in to comment.