diff --git a/modules/sara_r4/cellular_r4_api.c b/modules/sara_r4/cellular_r4_api.c index c0b59496..70f7f065 100644 --- a/modules/sara_r4/cellular_r4_api.c +++ b/modules/sara_r4/cellular_r4_api.c @@ -237,30 +237,17 @@ static CellularATError_t getDataFromResp( const CellularATCommandResponse_t * pA } /* Data is stored in the next intermediate response. */ - if( pAtResp->pItm->pNext != NULL ) - { - pInputLine = pAtResp->pItm->pNext->pLine; + pInputLine = pAtResp->pItm->pNext->pLine; - if( ( pInputLine != NULL ) && ( dataLenToCopy > 0U ) ) - { - /* Copy the data to the out buffer. */ - ( void ) memcpy( ( void * ) pDataRecv->pData, ( const void * ) pInputLine, dataLenToCopy ); - } - else - { - LogError( ( "Receive Data: paramerter error, data pointer %p, data to copy %u", - pInputLine, dataLenToCopy ) ); - atCoreStatus = CELLULAR_AT_BAD_PARAMETER; - } - } - else if( *pDataRecv->pDataLen == 0U ) + if( ( pInputLine != NULL ) && ( dataLenToCopy > 0U ) ) { - /* Receive command success but no data. */ - LogDebug( ( "Receive Data: no data" ) ); + /* Copy the data to the out buffer. */ + ( void ) memcpy( ( void * ) pDataRecv->pData, ( const void * ) pInputLine, dataLenToCopy ); } else { - LogError( ( "Receive Data: Intermediate response empty" ) ); + LogError( ( "Receive Data: paramerter error, data pointer %p, data to copy %u", + pInputLine, dataLenToCopy ) ); atCoreStatus = CELLULAR_AT_BAD_PARAMETER; } @@ -282,8 +269,6 @@ static CellularPktStatus_t _Cellular_RecvFuncData( CellularContext_t * pContext, const _socketDataRecv_t * pDataRecv = ( _socketDataRecv_t * ) pData; int32_t tempValue = 0; - ( void ) dataLen; - if( pContext == NULL ) { LogError( ( "Receive Data: invalid context" ) ); @@ -314,7 +299,8 @@ static CellularPktStatus_t _Cellular_RecvFuncData( CellularContext_t * pContext, { if( pAtResp->pItm->pNext == NULL ) { - /* No data response. */ + /* Modem return +USORD: 0,"". No data returned since there is no data + * length field in modem response. */ *pDataRecv->pDataLen = 0; } else @@ -341,10 +327,11 @@ static CellularPktStatus_t _Cellular_RecvFuncData( CellularContext_t * pContext, } } - /* Process the data buffer. */ - if( atCoreStatus == CELLULAR_AT_SUCCESS ) + /* Process the data buffer. Modem may also return +USORD: 0,0,"" with 0 data length. + * Process the data response only when data length is greater than 0. */ + if( ( atCoreStatus == CELLULAR_AT_SUCCESS ) && ( *pDataRecv->pDataLen > 0U ) ) { - atCoreStatus = getDataFromResp( pAtResp, pDataRecv, *pDataRecv->pDataLen ); + atCoreStatus = getDataFromResp( pAtResp, pDataRecv, dataLen ); } } } diff --git a/source/cellular_pkthandler.c b/source/cellular_pkthandler.c index a009b701..185d07e1 100644 --- a/source/cellular_pkthandler.c +++ b/source/cellular_pkthandler.c @@ -489,7 +489,16 @@ static CellularPktStatus_t _atParseGetHandler( CellularContext_t * pContext, { /* No URC callback function available, check for generic call back. */ LogDebug( ( "No URC Callback func avail %s, now trying generic URC Callback", pTokenPtr ) ); - _Cellular_ProcessGenericUrc( pContext, pSavePtr ); + + if( pSavePtr != pTokenPtr ) + { + /* pSavePtr != pTokenPtr means the string starts with '+'. + * Restore string to "+pTokenPtr:pSavePtr" for callback function. */ + pTokenPtr--; + *( pSavePtr - 1 ) = ':'; + } + + _Cellular_ProcessGenericUrc( pContext, pTokenPtr ); } return pktStatus; diff --git a/test/unit-test/cellular_pkthandler_utest.c b/test/unit-test/cellular_pkthandler_utest.c index 4fb72da1..7763a91b 100644 --- a/test/unit-test/cellular_pkthandler_utest.c +++ b/test/unit-test/cellular_pkthandler_utest.c @@ -28,6 +28,7 @@ * @brief Unit tests for functions in cellular_pkthandler_internal.h. */ +#include #include #include @@ -59,6 +60,8 @@ 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; void cellularAtParseTokenHandler( CellularContext_t * pContext, char * pInputStr ); @@ -356,12 +359,38 @@ CellularATError_t _CMOCK_Cellular_ATStrDup_CALLBACK( char ** ppDst, return atStatus; } +static void _CMOCK_Cellular_Generic_CALLBACK( const CellularContext_t * pContext, + const char * pRawData, + int cmock_num_calls ) +{ + ( void ) pRawData; + ( void ) pContext; + ( void ) cmock_num_calls; + + if( strcmp( pCompareString, pRawData ) == 0 ) + { + passCompareString = true; + } +} + /* Empty callback function for test. */ void cellularAtParseTokenHandler( CellularContext_t * pContext, char * pInputStr ) { ( void ) pContext; ( void ) pInputStr; + + if( strcmp( pCompareString, pInputStr ) == 0 ) + { + passCompareString = true; + } +} + +static char * getStringAfterColon( char * pInputStr ) +{ + char * ret = memchr( pInputStr, ':', strlen( pInputStr ) ); + + return ret ? ret + 1 : pInputStr + strlen( pInputStr ); } /* ========================================================================== */ @@ -513,7 +542,7 @@ void test__Cellular_HandlePacket_AT_UNSOLICITED_Start_Plus_No_Token_String( void memset( &context, 0, sizeof( CellularContext_t ) ); Cellular_ATStrDup_StubWithCallback( _CMOCK_Cellular_ATStrDup_CALLBACK ); - _Cellular_GenericCallback_Ignore(); + pktStatus = _Cellular_HandlePacket( &context, AT_UNSOLICITED, CELLULAR_PLUS_TOKEN_ONLY_STRING ); TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_BAD_REQUEST, pktStatus ); } @@ -527,9 +556,8 @@ void test__Cellular_HandlePacket_AT_UNSOLICITED_Too_Large_String( void ) CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK; memset( &context, 0, sizeof( CellularContext_t ) ); - Cellular_ATStrDup_StubWithCallback( _CMOCK_Cellular_ATStrDup_CALLBACK ); - _Cellular_GenericCallback_Ignore(); + pktStatus = _Cellular_HandlePacket( &context, AT_UNSOLICITED, CELLULAR_SAMPLE_PREFIX_STRING_LARGE_INPUT ); TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_FAILURE, pktStatus ); } @@ -546,7 +574,7 @@ void test__Cellular_HandlePacket_AT_UNSOLICITED_Null_Parse_Function( void ) /* copy the token table. */ ( void ) memcpy( &context.tokenTable, &tokenTableWoParseFunc, sizeof( CellularTokenTable_t ) ); Cellular_ATStrDup_StubWithCallback( _CMOCK_Cellular_ATStrDup_CALLBACK ); - _Cellular_GenericCallback_Ignore(); + pktStatus = _Cellular_HandlePacket( &context, AT_UNSOLICITED, CELLULAR_URC_TOKEN_STRING_INPUT ); TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_FAILURE, pktStatus ); } @@ -563,9 +591,14 @@ void test__Cellular_HandlePacket_AT_UNSOLICITED_Happy_Path( void ) /* copy the token table. */ ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) ); Cellular_ATStrDup_StubWithCallback( _CMOCK_Cellular_ATStrDup_CALLBACK ); - _Cellular_GenericCallback_Ignore(); + + /* set for cellularAtParseTokenHandler function */ + passCompareString = false; + pCompareString = getStringAfterColon( CELLULAR_URC_TOKEN_STRING_INPUT_START_PLUS ); + pktStatus = _Cellular_HandlePacket( &context, AT_UNSOLICITED, CELLULAR_URC_TOKEN_STRING_INPUT_START_PLUS ); TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + TEST_ASSERT_EQUAL( true, passCompareString ); } /** @@ -581,9 +614,15 @@ void test__Cellular_HandlePacket_AT_UNSOLICITED_Input_String_Greater_Than_Urc_To /* Test the greater string size in comparison function. */ ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) ); Cellular_ATStrDup_StubWithCallback( _CMOCK_Cellular_ATStrDup_CALLBACK ); - _Cellular_GenericCallback_Ignore(); + + /* set for generic callback function */ + passCompareString = false; + pCompareString = CELLULAR_URC_TOKEN_STRING_GREATER_INPUT; + _Cellular_GenericCallback_Stub( _CMOCK_Cellular_Generic_CALLBACK ); + pktStatus = _Cellular_HandlePacket( &context, AT_UNSOLICITED, CELLULAR_URC_TOKEN_STRING_GREATER_INPUT ); TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + TEST_ASSERT_EQUAL( true, passCompareString ); } /** @@ -600,9 +639,15 @@ void test__Cellular_HandlePacket_AT_UNSOLICITED_Input_String_Less_Than_Urc_Token /* Test the smaller string size in comparison function. */ Cellular_ATStrDup_StubWithCallback( _CMOCK_Cellular_ATStrDup_CALLBACK ); - _Cellular_GenericCallback_Ignore(); + + /* set for generic callback function */ + passCompareString = false; + pCompareString = CELLULAR_URC_TOKEN_STRING_SMALLER_INPUT; + _Cellular_GenericCallback_Stub( _CMOCK_Cellular_Generic_CALLBACK ); + pktStatus = _Cellular_HandlePacket( &context, AT_UNSOLICITED, CELLULAR_URC_TOKEN_STRING_SMALLER_INPUT ); TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + TEST_ASSERT_EQUAL( true, passCompareString ); } /** @@ -620,6 +665,29 @@ void test__Cellular_HandlePacket_Wrong_RespType( void ) TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_BAD_PARAM, pktStatus ); } +/** + * @brief Test that URC with colon for _Cellular_HandlePacket when token is not in the token table. + */ +void test__Cellular_HandlePacket_AT_UNSOLICITED_Input_String_With_Colon_Not_In_Urc_Token_Path( void ) +{ + CellularContext_t context; + CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK; + + memset( &context, 0, sizeof( CellularContext_t ) ); + /* copy the token table. */ + ( void ) memcpy( &context.tokenTable, &tokenTableWoParseFunc, sizeof( CellularTokenTable_t ) ); + Cellular_ATStrDup_StubWithCallback( _CMOCK_Cellular_ATStrDup_CALLBACK ); + + /* set for generic callback function */ + passCompareString = false; + pCompareString = CELLULAR_AT_MULTI_DATA_WO_PREFIX_STRING_RESP; + _Cellular_GenericCallback_Stub( _CMOCK_Cellular_Generic_CALLBACK ); + + pktStatus = _Cellular_HandlePacket( &context, AT_UNSOLICITED, CELLULAR_AT_MULTI_DATA_WO_PREFIX_STRING_RESP ); + TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + TEST_ASSERT_EQUAL( true, passCompareString ); +} + /** * @brief Test that null Context case for _Cellular_PktHandler_AtcmdRequestWithCallback. */