From e69b0fa1cc46df976825b8d2e6ccbb006876f00e Mon Sep 17 00:00:00 2001 From: Ching-Hsin Lee Date: Mon, 20 Nov 2023 18:39:01 +0800 Subject: [PATCH] Update _getMsgType for URC without prefix * Update the logic for port not using URC without prefix table * Check AT command type for response without prefix --- source/cellular_pktio.c | 55 ++++--- test/unit-test/cellular_pktio_utest.c | 223 ++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 21 deletions(-) diff --git a/source/cellular_pktio.c b/source/cellular_pktio.c index 4338717f..5cf94636 100644 --- a/source/cellular_pktio.c +++ b/source/cellular_pktio.c @@ -85,8 +85,8 @@ static CellularPktStatus_t _Cellular_ProcessLine( CellularContext_t * pContext, CellularATCommandResponse_t * pResp, CellularATCommandType_t atType, const char * pRespPrefix ); -static bool urcTokenWoPrefix( const CellularContext_t * pContext, - const char * pLine ); +static bool _checkUrcTokenWoPrefix( const CellularContext_t * pContext, + const char * pLine ); static _atRespType_t _getMsgType( CellularContext_t * pContext, const char * pLine, const char * pRespPrefix ); @@ -409,20 +409,27 @@ static CellularPktStatus_t _Cellular_ProcessLine( CellularContext_t * pContext, /*-----------------------------------------------------------*/ -static bool urcTokenWoPrefix( const CellularContext_t * pContext, - const char * pLine ) +static bool _checkUrcTokenWoPrefix( const CellularContext_t * pContext, + const char * pLine ) { bool ret = false; uint32_t i = 0; uint32_t urcTokenTableSize = pContext->tokenTable.cellularUrcTokenWoPrefixTableSize; const char * const * const pUrcTokenTable = pContext->tokenTable.pCellularUrcTokenWoPrefixTable; - for( i = 0; i < urcTokenTableSize; i++ ) + if( ( pUrcTokenTable == NULL ) || ( urcTokenTableSize == 0 ) ) { - if( strcmp( pLine, pUrcTokenTable[ i ] ) == 0 ) + ret = false; + } + else + { + for( i = 0; i < urcTokenTableSize; i++ ) { - ret = true; - break; + if( strcmp( pLine, pUrcTokenTable[ i ] ) == 0 ) + { + ret = true; + break; + } } } @@ -443,12 +450,7 @@ static _atRespType_t _getMsgType( CellularContext_t * pContext, /* Lock the response mutex when deciding message type. */ PlatformMutex_Lock( &pContext->PktRespMutex ); - if( pContext->tokenTable.pCellularUrcTokenWoPrefixTable == NULL ) - { - atStatus = CELLULAR_AT_ERROR; - atRespType = AT_UNDEFINED; - } - else if( urcTokenWoPrefix( pContext, pLine ) == true ) + if( _checkUrcTokenWoPrefix( pContext, pLine ) == true ) { atRespType = AT_UNSOLICITED; } @@ -459,7 +461,7 @@ static _atRespType_t _getMsgType( CellularContext_t * pContext, if( ( inputWithPrefix == true ) && ( pRespPrefix != NULL ) ) { - /* Check if SRC prefix exist in pLine. */ + /* Check if this line contains prefix expected in AT command response. */ atStatus = Cellular_ATStrStartWith( pLine, pRespPrefix, &inputWithSrcPrefix ); } } @@ -470,23 +472,34 @@ static _atRespType_t _getMsgType( CellularContext_t * pContext, { if( ( pContext->PktioAtCmdType != CELLULAR_AT_NO_COMMAND ) && ( inputWithSrcPrefix == true ) ) { + /* Celluar interface is sending AT command and this line contains + * expected prefix in the response. Return AT_SOLICTIED here. */ atRespType = AT_SOLICITED; } else { + /* Lines with prefix are considered AT_UNSOLICITED unless the prefix + * is expected in AT command response. */ atRespType = AT_UNSOLICITED; } } else { - if( ( ( pContext->PktioAtCmdType != CELLULAR_AT_NO_COMMAND ) && ( pRespPrefix == NULL ) ) || - ( pContext->PktioAtCmdType == CELLULAR_AT_MULTI_DATA_WO_PREFIX ) || - ( pContext->PktioAtCmdType == CELLULAR_AT_WITH_PREFIX ) || - ( pContext->PktioAtCmdType == CELLULAR_AT_MULTI_WITH_PREFIX ) || - ( pContext->PktioAtCmdType == CELLULAR_AT_WITH_PREFIX_NO_RESULT_CODE ) ) + if( pContext->PktioAtCmdType != CELLULAR_AT_NO_COMMAND ) { + /* Cellular interface is waiting for AT command response from + * cellular modem. The token without prefix can be success or error + * token to indicate the AT command status. Return AT_SOLICITED + * here and this line will be parsed in _Cellular_ProcessLine later. */ atRespType = AT_SOLICITED; } + else + { + /* This line doesn't contain any prefix and cellular interface is + * not sending AT command. Therefore, this line is unexpected. + * Return AT_UNDEFINED here. */ + atRespType = AT_UNDEFINED; + } } } @@ -1372,7 +1385,7 @@ CellularPktStatus_t _Cellular_PktioSendAtCmd( CellularContext_t * pContext, { PlatformMutex_Lock( &pContext->PktRespMutex ); - if( pAtRspPrefix != NULL ) + if( ( pAtRspPrefix != NULL ) && ( atType != CELLULAR_AT_WO_PREFIX ) && ( atType != CELLULAR_AT_WO_PREFIX_NO_RESULT_CODE ) ) { ( void ) strncpy( pContext->pktRespPrefixBuf, pAtRspPrefix, CELLULAR_CONFIG_MAX_PREFIX_STRING_LENGTH ); pContext->pRespPrefix = pContext->pktRespPrefixBuf; diff --git a/test/unit-test/cellular_pktio_utest.c b/test/unit-test/cellular_pktio_utest.c index 5e52a4b6..87a3df16 100644 --- a/test/unit-test/cellular_pktio_utest.c +++ b/test/unit-test/cellular_pktio_utest.c @@ -2127,6 +2127,62 @@ void test__Cellular_PktioInit_Thread_Rx_Data_Event_CELLULAR_AT_WITH_PREFIX_STRIN TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); } +/** + * @brief _Cellular_PktioInit - Sending CELLULAR_AT_WITH_PREFIX with empty response prefix. + * + * Empty response prefix will be considered invalid string. Verify AT_UNDEFINED type + * is returnedy in _getMsgType function. + * + * Coverage + * @code{c} + * else + * { + * { + * atStatus = Cellular_ATStrStartWith( pLine, pRespPrefix, &inputWithSrcPrefix ); + * } + * } + * + * if( ( atStatus == CELLULAR_AT_SUCCESS ) && ( atRespType == AT_UNDEFINED ) ) + * { + * ... + * } + * @endcode + * ( atStatus == CELLULAR_AT_SUCCESS ) is false. + * ( atRespType == AT_UNDEFINED ) is true. + */ +void test__Cellular_PktioInit_Thread_Rx_Data_Event_CELLULAR_AT_WITH_PREFIX_empty_prefix( void ) +{ + CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK; + CellularContext_t context; + CellularCommInterface_t * pCommIntf = &CellularCommInterface; + + threadReturn = true; + 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_WITH_PREFIX resp. */ + pktioEvtMask = PKTIO_EVT_MASK_RX_DATA; + recvCount = 4; + atCmdType = CELLULAR_AT_WITH_PREFIX; + /* copy the token table. */ + ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) ); + context.pktDataPrefixCB = NULL; + context.pRespPrefix = ""; /* Use empty string to cover Cellular_ATStrStartWith failed case. */ + + /* API call. */ + pktStatus = _Cellular_PktioInit( &context, PktioHandlePacketCallback_t ); + + /* Validation. */ + TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + /* This command returns an AT_UNDEFINED type, which is unhandled in the test + * test case. Ensure the context is cleaned. */ + TEST_ASSERT_EQUAL( CELLULAR_AT_NO_COMMAND, context.PktioAtCmdType ); + TEST_ASSERT_EQUAL( NULL, context.pRespPrefix ); +} + /** * @brief Test thread receiving rx data event with CELLULAR_AT_WITH_PREFIX_STRING resp for _Cellular_PktioInit to return CELLULAR_PKT_STATUS_OK. */ @@ -2548,6 +2604,63 @@ void test__Cellular_PktioInit_Thread_Rx_Data_Event_URC_TOKEN_STRING_RESP( void ) TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); } +/** + * @brief _Cellular_PktioInit - urcTokenTableSize is set to 0 in _checkUrcTokenWoPrefix. + * + * Cover urcTokenTableSize is set to 0 in _checkUrcTokenWoPrefix. This function + * should return false. Verify AT_UNDEFINED type is returned With input string "TEST1" + * and the context is cleaned for unhandled AT_UNDEFINED type input. + * + * Coverage + * @code{c} + * static bool _checkUrcTokenWoPrefix( const CellularContext_t * pContext, + * const char * pLine ) + * { + * ... + * if( ( pUrcTokenTable == NULL ) || ( urcTokenTableSize == 0 ) ) + * { + * ret = false; + * } + * ... + * } + * @endcode + * ( pUrcTokenTable == NULL ) is false. + * ( urcTokenTableSize == 0 ) is true. + */ +void test__Cellular_PktioInit_Thread_Rx_Data_Event_URC_WO_PREFIX_zero_table_size( void ) +{ + CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK; + CellularContext_t context; + CellularCommInterface_t * pCommIntf = &CellularCommInterface; + + threadReturn = true; + 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_COMMAND resp. */ + pktioEvtMask = PKTIO_EVT_MASK_RX_DATA; + recvCount = 2; + atCmdType = CELLULAR_AT_NO_COMMAND; + + /* copy the token table. */ + ( void ) memcpy( &context.tokenTable, &tokenTable, sizeof( CellularTokenTable_t ) ); + /* Set the URC without prefix table size to 0 for testing here. */ + context.tokenTable.cellularUrcTokenWoPrefixTableSize = 0; + + /* API call. */ + pktStatus = _Cellular_PktioInit( &context, PktioHandlePacketCallback_t ); + + /* Validation. */ + TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + /* This command returns an AT_UNDEFINED type, which is unhandled in the test + * test case. Ensure the context is cleaned. */ + TEST_ASSERT_EQUAL( CELLULAR_AT_NO_COMMAND, context.PktioAtCmdType ); + TEST_ASSERT_EQUAL( NULL, context.pRespPrefix ); +} + /** * @brief Test RX data event _handle_data function. * @@ -2813,10 +2926,16 @@ void test__Cellular_PktioSendAtCmd_Happy_Path( void ) memset( &context, 0, sizeof( CellularContext_t ) ); context.pCommIntf = pCommIntf; context.hPktioCommIntf = ( CellularCommInterfaceHandle_t ) &commInterfaceHandle; + + /* API call. */ pktStatus = _Cellular_PktioSendAtCmd( &context, atReqSetRatPriority.pAtCmd, atReqSetRatPriority.atCmdType, atReqSetRatPriority.pAtRspPrefix ); + + /* Validation. */ TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + /* The context.PrespPrefix should be set to pktRespPrefixBuf. */ + TEST_ASSERT_EQUAL( &context.pktRespPrefixBuf, context.pRespPrefix ); } /** @@ -2847,6 +2966,110 @@ void test__Cellular_PktioSendAtCmd_Happy_Path_No_Prefix( void ) TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); } +/** + * @brief _Cellular_PktioSendAtCmd - Sending CELLULAR_AT_WO_PREFIX with prefix. + * + * Prefix won't be parsed for CELLULAR_AT_WO_PREFIX type command. pRespPrefix should + * be set NULL. + * + * Coverage + * @code{c} + * if( ( pAtRspPrefix != NULL ) && ( atType != CELLULAR_AT_WO_PREFIX ) && ( atType != CELLULAR_AT_WO_PREFIX_NO_RESULT_CODE ) ) + * { + * ( void ) strncpy( pContext->pktRespPrefixBuf, pAtRspPrefix, CELLULAR_CONFIG_MAX_PREFIX_STRING_LENGTH ); + * pContext->pRespPrefix = pContext->pktRespPrefixBuf; + * } + * else + * { + * pContext->pRespPrefix = NULL; + * } + * @endcode + * ( pAtRspPrefix != NULL ) is true. + * ( atType != CELLULAR_AT_WO_PREFIX ) is false. + */ +void test__Cellular_PktioSendAtCmd_CELLULAR_AT_WO_PREFIX_with_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_WO_PREFIX, + "+QCFG", + NULL, + NULL, + 0, + }; + + /* Setup variable. */ + memset( &context, 0, sizeof( CellularContext_t ) ); + context.pCommIntf = pCommIntf; + context.hPktioCommIntf = ( CellularCommInterfaceHandle_t ) &commInterfaceHandle; + + /* API call. */ + pktStatus = _Cellular_PktioSendAtCmd( &context, atReqSetRatPriority.pAtCmd, + atReqSetRatPriority.atCmdType, + atReqSetRatPriority.pAtRspPrefix ); + + /* Validation. */ + TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + TEST_ASSERT_EQUAL( NULL, context.pRespPrefix ); /* The context.PrespPrefix should be set NULL. */ +} + +/** + * @brief _Cellular_PktioSendAtCmd - Sending CELLULAR_AT_WO_PREFIX_NO_RESULT_CODE with prefix. + * + * Prefix won't be parsed for CELLULAR_AT_WO_PREFIX_NO_RESULT_CODE type command. + * pRespPrefix should be set NULL. + * + * Coverage + * @code{c} + * if( ( pAtRspPrefix != NULL ) && ( atType != CELLULAR_AT_WO_PREFIX ) && ( atType != CELLULAR_AT_WO_PREFIX_NO_RESULT_CODE ) ) + * { + * ( void ) strncpy( pContext->pktRespPrefixBuf, pAtRspPrefix, CELLULAR_CONFIG_MAX_PREFIX_STRING_LENGTH ); + * pContext->pRespPrefix = pContext->pktRespPrefixBuf; + * } + * else + * { + * pContext->pRespPrefix = NULL; + * } + * @endcode + * ( pAtRspPrefix != NULL ) is true. + * ( atType != CELLULAR_AT_WO_PREFIX_NO_RESULT_CODE ) is false. + */ +void test__Cellular_PktioSendAtCmd_CELLULAR_AT_WO_PREFIX_NO_RESULT_CODE_with_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_WO_PREFIX_NO_RESULT_CODE, + "+QCFG", + NULL, + NULL, + 0, + }; + + /* Setup variable. */ + memset( &context, 0, sizeof( CellularContext_t ) ); + context.pCommIntf = pCommIntf; + context.hPktioCommIntf = ( CellularCommInterfaceHandle_t ) &commInterfaceHandle; + + /* API call. */ + pktStatus = _Cellular_PktioSendAtCmd( &context, atReqSetRatPriority.pAtCmd, + atReqSetRatPriority.atCmdType, + atReqSetRatPriority.pAtRspPrefix ); + + /* Validation. */ + TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + TEST_ASSERT_EQUAL( NULL, context.pRespPrefix ); /* The context.PrespPrefix should be set NULL. */ +} + /** * @brief Test that any NULL parameter for _Cellular_PktioSendData. */