_getMsgType in FreeRTOS Cellular Interface Library

_getMsgType() in cellular_pktio.c

static _atRespType_t _getMsgType( CellularContext_t * pContext,
const char * pLine,
const char * pRespPrefix )
{
_atRespType_t atRespType = AT_UNDEFINED;
CellularATError_t atStatus = CELLULAR_AT_SUCCESS;
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;
    atRespType = AT_UNDEFINED;
}
else if( urcTokenWoPrefix( pContext, pLine ) == true )
{
    atRespType = AT_UNSOLICITED;
}
else
{
    /* Check if prefix exist in pLine. */
    ( void ) Cellular_ATIsPrefixPresent( pLine, &inputWithPrefix );

    if( ( inputWithPrefix == true ) && ( pRespPrefix != NULL ) )
    {
        /* Check if SRC prefix exist in pLine. */
        atStatus = Cellular_ATStrStartWith( pLine, pRespPrefix, &inputWithSrcPrefix );
    }
}

if( ( atStatus == CELLULAR_AT_SUCCESS ) && ( atRespType == AT_UNDEFINED ) )
{
    if( inputWithPrefix == true )
    {
        if( ( pContext->PktioAtCmdType != CELLULAR_AT_NO_COMMAND ) && ( inputWithSrcPrefix == true ) )
        {
            atRespType = AT_SOLICITED;
        }
        else
        {
            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 ) )
        {
            atRespType = AT_SOLICITED;
        }
    }
}

PlatformMutex_Unlock( &pContext->PktRespMutex );

return atRespType;

}

question:
1、CellularUrcTokenWoPrefixTable must be register in CellularContext in applation?
2、if inputWithPrefix = false , and pktioAtcmdType = CELLULAR_AT_WITH_PREFIX, why set atRespType = AT_SOLICITED?

@Qianfeng.Tang

Thank you for your interest in cellular interface. Below is my reply to your questions.

1、CellularUrcTokenWoPrefixTable must be register in CellularContext in applation?

CellularUrcTokenWoPrefixTable contains the URCs without prefix. It is modem specific so provided in the modem port. The reference BG96 port can be used as an example. It should not be provided in application.

2、if inputWithPrefix = false , and pktioAtcmdType = CELLULAR_AT_WITH_PREFIX, why set atRespType = AT_SOLICITED?

The result code( for example “OK” and “ERROR” ) to indicate the AT command executed result is also considered AT_SOLICTED and later been parsed in _Cellular_ProcessLine function.

If you are having problem with URC without prefix, please update in this thread. We will discuss with you here.

Thank you for your reply, but I still have the following questions:

  1. In the porting file of BG96, why do we need to process the CellularUrcTokenWoPrefixTable string list twice when it already appears in the CellularUrcHandlerTable strings?

CellularAtParseTokenMap_t CellularUrcHandlerTable =

{
{ “CEREG”, Cellular_CommonUrcProcessCereg },
{ “CGREG”, Cellular_CommonUrcProcessCgreg },
{ “CREG”, Cellular_CommonUrcProcessCreg },
{ “NORMAL POWER DOWN”, _Cellular_ProcessPowerDown },
{ “PSM POWER DOWN”, _Cellular_ProcessPsmPowerDown },
{ “QIND”, _Cellular_ProcessIndication },
{ “QIOPEN”, _Cellular_ProcessSocketOpen },
{ “QIURC”, _Cellular_ProcessSocketurc },
{ “QSIMSTAT”, _Cellular_ProcessSimstat },
{ “RDY” , _Cellular_ProcessModemRdy }
};
const char * CellularUrcTokenWoPrefixTable = {“NORMAL POWER DOWN”,“PSM POWER DOWN”,“RDY”};

  1. If the CellularUrcTokenWoPrefixTable is not provided, does it make sense for the function “_getMsgType()” to directly return CELLULAR_AT_ERROR without further processing of the received buffer?

  2. When checking if a string contains an expected prefix in the function “_getMsgType()”, there is no check for PktioAtCmdType (assuming that when PktioAtCmdType = CELLULAR_AT_WO_PREFIX, I believe there is no need to check for an expected prefix).

  3. Why does the function “_getMsgType()” set AT_UNSOLICITED when detecting a prefix but the detected prefix is different from the expected prefix?

if( inputWithPrefix == true )
{
if( ( pContext->PktioAtCmdType != CELLULAR_AT_NO_COMMAND ) && ( inputWithSrcPrefix == true ) )
{
atRespType = AT_SOLICITED;
}
else
{
atRespType = AT_UNSOLICITED;
}
}

  1. In the function “_getMsgType()”, when checking PktioAtCmdType at the end, not all conditions are checked, which means that unchecked conditions will result in a return type of AT_UNDEFINED (e.g., when PktioAtCmdType = CELLULAR_AT_WO_PREFIX).

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 ) )
{
atRespType = AT_SOLICITED;
}

  1. In the function “_preprocessLine()”, if the callback functions pktDataSendPrefixCB() or pktDataPrefixCB() do not return CELLULAR_PKT_STATUS_OK, then pContext->pPktioReadPtr and pContext->partialDataRcvdLen are not initialized, resulting in newly received data being concatenated with unprocessed data from this processing.

  2. In the function “_Cellular_ProcessLine()”, if a keyword is found in either pTokenExtraTable or pTokenSuccessTable, the current line is not linked to ppAtResp list. This means that after the function returns, ppAtResp may point to empty when executing the pContext->pPktioHandlepktCB() callback function.

/* This command is completed. Call the user callback to parse the result. */
if( pContext->pPktioHandlepktCB != NULL )
{
( void ) pContext->pPktioHandlepktCB( pContext, AT_SOLICITED, *ppAtResp );
}

Hi QianFeng,

Below is my reply to your questions.

  1. In the porting file of BG96, why do we need to process the CellularUrcTokenWoPrefixTable string list twice when it already appears in the CellularUrcHandlerTable strings?

_getMsgType only distinguishes _atRespType_t. The port can decide to handle this URC without prefix or not in CellularUrcHandlerTable.

  1. If the CellularUrcTokenWoPrefixTable is not provided, does it make sense for the function “_getMsgType()” to directly return CELLULAR_AT_ERROR without further processing of the received buffer?

Most of the port has URC without prefix token. We will consider to accept port not using URC without prefix token table or ensure this table is always set in Cellular_CommonInit.

  1. When checking if a string contains an expected prefix in the function “_getMsgType()”, there is no check for PktioAtCmdType (assuming that when PktioAtCmdType = CELLULAR_AT_WO_PREFIX, I believe there is no need to check for an expected prefix).

_getMsgType is a general function for different AT command types. atReq.pAtRspPrefix should be set to NULL if AT command type is CELLULAR_AT_WO_PREFIX. This check can be added in _Cellular_PktioSendAtCmd.

  1. Why does the function “_getMsgType()” set AT_UNSOLICITED when detecting a prefix but the detected prefix is different from the expected prefix?

Take the following AT command sequence as an example:

AT+COPS?
+CREG: 1                       # The URC is received in between AT command and response
+COPS:0,2,"46692",9

To distinguish a URC and AT command response, the method used in cellular interface is that AT command response has to specify the expected prefix. Otherwise, lines with prefix will be considered a URC. Then the port can decide to handle it or not in the CellularUrcHandlerTable.

  1. In the function “_getMsgType()”, when checking PktioAtCmdType at the end, not all conditions are checked, which means that unchecked conditions will result in a return type of AT_UNDEFINED (e.g., when PktioAtCmdType = CELLULAR_AT_WO_PREFIX).

We will review this condition and update if necessary. AT_UNDEFINED is handled in _handleMsgType. It can also be handled by the port if required.

  1. In the function “_preprocessLine()”, if the callback functions pktDataSendPrefixCB() or pktDataPrefixCB() do not return CELLULAR_PKT_STATUS_OK, then pContext->pPktioReadPtr and pContext->partialDataRcvdLen are not initialized, resulting in newly received data being concatenated with unprocessed data from this processing.

We can consider to handle different returned value in this function.

  1. In the function “_Cellular_ProcessLine()”, if a keyword is found in either pTokenExtraTable or pTokenSuccessTable, the current line is not linked to ppAtResp list. This means that after the function returns, ppAtResp may point to empty when executing the pContext->pPktioHandlepktCB() callback function.

The success tokens and extra success tokens are used to indicate the status of AT command. So it won’t be added to the response. If the AT command doesn’t use token to indicate status, you can take a look at this PR to see if CELLULAR_AT_WO_PREFIX_NO_RESULT_CODE or CELLULAR_AT_WITH_PREFIX_NO_RESULT_CODE can meet your requirement.

Thank you for pointing out some of the problems of cellular interface. We will also create PR to fix these problems if required.

Hi QianFeng,

We have addressed the questions above in this commit. Thank you for your feedback.