diff --git a/docs/doxygen/include/size_table.md b/docs/doxygen/include/size_table.md
index 5e8032d3..18d9c478 100644
--- a/docs/doxygen/include/size_table.md
+++ b/docs/doxygen/include/size_table.md
@@ -24,27 +24,27 @@
cellular_common_api.c |
+ 0.7K |
0.6K |
- 0.5K |
cellular_common.c |
- 1.6K |
+ 1.7K |
1.5K |
cellular_pkthandler.c |
- 1.5K |
- 1.4K |
+ 1.7K |
+ 1.6K |
cellular_pktio.c |
+ 2.0K |
1.8K |
- 1.6K |
Total estimates |
- 14.2K |
- 12.9K |
+ 14.8K |
+ 13.4K |
diff --git a/lexicon.txt b/lexicon.txt
index c101ded0..f7097e64 100644
--- a/lexicon.txt
+++ b/lexicon.txt
@@ -547,6 +547,8 @@ pktioreadthread
pktiosendatcmd
pktiosenddata
pktioshutdown
+pktrequestmutex
+pktrespmutex
pktrespqueue
pktrxcallback
pktstatus
@@ -799,6 +801,7 @@ technoloyg
tempvalue
testindex
testresultnumber
+threadreturn
threadroutine
ticktype
timeoutatcmddatarecvrequestwithcallback
diff --git a/modules/hl7802/cellular_hl7802.c b/modules/hl7802/cellular_hl7802.c
index f23239c3..99cd9873 100644
--- a/modules/hl7802/cellular_hl7802.c
+++ b/modules/hl7802/cellular_hl7802.c
@@ -335,6 +335,15 @@ CellularError_t Cellular_ModuleEnableUE( CellularContext_t * pContext )
{
CellularError_t cellularStatus = CELLULAR_SUCCESS;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ CellularAtReq_t atReqGetWoPrefix =
+ {
+ NULL,
+ CELLULAR_AT_WO_PREFIX,
+ NULL,
+ NULL,
+ NULL,
+ 0
+ };
CellularAtReq_t atReqGetNoResult =
{
NULL,
@@ -351,8 +360,8 @@ CellularError_t Cellular_ModuleEnableUE( CellularContext_t * pContext )
if( pContext != NULL )
{
/* Disable echo. */
- atReqGetNoResult.pAtCmd = "ATE0";
- cellularStatus = sendAtCommandWithRetryTimeout( pContext, &atReqGetNoResult,
+ atReqGetWoPrefix.pAtCmd = "ATE0";
+ cellularStatus = sendAtCommandWithRetryTimeout( pContext, &atReqGetWoPrefix,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
if( cellularStatus == CELLULAR_SUCCESS )
@@ -464,8 +473,8 @@ CellularError_t Cellular_ModuleEnableUE( CellularContext_t * pContext )
if( cellularStatus == CELLULAR_SUCCESS )
{
Platform_Delay( CELLULAR_HL7802_RESET_DELAY_MS );
- atReqGetNoResult.pAtCmd = "ATE0";
- cellularStatus = sendAtCommandWithRetryTimeout( pContext, &atReqGetNoResult,
+ atReqGetWoPrefix.pAtCmd = "ATE0";
+ cellularStatus = sendAtCommandWithRetryTimeout( pContext, &atReqGetWoPrefix,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
}
}
diff --git a/modules/sara_r4/cellular_r4.c b/modules/sara_r4/cellular_r4.c
index 8efbc5b9..07b4e444 100644
--- a/modules/sara_r4/cellular_r4.c
+++ b/modules/sara_r4/cellular_r4.c
@@ -262,7 +262,15 @@ CellularError_t rebootCellularModem( CellularContext_t * pContext,
CellularError_t cellularStatus = CELLULAR_SUCCESS;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
uint32_t count = 0;
-
+ CellularAtReq_t atReqGetWoPrefix =
+ {
+ NULL,
+ CELLULAR_AT_WO_PREFIX,
+ NULL,
+ NULL,
+ NULL,
+ 0
+ };
CellularAtReq_t atReqGetNoResult =
{
"AT+CFUN=15",
@@ -283,9 +291,9 @@ CellularError_t rebootCellularModem( CellularContext_t * pContext,
{
LogInfo( ( "rebootCellularModem: Use ATE0 command to test modem status." ) );
- atReqGetNoResult.pAtCmd = "ATE0";
+ atReqGetWoPrefix.pAtCmd = "ATE0";
- pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqGetNoResult, ENBABLE_MODULE_UE_REBOOT_POLL_TIME );
+ pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqGetWoPrefix, ENBABLE_MODULE_UE_REBOOT_POLL_TIME );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
if( cellularStatus == CELLULAR_SUCCESS )
diff --git a/source/cellular_common.c b/source/cellular_common.c
index 03852666..911cc536 100644
--- a/source/cellular_common.c
+++ b/source/cellular_common.c
@@ -1115,6 +1115,7 @@ CellularError_t _Cellular_RegisterUndefinedRespCallback( CellularContext_t * pCo
else
{
/* undefinedRespCallback can be set to NULL to unregister the callback. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->undefinedRespCallback = undefinedRespCallback;
if( pContext->undefinedRespCallback != NULL )
@@ -1125,6 +1126,8 @@ CellularError_t _Cellular_RegisterUndefinedRespCallback( CellularContext_t * pCo
{
pContext->pUndefinedRespCBContext = NULL;
}
+
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
}
return cellularStatus;
diff --git a/source/cellular_common_api.c b/source/cellular_common_api.c
index c936b22d..5c010d54 100644
--- a/source/cellular_common_api.c
+++ b/source/cellular_common_api.c
@@ -206,8 +206,10 @@ CellularError_t Cellular_CommonRegisterUrcNetworkRegistrationEventCallback( Cell
}
else
{
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->cbEvents.networkRegistrationCallback = networkRegistrationCallback;
pContext->cbEvents.pNetworkRegistrationCallbackContext = pCallbackContext;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
}
return cellularStatus;
@@ -231,8 +233,10 @@ CellularError_t Cellular_CommonRegisterUrcPdnEventCallback( CellularHandle_t cel
}
else
{
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->cbEvents.pdnEventCallback = pdnEventCallback;
pContext->cbEvents.pPdnEventCallbackContext = pCallbackContext;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
}
return cellularStatus;
@@ -256,8 +260,10 @@ CellularError_t Cellular_CommonRegisterUrcSignalStrengthChangedCallback( Cellula
}
else
{
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->cbEvents.signalStrengthChangedCallback = signalStrengthChangedCallback;
pContext->cbEvents.pSignalStrengthChangedCallbackContext = pCallbackContext;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
}
return cellularStatus;
@@ -281,8 +287,10 @@ CellularError_t Cellular_CommonRegisterUrcGenericCallback( CellularHandle_t cell
}
else
{
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->cbEvents.genericCallback = genericCallback;
pContext->cbEvents.pGenericCallbackContext = pCallbackContext;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
}
return cellularStatus;
@@ -306,8 +314,10 @@ CellularError_t Cellular_CommonRegisterModemEventCallback( CellularHandle_t cell
}
else
{
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->cbEvents.modemEventCallback = modemEventCallback;
pContext->cbEvents.pModemEventCallbackContext = pCallbackContext;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
}
return cellularStatus;
diff --git a/source/cellular_pkthandler.c b/source/cellular_pkthandler.c
index dd591129..13e99427 100644
--- a/source/cellular_pkthandler.c
+++ b/source/cellular_pkthandler.c
@@ -81,6 +81,8 @@ static void _Cellular_ProcessGenericUrc( const CellularContext_t * pContext,
static CellularPktStatus_t _atParseGetHandler( CellularContext_t * pContext,
const char * pTokenPtr,
char * pSavePtr );
+static CellularPktStatus_t _handleUndefinedMessage( CellularContext_t * pContext,
+ const char * pLine );
/*-----------------------------------------------------------*/
@@ -93,7 +95,6 @@ static CellularPktStatus_t _convertAndQueueRespPacket( CellularContext_t * pCont
if( ( pBuf != NULL ) )
{
pAtResp = ( const CellularATCommandResponse_t * ) pBuf;
- PlatformMutex_Lock( &pContext->PktRespMutex );
if( pAtResp->status == false )
{
@@ -115,8 +116,6 @@ static CellularPktStatus_t _convertAndQueueRespPacket( CellularContext_t * pCont
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
LogError( ( "_convertAndQueueRespPacket: Got a response when the Resp Q is full!!" ) );
}
-
- PlatformMutex_Unlock( &pContext->PktRespMutex );
}
else
{
@@ -217,12 +216,16 @@ static CellularPktStatus_t _Cellular_AtcmdRequestTimeoutWithCallbackRaw( Cellula
}
else
{
+ LogDebug( ( ">>>>>Start sending [%s]<<<<<", atReq.pAtCmd ) );
+
/* Fill in request info structure. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->pktRespCB = atReq.respCallback;
- LogDebug( ( ">>>>>Start sending [%s]<<<<<", atReq.pAtCmd ) );
pContext->pPktUsrData = atReq.pData;
pContext->PktUsrDataLen = ( uint16_t ) atReq.dataLen;
pContext->pCurrentCmd = atReq.pAtCmd;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
pktStatus = _Cellular_PktioSendAtCmd( pContext, atReq.pAtCmd, atReq.atCmdType, atReq.pAtRspPrefix );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
@@ -252,9 +255,11 @@ static CellularPktStatus_t _Cellular_AtcmdRequestTimeoutWithCallbackRaw( Cellula
}
/* No command is waiting response. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->PktioAtCmdType = CELLULAR_AT_NO_COMMAND;
pContext->pktRespCB = NULL;
pContext->pCurrentCmd = NULL;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
LogDebug( ( "<<<<>>>>Start sending Data <<<<<" ) );
+
+ /* Send the packet. Data send is regarded as CELLULAR_AT_NO_RESULT. Only
+ * success or error token is expected in the result. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->PktioAtCmdType = CELLULAR_AT_NO_RESULT;
- /* Send the packet. */
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
*dataReq.pSentDataLength = _Cellular_PktioSendData( pContext, dataReq.pData, dataReq.dataLen );
if( *dataReq.pSentDataLength != dataReq.dataLen )
@@ -331,7 +341,11 @@ static CellularPktStatus_t _Cellular_DataSendWithTimeoutDelayRaw( CellularContex
LogError( ( "pkt_recv status=%d, data sending timed out", pktStatus ) );
}
+ /* Set AT command type to CELLULAR_AT_NO_COMMAND for timeout case here. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->PktioAtCmdType = CELLULAR_AT_NO_COMMAND;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
LogDebug( ( "<<<<>>>>", pktStatus ) );
}
@@ -479,6 +493,41 @@ static CellularPktStatus_t _atParseGetHandler( CellularContext_t * pContext,
/*-----------------------------------------------------------*/
+/*
+ * @brief Handle AT_UNDEFINED message type.
+ */
+static CellularPktStatus_t _handleUndefinedMessage( CellularContext_t * pContext,
+ const char * pLine )
+{
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+
+ LogInfo( ( "AT_UNDEFINED message received %s\r\n", pLine ) );
+
+ /* undefined message received. Try to handle it with cellular module
+ * specific handler. */
+ if( pContext->undefinedRespCallback == NULL )
+ {
+ LogError( ( "No undefined callback for AT_UNDEFINED type message %s received.",
+ pLine ) );
+ pktStatus = CELLULAR_PKT_STATUS_INVALID_DATA;
+ }
+ else
+ {
+ pktStatus = pContext->undefinedRespCallback( pContext->pUndefinedRespCBContext, pLine );
+
+ if( pktStatus != CELLULAR_PKT_STATUS_OK )
+ {
+ LogError( ( "undefinedRespCallback returns error %d for AT_UNDEFINED type message %s received.",
+ pktStatus, pLine ) );
+ pktStatus = CELLULAR_PKT_STATUS_INVALID_DATA;
+ }
+ }
+
+ return pktStatus;
+}
+
+/*-----------------------------------------------------------*/
+
void _Cellular_PktHandlerCleanup( CellularContext_t * pContext )
{
if( ( pContext != NULL ) && ( pContext->pktRespQueue != NULL ) )
@@ -513,6 +562,11 @@ CellularPktStatus_t _Cellular_HandlePacket( CellularContext_t * pContext,
pktStatus = _processUrcPacket( pContext, pBuf );
break;
+ case AT_UNDEFINED:
+ pktStatus = _handleUndefinedMessage( pContext, pBuf );
+
+ break;
+
default:
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
LogError( ( "_Cellular_HandlePacket Callback type (%d) error", atRespType ) );
@@ -573,11 +627,21 @@ CellularPktStatus_t _Cellular_AtcmdRequestSuccessToken( CellularContext_t * pCon
else
{
_Cellular_PktHandlerAcquirePktRequestMutex( pContext );
+
+ /* Set the extra Token table for this AT command. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->tokenTable.pCellularSrcExtraTokenSuccessTable = pCellularSrcTokenSuccessTable;
pContext->tokenTable.cellularSrcExtraTokenSuccessTableSize = cellularSrcTokenSuccessTableSize;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
pktStatus = _Cellular_AtcmdRequestTimeoutWithCallbackRaw( pContext, atReq, atTimeoutMS );
+
+ /* Clear the extra Token table for this AT command. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->tokenTable.cellularSrcExtraTokenSuccessTableSize = 0;
pContext->tokenTable.pCellularSrcExtraTokenSuccessTable = NULL;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
_Cellular_PktHandlerReleasePktRequestMutex( pContext );
}
@@ -602,11 +666,21 @@ CellularPktStatus_t _Cellular_TimeoutAtcmdDataRecvRequestWithCallback( CellularC
else
{
_Cellular_PktHandlerAcquirePktRequestMutex( pContext );
+
+ /* Set the data receive prefix. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->pktDataPrefixCB = pktDataPrefixCallback;
pContext->pDataPrefixCBContext = pCallbackContext;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
pktStatus = _Cellular_AtcmdRequestTimeoutWithCallbackRaw( pContext, atReq, timeoutMS );
+
+ /* Clear the data receive prefix. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->pktDataPrefixCB = NULL;
pContext->pDataPrefixCBContext = NULL;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
_Cellular_PktHandlerReleasePktRequestMutex( pContext );
}
@@ -634,11 +708,20 @@ CellularPktStatus_t _Cellular_AtcmdDataSend( CellularContext_t * pContext,
else
{
_Cellular_PktHandlerAcquirePktRequestMutex( pContext );
+
+ /* Set the data send prefix callback. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->pktDataSendPrefixCB = pktDataSendPrefixCallback;
pContext->pDataSendPrefixCBContext = pCallbackContext;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
pktStatus = _Cellular_AtcmdRequestTimeoutWithCallbackRaw( pContext, atReq, atTimeoutMS );
+
+ /* Clear the data send prefix callback. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->pDataSendPrefixCBContext = NULL;
pContext->pktDataSendPrefixCB = NULL;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
if( pktStatus == CELLULAR_PKT_STATUS_OK )
{
@@ -682,11 +765,20 @@ CellularPktStatus_t _Cellular_TimeoutAtcmdDataSendSuccessToken( CellularContext_
else
{
_Cellular_PktHandlerAcquirePktRequestMutex( pContext );
+
+ /* Set the extra token table. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->tokenTable.pCellularSrcExtraTokenSuccessTable = pCellularSrcTokenSuccessTable;
pContext->tokenTable.cellularSrcExtraTokenSuccessTableSize = cellularSrcTokenSuccessTableSize;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
pktStatus = _Cellular_AtcmdRequestTimeoutWithCallbackRaw( pContext, atReq, atTimeoutMS );
+
+ /* Clear the extra token table. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->tokenTable.cellularSrcExtraTokenSuccessTableSize = 0;
pContext->tokenTable.pCellularSrcExtraTokenSuccessTable = NULL;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
if( pktStatus == CELLULAR_PKT_STATUS_OK )
{
diff --git a/source/cellular_pktio.c b/source/cellular_pktio.c
index 9f006564..687d9760 100644
--- a/source/cellular_pktio.c
+++ b/source/cellular_pktio.c
@@ -75,18 +75,17 @@ static void _saveATData( char * pLine,
CellularATCommandResponse_t * pResp );
static CellularPktStatus_t _processIntermediateResponse( char * pLine,
CellularATCommandResponse_t * pResp,
- CellularATCommandType_t atType,
- const char * pRespPrefix );
+ CellularATCommandType_t atType );
static CellularATCommandResponse_t * _Cellular_AtResponseNew( void );
static void _Cellular_AtResponseFree( CellularATCommandResponse_t * pResp );
-static CellularPktStatus_t _Cellular_ProcessLine( const CellularContext_t * pContext,
+static CellularPktStatus_t _Cellular_ProcessLine( CellularContext_t * pContext,
char * pLine,
CellularATCommandResponse_t * pResp,
CellularATCommandType_t atType,
const char * pRespPrefix );
static bool urcTokenWoPrefix( const CellularContext_t * pContext,
const char * pLine );
-static _atRespType_t _getMsgType( const CellularContext_t * pContext,
+static _atRespType_t _getMsgType( CellularContext_t * pContext,
const char * pLine,
const char * pRespPrefix );
static CellularCommInterfaceError_t _Cellular_PktRxCallBack( void * pUserData,
@@ -182,13 +181,10 @@ static void _saveATData( char * pLine,
static CellularPktStatus_t _processIntermediateResponse( char * pLine,
CellularATCommandResponse_t * pResp,
- CellularATCommandType_t atType,
- const char * pRespPrefix )
+ CellularATCommandType_t atType )
{
CellularPktStatus_t pkStatus = CELLULAR_PKT_STATUS_PENDING_DATA;
- ( void ) pRespPrefix;
-
switch( atType )
{
case CELLULAR_AT_WO_PREFIX:
@@ -240,10 +236,17 @@ static CellularPktStatus_t _processIntermediateResponse( char * pLine,
break;
case CELLULAR_AT_MULTI_DATA_WO_PREFIX:
- default:
_saveATData( pLine, pResp );
pkStatus = CELLULAR_PKT_STATUS_PENDING_BUFFER;
break;
+
+ default:
+ /* Unexpected message received when sending the AT command. */
+ LogInfo( ( "Undefind message received %s when sending AT command type %d.",
+ pLine, atType ) );
+
+ pkStatus = CELLULAR_PKT_STATUS_INVALID_DATA;
+ break;
}
return pkStatus;
@@ -295,7 +298,7 @@ static void _Cellular_AtResponseFree( CellularATCommandResponse_t * pResp )
/*-----------------------------------------------------------*/
-static CellularPktStatus_t _Cellular_ProcessLine( const CellularContext_t * pContext,
+static CellularPktStatus_t _Cellular_ProcessLine( CellularContext_t * pContext,
char * pLine,
CellularATCommandResponse_t * pResp,
CellularATCommandType_t atType,
@@ -310,6 +313,12 @@ static CellularPktStatus_t _Cellular_ProcessLine( const CellularContext_t * pCon
uint32_t tokenErrorTableSize = 0;
uint32_t tokenExtraTableSize = 0;
+ /* This variable is used in warning message. */
+ ( void ) pRespPrefix;
+
+ /* Lock the response mutex when processing the input line. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
+
if( ( pContext->tokenTable.pCellularSrcTokenErrorTable != NULL ) &&
( pContext->tokenTable.pCellularSrcTokenSuccessTable != NULL ) )
{
@@ -357,7 +366,7 @@ static CellularPktStatus_t _Cellular_ProcessLine( const CellularContext_t * pCon
}
else
{
- pkStatus = _processIntermediateResponse( pLine, pResp, atType, pRespPrefix );
+ pkStatus = _processIntermediateResponse( pLine, pResp, atType );
}
}
}
@@ -371,6 +380,8 @@ static CellularPktStatus_t _Cellular_ProcessLine( const CellularContext_t * pCon
pkStatus ) );
}
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
return pkStatus;
}
@@ -398,7 +409,7 @@ static bool urcTokenWoPrefix( const CellularContext_t * pContext,
/*-----------------------------------------------------------*/
-static _atRespType_t _getMsgType( const CellularContext_t * pContext,
+static _atRespType_t _getMsgType( CellularContext_t * pContext,
const char * pLine,
const char * pRespPrefix )
{
@@ -407,6 +418,9 @@ static _atRespType_t _getMsgType( const CellularContext_t * pContext,
bool inputWithPrefix = false;
bool inputWithSrcPrefix = false;
+ /* Lock the response mutex when deciding message type. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
+
if( pContext->tokenTable.pCellularUrcTokenWoPrefixTable == NULL )
{
atStatus = CELLULAR_AT_ERROR;
@@ -453,6 +467,8 @@ static _atRespType_t _getMsgType( const CellularContext_t * pContext,
}
}
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
return atRespType;
}
@@ -686,45 +702,75 @@ static CellularPktStatus_t _handleMsgType( CellularContext_t * pContext,
if( pkStatus == CELLULAR_PKT_STATUS_OK )
{
+ /* This command is completed. Call the user callback to parse the result. */
if( pContext->pPktioHandlepktCB != NULL )
{
( void ) pContext->pPktioHandlepktCB( pContext, AT_SOLICITED, *ppAtResp );
}
+ /* Reset the command type. Further response from cellular modem won't be
+ * regarded as AT_SOLICITED response. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
+ pContext->PktioAtCmdType = CELLULAR_AT_NO_COMMAND;
+ pContext->pRespPrefix = NULL;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
FREE_AT_RESPONSE_AND_SET_NULL( *ppAtResp );
}
else if( pkStatus == CELLULAR_PKT_STATUS_PENDING_BUFFER )
{
- /* Check data prefix first then store the data if this command has data response. */
+ /* This command expects raw data to be appended to buffer. Check data
+ * prefix first then store the data if this command has data response. */
+ }
+ else if( pkStatus == CELLULAR_PKT_STATUS_PENDING_DATA )
+ {
+ /* The command expects more response line. */
}
else
{
- if( pkStatus != CELLULAR_PKT_STATUS_PENDING_DATA )
- {
- ( void ) memset( pContext->pktioReadBuf, 0, PKTIO_READ_BUFFER_SIZE + 1U );
- pContext->pPktioReadPtr = NULL;
- FREE_AT_RESPONSE_AND_SET_NULL( *ppAtResp );
- /* pContext->pCurrentCmd is not NULL since it is a solicited response. */
- LogError( ( "processLine ERROR, cleaning up! Current command %s", pContext->pCurrentCmd ) );
- }
+ /* A unexpected message received when sending the AT command.Try to
+ * handle it with undefined response callback. */
+ pContext->recvdMsgType = AT_UNDEFINED;
}
}
else
+ {
+ /* This is AT_UNDEFINED when not sending the AT command. */
+ }
+
+ if( pContext->recvdMsgType == AT_UNDEFINED )
{
/* Pktio receives AT_UNDEFINED response from modem. This could be module specific
- * response. Cellular module registers the callback function through _Cellular_RegisterUndefinedRespCallback
- * to handle the response. */
- if( ( pContext->undefinedRespCallback == NULL ) ||
- ( pContext->undefinedRespCallback( pContext->pUndefinedRespCBContext, pLine ) != CELLULAR_PKT_STATUS_OK ) )
+ * response. Call the packet handler callback to handle this message. */
+ if( pContext->pPktioHandlepktCB != NULL )
+ {
+ pkStatus = pContext->pPktioHandlepktCB( pContext, AT_UNDEFINED, pLine );
+ }
+
+ if( pkStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "recvdMsgType is AT_UNDEFINED for Message: %s, cmd %s",
pLine,
( pContext->pCurrentCmd != NULL ? pContext->pCurrentCmd : "NULL" ) ) );
+
+ /* Reset the command type. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
+ pContext->PktioAtCmdType = CELLULAR_AT_NO_COMMAND;
+ pContext->pRespPrefix = NULL;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
+ /* Clean the read buffer and read pointer. */
( void ) memset( pContext->pktioReadBuf, 0, PKTIO_READ_BUFFER_SIZE + 1U );
pContext->pPktioReadPtr = NULL;
pContext->partialDataRcvdLen = 0;
FREE_AT_RESPONSE_AND_SET_NULL( *ppAtResp );
- pkStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
+
+ /* Return invalid data error code. */
+ pkStatus = CELLULAR_PKT_STATUS_INVALID_DATA;
+ }
+ else
+ {
+ /* The undefined response callback handle this message without problem. */
}
}
@@ -779,6 +825,19 @@ static bool _preprocessLine( CellularContext_t * pContext,
bool keepProcess = true;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ CellularATCommandDataPrefixCallback_t pktDataPrefixCB = NULL;
+ void * pDataPrefixCBContext = NULL;
+ CellularATCommandDataSendPrefixCallback_t pktDataSendPrefixCB = NULL;
+ void * pDataSendPrefixCBContext = NULL;
+
+ /* Acquire the response lock to keep consistency. */
+ PlatformMutex_Lock( &pContext->PktRespMutex );
+ pktDataPrefixCB = pContext->pktDataPrefixCB;
+ pDataPrefixCBContext = pContext->pDataPrefixCBContext;
+ pktDataSendPrefixCB = pContext->pktDataSendPrefixCB;
+ pDataSendPrefixCBContext = pContext->pDataSendPrefixCBContext;
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
/* The line only has change line. */
if( *pBytesRead <= 0U )
{
@@ -788,13 +847,13 @@ static bool _preprocessLine( CellularContext_t * pContext,
}
else
{
- if( pContext->pktDataSendPrefixCB != NULL )
+ if( pktDataSendPrefixCB != NULL )
{
/* Check if the AT command response is the data send prefix.
* Data send prefix is an SRC success token for data send AT commmand.
* It is used to indicate modem can receive data now. */
/* This function may fix the data stream if the data send prefix is not a line. */
- pktStatus = pContext->pktDataSendPrefixCB( pContext->pDataSendPrefixCBContext, pTempLine, pBytesRead );
+ pktStatus = pktDataSendPrefixCB( pDataSendPrefixCBContext, pTempLine, pBytesRead );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
@@ -802,7 +861,7 @@ static bool _preprocessLine( CellularContext_t * pContext,
keepProcess = false;
}
}
- else if( pContext->pktDataPrefixCB != NULL )
+ else if( pktDataPrefixCB != NULL )
{
/* Check if the AT command response is the data receive prefix.
* Data receive prefix is an SRC success token for data receive AT commnad.
@@ -811,9 +870,9 @@ static bool _preprocessLine( CellularContext_t * pContext,
/* This function may fix the data stream if the AT response and data
* received are in the same line. */
- pktStatus = pContext->pktDataPrefixCB( pContext->pDataPrefixCBContext,
- pTempLine, *pBytesRead,
- ppStartOfData, &pContext->dataLength );
+ pktStatus = pktDataPrefixCB( pDataPrefixCBContext,
+ pTempLine, *pBytesRead,
+ ppStartOfData, &pContext->dataLength );
if( pktStatus == CELLULAR_PKT_STATUS_OK )
{
@@ -1205,7 +1264,18 @@ CellularPktStatus_t _Cellular_PktioSendAtCmd( CellularContext_t * pContext,
}
else
{
- pContext->pRespPrefix = pAtRspPrefix;
+ PlatformMutex_Lock( &pContext->PktRespMutex );
+
+ if( pAtRspPrefix != NULL )
+ {
+ ( void ) strncpy( pContext->pktRespPrefixBuf, pAtRspPrefix, CELLULAR_CONFIG_MAX_PREFIX_STRING_LENGTH );
+ pContext->pRespPrefix = pContext->pktRespPrefixBuf;
+ }
+ else
+ {
+ pContext->pRespPrefix = NULL;
+ }
+
pContext->PktioAtCmdType = atType;
newCmdLen = cmdLen;
newCmdLen += 1U; /* Include space for \r. */
@@ -1213,6 +1283,8 @@ CellularPktStatus_t _Cellular_PktioSendAtCmd( CellularContext_t * pContext,
( void ) strncpy( pContext->pktioSendBuf, pAtCmd, cmdLen );
pContext->pktioSendBuf[ cmdLen ] = '\r';
+ PlatformMutex_Unlock( &pContext->PktRespMutex );
+
( void ) pContext->pCommIntf->send( pContext->hPktioCommIntf,
( const uint8_t * ) &pContext->pktioSendBuf, newCmdLen,
CELLULAR_COMM_IF_SEND_TIMEOUT_MS, &sentLen );
@@ -1225,7 +1297,7 @@ CellularPktStatus_t _Cellular_PktioSendAtCmd( CellularContext_t * pContext,
/*-----------------------------------------------------------*/
/* Sends data to the modem. */
-uint32_t _Cellular_PktioSendData( const CellularContext_t * pContext,
+uint32_t _Cellular_PktioSendData( CellularContext_t * pContext,
const uint8_t * pData,
uint32_t dataLen )
{
diff --git a/source/include/cellular_config_defaults.h b/source/include/cellular_config_defaults.h
index f8e7303a..10b08705 100644
--- a/source/include/cellular_config_defaults.h
+++ b/source/include/cellular_config_defaults.h
@@ -387,6 +387,18 @@
#define CELLULAR_AT_COMMAND_RAW_TIMEOUT_MS ( 5000U )
#endif
+/**
+ * @brief Cellular AT command response prefix string length.
+ *
+ * The maximum length of AT command response prefix string.
+ *
+ * Possible values:`Any positive integer`
+ * Default value (if undefined): 32
+ */
+#ifndef CELLULAR_CONFIG_MAX_PREFIX_STRING_LENGTH
+ #define CELLULAR_CONFIG_MAX_PREFIX_STRING_LENGTH ( 32U )
+#endif
+
/**
* @brief Macro that is called in the cellular library for logging "Error" level
* messages.
diff --git a/source/include/private/cellular_common_internal.h b/source/include/private/cellular_common_internal.h
index 798560dc..4d8011e7 100644
--- a/source/include/private/cellular_common_internal.h
+++ b/source/include/private/cellular_common_internal.h
@@ -113,8 +113,8 @@ struct CellularContext
CellularTokenTable_t tokenTable;
/* Packet handler. */
- PlatformMutex_t pktRequestMutex;
- PlatformMutex_t PktRespMutex;
+ PlatformMutex_t pktRequestMutex; /* The mutex for sending request. */
+ PlatformMutex_t PktRespMutex; /* The mutex for parsing the response from modem. */
QueueHandle_t pktRespQueue;
CellularATCommandResponseReceivedCallback_t pktRespCB;
CellularATCommandDataPrefixCallback_t pktDataPrefixCB; /* Data prefix callback function for socket receive function. */
@@ -135,6 +135,7 @@ struct CellularContext
char pktioReadBuf[ PKTIO_READ_BUFFER_SIZE + 1 ];
char * pPktioReadPtr;
const char * pRespPrefix;
+ char pktRespPrefixBuf[ CELLULAR_CONFIG_MAX_PREFIX_STRING_LENGTH ];
CellularATCommandType_t PktioAtCmdType;
_atRespType_t recvdMsgType;
CellularUndefinedRespCallback_t undefinedRespCallback;
diff --git a/source/include/private/cellular_pktio_internal.h b/source/include/private/cellular_pktio_internal.h
index 2ec8e51f..9d4771e0 100644
--- a/source/include/private/cellular_pktio_internal.h
+++ b/source/include/private/cellular_pktio_internal.h
@@ -129,7 +129,7 @@ CellularPktStatus_t _Cellular_PktioSendAtCmd( CellularContext_t * pContext,
*
* @return The data actually send to the comm interface.
*/
-uint32_t _Cellular_PktioSendData( const CellularContext_t * pContext,
+uint32_t _Cellular_PktioSendData( CellularContext_t * pContext,
const uint8_t * pData,
uint32_t dataLen );
diff --git a/test/unit-test/cellular_pkthandler_utest.c b/test/unit-test/cellular_pkthandler_utest.c
index 49ca2579..bc16e8b6 100644
--- a/test/unit-test/cellular_pkthandler_utest.c
+++ b/test/unit-test/cellular_pkthandler_utest.c
@@ -56,12 +56,15 @@
#define CELLULAR_SAMPLE_PREFIX_STRING_LARGE_INPUT "+CPIN:Story for Littel Red Riding Hood: Once upon a time there was a dear little girl who was loved by every one who looked at her, but most of all by her grandmother, and there was nothing that she would not have given to the child. Once she gave her a little cap of red velvet, which suited her so well that she would never wear anything else. So she was always called Little Red Riding Hood."
#define CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ( 32U )
+#define CELLULAR_AT_UNDEFINED_STRING_RESP "undefined_string"
+
static uint16_t queueData = CELLULAR_PKT_STATUS_BAD_PARAM;
static int32_t queueReturnFail = 0;
static int32_t queueCreateFail = 0;
static int32_t pktRespCBReturn = 0;
static bool passCompareString = false;
static char * pCompareString = NULL;
+static int32_t undefinedCallbackContext = 0;
void cellularAtParseTokenHandler( CellularContext_t * pContext,
char * pInputStr );
@@ -393,6 +396,30 @@ static char * getStringAfterColon( char * pInputStr )
return ret ? ret + 1 : pInputStr + strlen( pInputStr );
}
+static CellularPktStatus_t undefinedRespCallback( void * pCallbackContext,
+ const char * pLine )
+{
+ CellularPktStatus_t undefineReturnStatus = CELLULAR_PKT_STATUS_OK;
+
+ /* Verify pCallbackContext. */
+ TEST_ASSERT_EQUAL_PTR( &undefinedCallbackContext, pCallbackContext );
+
+ /* Verify pLine. */
+ if( strcmp( CELLULAR_AT_UNDEFINED_STRING_RESP, pLine ) == 0 )
+ {
+ *( ( int32_t * ) pCallbackContext ) = 1;
+ undefineReturnStatus = CELLULAR_PKT_STATUS_OK;
+ }
+ else
+ {
+ *( ( int32_t * ) pCallbackContext ) = 0;
+ undefineReturnStatus = CELLULAR_PKT_STATUS_FAILURE;
+ }
+
+ return undefineReturnStatus;
+}
+
+
/* ========================================================================== */
/**
@@ -651,7 +678,7 @@ void test__Cellular_HandlePacket_AT_UNSOLICITED_Input_String_Less_Than_Urc_Token
}
/**
- * @brief Test that null buffer AT_UNDEFINED case for _Cellular_HandlePacket.
+ * @brief Test that null buffer invalid message type case for _Cellular_HandlePacket.
*/
void test__Cellular_HandlePacket_Wrong_RespType( void )
{
@@ -660,11 +687,92 @@ void test__Cellular_HandlePacket_Wrong_RespType( void )
memset( &context, 0, sizeof( CellularContext_t ) );
- pktStatus = _Cellular_HandlePacket( &context, AT_UNDEFINED, NULL );
+ /* Send invalid message type. */
+ pktStatus = _Cellular_HandlePacket( &context, AT_UNDEFINED + 1, NULL );
TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_BAD_PARAM, pktStatus );
}
+/**
+ * @brief Test _Cellular_HandlePacket function with AT_UNDEFINED message type.
+ *
+ * AT_UNDEFINED message type is received. A callback function handles the message
+ * without problem. CELLULAR_PKT_STATUS_OK should be returned.
+ */
+void test__Cellular_HandlePacket_AT_UNDEFINED_with_undefined_callback_okay( void )
+{
+ CellularContext_t context;
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ char undefinedCallbackStr[] = CELLULAR_AT_UNDEFINED_STRING_RESP;
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+
+ /* Set undefined response callback. */
+ undefinedCallbackContext = 0;
+ context.undefinedRespCallback = undefinedRespCallback;
+ context.pUndefinedRespCBContext = &undefinedCallbackContext;
+
+ /* Send AT_UNDEFINED message. */
+ pktStatus = _Cellular_HandlePacket( &context, AT_UNDEFINED, undefinedCallbackStr );
+
+ /* CELLULAR_PKT_STATUS_OK should be returned, since it is handled. */
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
+
+ /* Verify undefinedRespCallback is called and the expected string is received. */
+ TEST_ASSERT_EQUAL_INT32( 1, undefinedCallbackContext );
+}
+
+/**
+ * @brief Test _Cellular_HandlePacket function with AT_UNDEFINED message type.
+ *
+ * AT_UNDEFINED message type is received. A callback function handles the message
+ * but fail to recognized the undefined response. CELLULAR_PKT_STATUS_INVALID_DATA
+ * should be returned.
+ */
+void test__Cellular_HandlePacket_AT_UNDEFINED_with_undefined_callback_fail( void )
+{
+ CellularContext_t context;
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ char undefinedCallbackStr[] = "RandomString";
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+
+ /* Set undefined response callback. */
+ undefinedCallbackContext = 1;
+ context.undefinedRespCallback = undefinedRespCallback;
+ context.pUndefinedRespCBContext = &undefinedCallbackContext;
+
+ /* Send AT_UNDEFINED message. */
+ pktStatus = _Cellular_HandlePacket( &context, AT_UNDEFINED, undefinedCallbackStr );
+
+ /* CELLULAR_PKT_STATUS_INVALID_DATA should be returned. */
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_INVALID_DATA, pktStatus );
+
+ /* Verify undefinedRespCallback is called and the expected string is received. */
+ TEST_ASSERT_EQUAL_INT32( 0, undefinedCallbackContext );
+}
+
+/**
+ * @brief Test _Cellular_HandlePacket function with AT_UNDEFINED message type.
+ *
+ * AT_UNDEFINED message type is received. No callback function is registered to handle
+ * the undefined message. CELLULAR_PKT_STATUS_INVALID_DATA should be returned.
+ */
+void test__Cellular_HandlePacket_AT_UNDEFINED_without_undefined_callback( void )
+{
+ CellularContext_t context;
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ char undefinedCallbackStr[] = CELLULAR_AT_UNDEFINED_STRING_RESP;
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+
+ /* Send AT_UNDEFINED message. */
+ pktStatus = _Cellular_HandlePacket( &context, AT_UNDEFINED, undefinedCallbackStr );
+
+ /* CELLULAR_PKT_STATUS_INVALID_DATA should be returned. */
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_INVALID_DATA, pktStatus );
+}
+
/**
* @brief Test that URC with colon for _Cellular_HandlePacket when token is not in the token table.
*/
diff --git a/test/unit-test/cellular_pktio_utest.c b/test/unit-test/cellular_pktio_utest.c
index 86a76cc8..fabf0a86 100644
--- a/test/unit-test/cellular_pktio_utest.c
+++ b/test/unit-test/cellular_pktio_utest.c
@@ -83,6 +83,12 @@ struct _cellularCommContext
int test3;
};
+typedef enum commIfRecvType
+{
+ COMM_IF_RECV_CUSTOM_STRING,
+ COMM_IF_RECV_NORMAL
+} commIfRecvType_t;
+
static uint16_t pktioEvtMask = 0x0000U;
static MockPlatformEventGroup_t evtGroup = { 0 };
@@ -113,6 +119,11 @@ static int setpktDataPrefixCBReturn = 0;
static int32_t customCallbackContext = 0;
+static commIfRecvType_t testCommIfRecvType = COMM_IF_RECV_NORMAL;
+static char * pCommIntfRecvCustomString = NULL;
+
+static bool atCmdStatusUndefindTest = false;
+
/* Try to Keep this map in Alphabetical order. */
/* FreeRTOS Cellular Common Library porting interface. */
/* coverity[misra_c_2012_rule_8_7_violation] */
@@ -208,6 +219,9 @@ void setUp()
setpktDataPrefixCBReturn = 0;
testInfiniteLoop = 0;
evtGroupHandle = &evtGroup;
+
+ testCommIfRecvType = COMM_IF_RECV_NORMAL;
+ pCommIntfRecvCustomString = NULL;
}
/* Called after each test method. */
@@ -233,6 +247,16 @@ void dummyDelay( uint32_t milliseconds )
( void ) milliseconds;
}
+void MockPlatformMutex_Unlock( PlatformMutex_t * pMutex )
+{
+ ( void ) pMutex;
+}
+
+void MockPlatformMutex_Lock( PlatformMutex_t * pMutex )
+{
+ ( void ) pMutex;
+}
+
void * mock_malloc( size_t size )
{
return ( void * ) malloc( size );
@@ -360,9 +384,9 @@ bool Platform_CreateDetachedThread( void ( * threadRoutine )( void * pArgument )
return threadReturn;
}
-static CellularCommInterfaceError_t _prvCommIntfOpen( CellularCommInterfaceReceiveCallback_t receiveCallback,
- void * pUserData,
- CellularCommInterfaceHandle_t * pCommInterfaceHandle )
+static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiveCallback_t receiveCallback,
+ void * pUserData,
+ CellularCommInterfaceHandle_t * pCommInterfaceHandle )
{
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
@@ -376,9 +400,9 @@ static CellularCommInterfaceError_t _prvCommIntfOpen( CellularCommInterfaceRecei
return commIntRet;
}
-static CellularCommInterfaceError_t _prvCommIntfOpenCallrecvCallbackNullContext( CellularCommInterfaceReceiveCallback_t receiveCallback,
- void * pUserData,
- CellularCommInterfaceHandle_t * pCommInterfaceHandle )
+static CellularCommInterfaceError_t prvCommIntfOpenCallrecvCallbackNullContext( CellularCommInterfaceReceiveCallback_t receiveCallback,
+ void * pUserData,
+ CellularCommInterfaceHandle_t * pCommInterfaceHandle )
{
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
@@ -394,7 +418,7 @@ static CellularCommInterfaceError_t _prvCommIntfOpenCallrecvCallbackNullContext(
return commIntRet;
}
-static CellularCommInterfaceError_t _prvCommIntfClose( CellularCommInterfaceHandle_t commInterfaceHandle )
+static CellularCommInterfaceError_t prvCommIntfClose( CellularCommInterfaceHandle_t commInterfaceHandle )
{
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
@@ -403,11 +427,11 @@ static CellularCommInterfaceError_t _prvCommIntfClose( CellularCommInterfaceHand
return commIntRet;
}
-static CellularCommInterfaceError_t _prvCommIntfSend( CellularCommInterfaceHandle_t commInterfaceHandle,
- const uint8_t * pData,
- uint32_t dataLength,
- uint32_t timeoutMilliseconds,
- uint32_t * pDataSentLength )
+static CellularCommInterfaceError_t prvCommIntfSend( CellularCommInterfaceHandle_t commInterfaceHandle,
+ const uint8_t * pData,
+ uint32_t dataLength,
+ uint32_t timeoutMilliseconds,
+ uint32_t * pDataSentLength )
{
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
@@ -422,11 +446,11 @@ static CellularCommInterfaceError_t _prvCommIntfSend( CellularCommInterfaceHandl
return commIntRet;
}
-static CellularCommInterfaceError_t _prvCommIntfReceive( CellularCommInterfaceHandle_t commInterfaceHandle,
- uint8_t * pBuffer,
- uint32_t bufferLength,
- uint32_t timeoutMilliseconds,
- uint32_t * pDataReceivedLength )
+static CellularCommInterfaceError_t prvCommIntfReceiveNormal( CellularCommInterfaceHandle_t commInterfaceHandle,
+ uint8_t * pBuffer,
+ uint32_t bufferLength,
+ uint32_t timeoutMilliseconds,
+ uint32_t * pDataReceivedLength )
{
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
@@ -566,12 +590,70 @@ static CellularCommInterfaceError_t _prvCommIntfReceive( CellularCommInterfaceHa
return commIntRet;
}
+
+static CellularCommInterfaceError_t prvCommIntfReceiveCustomString( CellularCommInterfaceHandle_t commInterfaceHandle,
+ uint8_t * pBuffer,
+ uint32_t bufferLength,
+ uint32_t timeoutMilliseconds,
+ uint32_t * pDataReceivedLength )
+{
+ CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
+
+ ( void ) commInterfaceHandle;
+ ( void ) pBuffer;
+ ( void ) bufferLength;
+ ( void ) timeoutMilliseconds;
+ ( void ) pDataReceivedLength;
+
+ if( recvCount > 0 )
+ {
+ recvCount--;
+
+ ( void ) strncpy( ( char * ) pBuffer, pCommIntfRecvCustomString, bufferLength );
+ *pDataReceivedLength = strlen( pCommIntfRecvCustomString );
+ }
+ else
+ {
+ *pDataReceivedLength = 0;
+ }
+
+ return commIntRet;
+}
+
+static CellularCommInterfaceError_t prvCommIntfReceive( CellularCommInterfaceHandle_t commInterfaceHandle,
+ uint8_t * pBuffer,
+ uint32_t bufferLength,
+ uint32_t timeoutMilliseconds,
+ uint32_t * pDataReceivedLength )
+{
+ CellularCommInterfaceError_t commIfRet;
+
+ if( testCommIfRecvType == COMM_IF_RECV_CUSTOM_STRING )
+ {
+ commIfRet = prvCommIntfReceiveCustomString( commInterfaceHandle,
+ pBuffer,
+ bufferLength,
+ timeoutMilliseconds,
+ pDataReceivedLength );
+ }
+ else
+ {
+ commIfRet = prvCommIntfReceiveNormal( commInterfaceHandle,
+ pBuffer,
+ bufferLength,
+ timeoutMilliseconds,
+ pDataReceivedLength );
+ }
+
+ return commIfRet;
+}
+
static CellularCommInterface_t CellularCommInterface =
{
- .open = _prvCommIntfOpen,
- .send = _prvCommIntfSend,
- .recv = _prvCommIntfReceive,
- .close = _prvCommIntfClose
+ .open = prvCommIntfOpen,
+ .send = prvCommIntfSend,
+ .recv = prvCommIntfReceive,
+ .close = prvCommIntfClose
};
static void _shutdownCallback( CellularContext_t * pContext )
@@ -582,6 +664,56 @@ static void _shutdownCallback( CellularContext_t * pContext )
}
}
+static CellularPktStatus_t prvUndefinedHandlePacket( CellularContext_t * pContext,
+ _atRespType_t atRespType,
+ const void * pBuf )
+{
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ const CellularATCommandResponse_t * pAtResp = NULL;
+ char * pLine = NULL;
+
+ if( pContext != NULL )
+ {
+ switch( atRespType )
+ {
+ case AT_SOLICITED:
+ pAtResp = ( const CellularATCommandResponse_t * ) pBuf;
+ atCmdStatusUndefindTest = pAtResp->status;
+ break;
+
+ case AT_UNSOLICITED:
+ break;
+
+ default:
+ pLine = ( char * ) pBuf;
+
+ /* undefined message received. Try to handle it with cellular module
+ * specific handler. */
+ if( pContext->undefinedRespCallback == NULL )
+ {
+ pktStatus = CELLULAR_PKT_STATUS_INVALID_DATA;
+ }
+ else
+ {
+ pktStatus = pContext->undefinedRespCallback( pContext->pUndefinedRespCBContext, pLine );
+
+ if( pktStatus != CELLULAR_PKT_STATUS_OK )
+ {
+ pktStatus = CELLULAR_PKT_STATUS_INVALID_DATA;
+ }
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
+ }
+
+ return pktStatus;
+}
+
CellularPktStatus_t PktioHandlePacketCallback_t( CellularContext_t * pContext,
_atRespType_t atRespType,
const void * pBuffer )
@@ -822,7 +954,7 @@ void test__Cellular_PktioInit_Thread_Comm_Open_ReceiveCallback_Null_Context_Fail
context.pPktioShutdownCB = _shutdownCallback;
/* Assign the comm interface to pContext. */
- commIntf.open = _prvCommIntfOpenCallrecvCallbackNullContext;
+ commIntf.open = prvCommIntfOpenCallrecvCallbackNullContext;
/* Check that CELLULAR_PKT_STATUS_OK is returned. */
pktStatus = _Cellular_PktioInit( &context, PktioHandlePacketCallback_t );
TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
@@ -1261,7 +1393,7 @@ void test__Cellular_PktioInit_Thread_Rx_Data_Event_AT_UNDEFINED_callback_okay( v
( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) );
/* Check that CELLULAR_PKT_STATUS_OK is returned. */
- pktStatus = _Cellular_PktioInit( &context, PktioHandlePacketCallback_t );
+ pktStatus = _Cellular_PktioInit( &context, prvUndefinedHandlePacket );
TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
/* Verify undefinedRespCallback is called and the expected string is received. */
@@ -1296,13 +1428,202 @@ void test__Cellular_PktioInit_Thread_Rx_Data_Event_AT_UNDEFINED_callback_fail( v
( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) );
/* Check that CELLULAR_PKT_STATUS_OK is returned. */
- pktStatus = _Cellular_PktioInit( &context, PktioHandlePacketCallback_t );
+ pktStatus = _Cellular_PktioInit( &context, prvUndefinedHandlePacket );
TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
/* Verify undefinedRespCallback is called and the expected string is not received. */
TEST_ASSERT_EQUAL_INT32( 0, customCallbackContext );
}
+/**
+ * @brief Test undefined message callback handling okay in pktio thread when sending AT command.
+ *
+ * The following sequence should have no error :
+ * 1. Sending CELLULAR_AT_NO_RESULT type message ( for example, AT+CFUN=1 )
+ * 2. Receiving "OK\r\n", CELLULAR_AT_UNDEFINED_STRING_RESP"\r\n"
+ * 3. The AT command should success. The UNKNOW_TOKEN should cause a call to undefined callback.
+ * 4. Okay is returned in the undefined response callback.
+ */
+void test__Cellular_PktioInit_Thread_Rx_Data_Event_SRC_AT_undefined_callback( void )
+{
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ CellularContext_t context;
+ CellularCommInterface_t * pCommIntf = &CellularCommInterface;
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+
+ /* Assign the comm interface to pContext. */
+ context.pCommIntf = pCommIntf;
+ context.pPktioShutdownCB = _shutdownCallback;
+
+ /* Test the rx_data event with CELLULAR_AT_NO_RESULT type AT command. */
+ atCmdStatusUndefindTest = false;
+ pktioEvtMask = PKTIO_EVT_MASK_RX_DATA;
+ recvCount = 1;
+ atCmdType = CELLULAR_AT_NO_RESULT;
+ testCommIfRecvType = COMM_IF_RECV_CUSTOM_STRING;
+ pCommIntfRecvCustomString = "OK\r\n"CELLULAR_AT_UNDEFINED_STRING_RESP "\r\n";
+
+ /* Setup the callback to handle the undefined message. */
+ context.undefinedRespCallback = undefinedRespCallback;
+ customCallbackContext = 0;
+ context.pUndefinedRespCBContext = &customCallbackContext;
+
+ /* Copy the token table. */
+ ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) );
+
+ /* Check that CELLULAR_PKT_STATUS_OK is returned. */
+ threadReturn = true; /* Set pktio thread return flag. */
+ pktStatus = _Cellular_PktioInit( &context, prvUndefinedHandlePacket );
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
+
+ /* Verify the command should return success. */
+ TEST_ASSERT_EQUAL( atCmdStatusUndefindTest, true );
+
+ /* Verify undefinedRespCallback is called and the expected string is received. */
+ TEST_ASSERT_EQUAL_INT32( 1, customCallbackContext );
+}
+
+/**
+ * @brief Test undefined message callback handling okay in pktio thread when sending AT command.
+ *
+ * The following sequence should have no error :
+ * 1. Sending CELLULAR_AT_NO_RESULT type message ( for example, AT+CFUN=1 )
+ * 2. Receiving CELLULAR_AT_UNDEFINED_STRING_RESP"\r\n", "OK\r\n"
+ * 3. The AT command should success. The UNKNOW_TOKEN should cause a call to undefined callback.
+ * 4. Okay is returned in the undefined response callback.
+ */
+void test__Cellular_PktioInit_Thread_Rx_Data_Event_SRC_AT_undefined_callback_okay( void )
+{
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ CellularContext_t context;
+ CellularCommInterface_t * pCommIntf = &CellularCommInterface;
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+
+ /* Assign the comm interface to pContext. */
+ context.pCommIntf = pCommIntf;
+ context.pPktioShutdownCB = _shutdownCallback;
+
+ /* Test the rx_data event with CELLULAR_AT_NO_RESULT type AT command. */
+ atCmdStatusUndefindTest = false;
+ pktioEvtMask = PKTIO_EVT_MASK_RX_DATA;
+ recvCount = 1;
+ atCmdType = CELLULAR_AT_NO_RESULT;
+ testCommIfRecvType = COMM_IF_RECV_CUSTOM_STRING;
+ pCommIntfRecvCustomString = CELLULAR_AT_UNDEFINED_STRING_RESP "\r\nOK\r\n";
+
+ /* Setup the callback to handle the undefined message. */
+ context.undefinedRespCallback = undefinedRespCallback;
+ customCallbackContext = 0;
+ context.pUndefinedRespCBContext = &customCallbackContext;
+
+ /* Copy the token table. */
+ ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) );
+
+ /* Check that CELLULAR_PKT_STATUS_OK is returned. */
+ threadReturn = true; /* Set pktio thread return flag. */
+ pktStatus = _Cellular_PktioInit( &context, prvUndefinedHandlePacket );
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
+
+ /* Verify the command should return success. */
+ TEST_ASSERT_EQUAL( atCmdStatusUndefindTest, true );
+
+ /* Verify undefinedRespCallback is called and the expected string is received. */
+ TEST_ASSERT_EQUAL_INT32( 1, customCallbackContext );
+}
+
+/**
+ * @brief Test undefined message callback handling error in pktio thread when sending AT command.
+ *
+ * The following sequence should have no error :
+ * 1. Sending CELLULAR_AT_NO_RESULT type message ( for example, AT+CFUN=1 )
+ * 2. Receiving CELLULAR_AT_UNDEFINED_STRING_RESP"\r\n", "OK\r\n"
+ * 3. The AT command should success. The UNKNOW_TOKEN should cause a call to undefined callback.
+ * 4. Error is returned in the undefined response callback. This would flush the
+ * pktio read buffer.
+ */
+void test__Cellular_PktioInit_Thread_Rx_Data_Event_SRC_AT_undefined_callback_fail( void )
+{
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ CellularContext_t context;
+ CellularCommInterface_t * pCommIntf = &CellularCommInterface;
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+
+ /* Assign the comm interface to pContext. */
+ context.pCommIntf = pCommIntf;
+ context.pPktioShutdownCB = _shutdownCallback;
+
+ /* Test the rx_data event with CELLULAR_AT_NO_RESULT type AT command. */
+ atCmdStatusUndefindTest = false;
+ pktioEvtMask = PKTIO_EVT_MASK_RX_DATA;
+ recvCount = 1;
+ atCmdType = CELLULAR_AT_NO_RESULT;
+ testCommIfRecvType = COMM_IF_RECV_CUSTOM_STRING;
+ pCommIntfRecvCustomString = "UNKNOWN_UNDEFINED\r\nOK\r\n";
+
+ /* Setup the callback to handle the undefined message. */
+ context.undefinedRespCallback = undefinedRespCallback;
+ customCallbackContext = 1;
+ context.pUndefinedRespCBContext = &customCallbackContext;
+
+ /* Copy the token table. */
+ ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) );
+
+ /* Check that CELLULAR_PKT_STATUS_OK is returned. */
+ threadReturn = true; /* Set pktio thread return flag. */
+ pktStatus = _Cellular_PktioInit( &context, prvUndefinedHandlePacket );
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
+
+ /* Verify the command should has error. */
+ TEST_ASSERT_EQUAL( atCmdStatusUndefindTest, false );
+
+ /* Verify undefinedRespCallback is called but the expected string is not received. */
+ TEST_ASSERT_EQUAL_INT32( 0, customCallbackContext );
+}
+
+/**
+ * @brief Test undefined message no callback in pktio thread when sending AT command.
+ *
+ * The following sequence should have no error :
+ * 1. Sending CELLULAR_AT_NO_RESULT type message ( for example, AT+CFUN=1 )
+ * 2. Receiving CELLULAR_AT_UNDEFINED_STRING_RESP"\r\n", "OK\r\n"
+ * 3. The AT command should success. The UNKNOW_TOKEN should cause a call to undefined callback.
+ * 4. The command callback won't be called. This would cause a timeout in pkthandler.
+ */
+void test__Cellular_PktioInit_Thread_Rx_Data_Event_SRC_AT_undefined_no_callback_fail( void )
+{
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ CellularContext_t context;
+ CellularCommInterface_t * pCommIntf = &CellularCommInterface;
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+
+ /* Assign the comm interface to pContext. */
+ context.pCommIntf = pCommIntf;
+ context.pPktioShutdownCB = _shutdownCallback;
+
+ /* Test the rx_data event with CELLULAR_AT_NO_RESULT type AT command. */
+ atCmdStatusUndefindTest = false;
+ pktioEvtMask = PKTIO_EVT_MASK_RX_DATA;
+ recvCount = 1;
+ atCmdType = CELLULAR_AT_NO_RESULT;
+ testCommIfRecvType = COMM_IF_RECV_CUSTOM_STRING;
+ pCommIntfRecvCustomString = "UNKNOWN_UNDEFINED\r\nOK\r\n";
+
+ /* Copy the token table. */
+ ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) );
+
+ /* Check that CELLULAR_PKT_STATUS_OK is returned. */
+ threadReturn = true; /* Set pktio thread return flag. */
+ pktStatus = _Cellular_PktioInit( &context, prvUndefinedHandlePacket );
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
+
+ /* Verify the command should has error. */
+ TEST_ASSERT_EQUAL( atCmdStatusUndefindTest, false );
+}
+
/**
* @brief Test thread receiving rx data event with CELLULAR_AT_MULTI_WO_PREFIX resp for _Cellular_PktioInit to return CELLULAR_PKT_STATUS_OK.
*/
@@ -1620,6 +1941,49 @@ void test__Cellular_PktioInit_Thread_Rx_Data_Event_URC_TOKEN_STRING_RESP( void )
TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
}
+/**
+ * @brief Test RX data event _handle_data function.
+ *
+ * pktio read thread is in data mode and expects more data to be received. Modem returns
+ * not enough data to pktio. These data will be stored as partial data.
+ */
+void test__Cellular_PktioInit_Thread_Rx_Data_Event_handle_data( void )
+{
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ CellularContext_t context;
+ CellularCommInterface_t * pCommIntf = &CellularCommInterface;
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+
+ /* Assign the comm interface to pContext. */
+ context.pCommIntf = pCommIntf;
+ context.pPktioShutdownCB = _shutdownCallback;
+
+ /* Test the rx_data event with CELLULAR_AT_NO_RESULT type AT command. */
+ pktioEvtMask = PKTIO_EVT_MASK_RX_DATA;
+ recvCount = 1;
+ atCmdType = CELLULAR_AT_NO_RESULT;
+ testCommIfRecvType = COMM_IF_RECV_CUSTOM_STRING;
+ pCommIntfRecvCustomString = "12345";
+
+ /* Copy the token table. */
+ ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) );
+
+ /* Pktio read thread enter data mode by setting dataLength. */
+ context.dataLength = 10;
+
+ /* Check that CELLULAR_PKT_STATUS_OK is returned. */
+ threadReturn = true; /* Set pktio thread return flag. */
+ pktStatus = _Cellular_PktioInit( &context, prvUndefinedHandlePacket );
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
+
+ /* Store 5 bytes in the partial data. */
+ TEST_ASSERT_EQUAL_UINT( context.partialDataRcvdLen, 5 );
+
+ /* The data is incomplete. pPktioReadPtr should be the same pktioReadBuf. */
+ TEST_ASSERT_EQUAL( context.pPktioReadPtr, context.pktioReadBuf );
+}
+
/**
* @brief Test pkio aborted event case for _Cellular_PktioInit to return CELLULAR_PKT_STATUS_FAILURE.
*/
@@ -1848,6 +2212,34 @@ void test__Cellular_PktioSendAtCmd_Happy_Path( void )
TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
}
+/**
+ * @brief Test that happy path for _Cellular_PktioSendAtCmd.
+ */
+void test__Cellular_PktioSendAtCmd_Happy_Path_No_Prefix( void )
+{
+ CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
+ CellularContext_t context;
+ CellularCommInterface_t * pCommIntf = &CellularCommInterface;
+ struct _cellularCommContext commInterfaceHandle = { 0 };
+ CellularAtReq_t atReqSetRatPriority =
+ {
+ "ATE0",
+ CELLULAR_AT_NO_RESULT,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ };
+
+ memset( &context, 0, sizeof( CellularContext_t ) );
+ context.pCommIntf = pCommIntf;
+ context.hPktioCommIntf = ( CellularCommInterfaceHandle_t ) &commInterfaceHandle;
+ pktStatus = _Cellular_PktioSendAtCmd( &context, atReqSetRatPriority.pAtCmd,
+ atReqSetRatPriority.atCmdType,
+ atReqSetRatPriority.pAtRspPrefix );
+ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus );
+}
+
/**
* @brief Test that any NULL parameter for _Cellular_PktioSendData.
*/