diff --git a/docs/doxygen/portingCellularModule.dox b/docs/doxygen/portingCellularModule.dox index 89360a6c..760ee9d9 100644 --- a/docs/doxygen/portingCellularModule.dox +++ b/docs/doxygen/portingCellularModule.dox @@ -167,8 +167,10 @@ They can be used to reduce porting effort.
@page cellular_module_urc_handler cellular_module_urc_handler @brief Implement URC handler to handle URC event and call the corresponding callback function.
- @ref CellularTokenTable_t.pCellularUrcHandlerTable : URC handler table of @ref CellularAtParseTokenHandler_t -- @ref CellularTokenTable_t.cellularPrefixToParserMapSize -Example URC handler table. +- @ref CellularTokenTable_t.cellularPrefixToParserMapSize : The size of the URC handler table +
+ +Example URC handler table: ``` CellularAtParseTokenMap_t CellularUrcHandlerTable[] = { @@ -179,9 +181,44 @@ CellularAtParseTokenMap_t CellularUrcHandlerTable[] = } uint32_t CellularUrcHandlerTableSize = 4; ``` +
+There are two types of URC strings can be handled with this table: +- URC with prefix
+This type of URC string is of the following format:
+> \\":"\
+The logic to check the URC prefix can be referenced in @ref Cellular_ATIsPrefixPresent
+Example of URC with prefix: "+CREG:2,0"
+In this example,
+URC_leading_char is "+"
+URC_prefix is "CREG"
+URC_payload is "2,0"
+The URC callback function, @ref CellularAtParseTokenHandler_t, will be called with + parameter pInputStr point to string URC_payload, "2,0" in this example. +> The default prefix leading char can be referenced in this config @ref CELLULAR_CHECK_IS_PREFIX_LEADING_CHAR.
+> The default valid prefix string chars can be referenced in this config @ref CELLULAR_CHECK_IS_PREFIX_CHAR.
+> Reference @subpage cellular_prefix_string_customize_config for more information. + +- URC without prefix
+This type of URC string is of fixed format.
+Example of URC without prefix : "NORMAL POWER DOWN"
+The URC callback function, @ref CellularAtParseTokenHandler_t, will be called with + parameter pInputStr point to URC string, "NORMAL POWER DOWN" in this example. +
+ @image html cellular_URC_handler_implementation.png width=80% */ +/** +@page cellular_prefix_string_customize_config Customization config for prefix string. +@brief The config can be redefined in cellular_config.h to support different modem prefix string format.
+ +@section CELLULAR_CHECK_IS_PREFIX_CHAR +@copydoc CELLULAR_CHECK_IS_PREFIX_CHAR + +@section CELLULAR_CHECK_IS_PREFIX_LEADING_CHAR +@copydoc CELLULAR_CHECK_IS_PREFIX_LEADING_CHAR +*/ + /** @paramstructs_group{cellular_common,Cellular_common} @paramstructs_brief{cellular_common,cellular_common} diff --git a/lexicon.txt b/lexicon.txt index d86489b7..2ae54e15 100644 --- a/lexicon.txt +++ b/lexicon.txt @@ -293,6 +293,7 @@ firmwareversion freertos freertosconfig fucntion +fso functionpointers fw gcc @@ -468,6 +469,7 @@ parsetimezoneinfo parseyearmonthdayincclkresponse partialdata partialdatarcvdlen +passcomparestring patbuf patcmd patcommandpayload @@ -495,6 +497,7 @@ pcomminterface pcomminterfacehandle pcommintf pcontext +pcomparestring pcurrentcmd pcwriteto pdata @@ -529,6 +532,7 @@ phexdata pinputbuf pinputline pinputptr +pinputstr pitm pkio pkt @@ -751,6 +755,7 @@ simcardstate simlockstate sinr sms +smso snprintf socketclose socketconnect diff --git a/source/cellular_at_core.c b/source/cellular_at_core.c index b1b62769..0b46504f 100644 --- a/source/cellular_at_core.c +++ b/source/cellular_at_core.c @@ -45,15 +45,6 @@ /*-----------------------------------------------------------*/ -#ifndef CELLULAR_CHECK_IS_PREFIX_CHAR - #define CELLULAR_CHECK_IS_PREFIX_CHAR( inputChar ) \ - ( ( ( ( int32_t ) isalpha( ( ( int8_t ) ( inputChar ) ) ) ) == 0 ) && \ - ( ( ( int32_t ) isdigit( ( ( int8_t ) ( inputChar ) ) ) ) == 0 ) && \ - ( ( inputChar ) != '+' ) && ( ( inputChar ) != '_' ) ) -#endif - -/*-----------------------------------------------------------*/ - /** * @brief String validation results. */ @@ -136,6 +127,10 @@ CellularATError_t Cellular_ATIsPrefixPresent( const char * pString, { *pResult = false; } + else if( !CELLULAR_CHECK_IS_PREFIX_LEADING_CHAR( *pString ) ) + { + *pResult = false; + } else { /* There should be only '+', '_', characters or digit before seperator. */ diff --git a/source/cellular_pkthandler.c b/source/cellular_pkthandler.c index 90f9a5c5..456b58af 100644 --- a/source/cellular_pkthandler.c +++ b/source/cellular_pkthandler.c @@ -133,20 +133,22 @@ static CellularPktStatus_t urcParseToken( CellularContext_t * pContext, char * pInputLine ) { CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK; + bool inputWithPrefix = false; /* pInputLine = "+" pTokenPtr + ":" + pSavePtr. * if string not start with "+", then pTokenPtr = pSavePtr = pInputPtr. */ char * pSavePtr = pInputLine, * pTokenPtr = pInputLine; - LogDebug( ( "Next URC token to parse [%s]", pInputLine ) ); - /* First check for + at the beginning and advance to point to the next - * byte. Use that string to pass to strtok and retrieve the token. Once the - * token use is retrieved, get the function handler map and call that - * function. */ - if( *pSavePtr == '+' ) + /* Check if prefix exist in the input string. The pInputLine is checked in _processUrcPacket. */ + ( void ) Cellular_ATIsPrefixPresent( pInputLine, &inputWithPrefix ); + + if( inputWithPrefix == true ) { + /* Cellular_ATIsPrefixPresent check the prefix string is valid and start with + * leading char. ":" is also checked in Cellular_ATIsPrefixPresent. Remove + * the leading char and split the string. */ pSavePtr++; pTokenPtr = strtok_r( pSavePtr, ":", &pSavePtr ); @@ -156,6 +158,12 @@ static CellularPktStatus_t urcParseToken( CellularContext_t * pContext, pktStatus = CELLULAR_PKT_STATUS_BAD_REQUEST; } } + else + { + /* This is the input without prefix case. Nothing need to be done for this case. + * There are some special cases. For example, "+URC" the string without ":" should + * be regarded as URC without prefix. */ + } if( pktStatus == CELLULAR_PKT_STATUS_OK ) { diff --git a/source/include/cellular_config_defaults.h b/source/include/cellular_config_defaults.h index 16cfb4ec..fd1d8cc8 100644 --- a/source/include/cellular_config_defaults.h +++ b/source/include/cellular_config_defaults.h @@ -401,6 +401,45 @@ #define CELLULAR_CONFIG_MAX_PREFIX_STRING_LENGTH ( 32U ) #endif +/** + * @brief Macro to check prefix leading char.
+ * + * Cellular interface requires prefix string starts with "+". Some cellular modem + * uses different leading char. This macro can be defined in cellular_config.h to + * support different leading char.
+ * + * Default value (if undefined): '+' + * + * For example: + * > ^SMSO:(list of supporteds)
+ * The prefix string contains "^" which is not default leading char for prefix + * string. User can define this config to support this prefix string. + */ +#ifndef CELLULAR_CHECK_IS_PREFIX_LEADING_CHAR + #define CELLULAR_CHECK_IS_PREFIX_LEADING_CHAR( x ) ( ( x ) == '+' ) +#endif + +/** + * @brief Macro to check prefix chars.
+ * + * The macro to check prefix string contains valid char. Modem with different prefix + * strings can be supported with this config.
+ * + * Default value (if undefined): alphabet, digit, '+' and '_' + * + * For example: + * > +APP PDP: 0,ACTIVE
+ * The prefix string contains space which is not default valid char. User can define + * this config to support this prefix string. + */ +#ifndef CELLULAR_CHECK_IS_PREFIX_CHAR + #define CELLULAR_CHECK_IS_PREFIX_CHAR( inputChar ) \ + ( ( ( ( int32_t ) isalpha( ( ( int8_t ) ( inputChar ) ) ) ) == 0 ) && \ + ( ( ( int32_t ) isdigit( ( ( int8_t ) ( inputChar ) ) ) ) == 0 ) && \ + ( ( inputChar ) != '_' ) && \ + ( !( CELLULAR_CHECK_IS_PREFIX_LEADING_CHAR( inputChar ) ) ) ) +#endif + /** * @brief Macro that is called in the cellular library for logging "Error" level * messages. diff --git a/test/unit-test/cellular_at_core_utest.c b/test/unit-test/cellular_at_core_utest.c index 9bcf37fd..7accfd06 100644 --- a/test/unit-test/cellular_at_core_utest.c +++ b/test/unit-test/cellular_at_core_utest.c @@ -167,6 +167,11 @@ */ #define CELLULAR_SAMPLE_PREFIX_STRING_STAR_FIRST_INPUT "*CPIN:READY" +/** + * @brief Cellular sample prefix string with invalid prefix char. + */ +#define CELLULAR_SAMPLE_PREFIX_STRING_INVALID_PREFIX_CHAR "+*CPIN:READY" + static int mallocAllocFail = 0; /* ============================ UNITY FIXTURES ============================ */ @@ -1055,3 +1060,17 @@ void test_Cellular_ATIsPrefixPresent_Wrong_Prefix( void ) TEST_ASSERT_EQUAL( CELLULAR_AT_SUCCESS, cellularStatus ); TEST_ASSERT_EQUAL( false, Result ); } + +/** + * @brief Test the string with wrong prefix case for Cellular_ATIsPrefixPresent to return CELLULAR_AT_BAD_PARAMETER. + */ +void test_Cellular_ATIsPrefixPresent_Invalid_Prefix_Char( void ) +{ + CellularATError_t cellularStatus = CELLULAR_AT_SUCCESS; + char pString[] = CELLULAR_SAMPLE_PREFIX_STRING_INVALID_PREFIX_CHAR; + bool Result; + + cellularStatus = Cellular_ATIsPrefixPresent( pString, &Result ); + TEST_ASSERT_EQUAL( CELLULAR_AT_SUCCESS, cellularStatus ); + TEST_ASSERT_EQUAL( false, Result ); +} diff --git a/test/unit-test/cellular_pkthandler_utest.c b/test/unit-test/cellular_pkthandler_utest.c index 71af69dc..15072fef 100644 --- a/test/unit-test/cellular_pkthandler_utest.c +++ b/test/unit-test/cellular_pkthandler_utest.c @@ -52,6 +52,7 @@ #define CELLULAR_AT_MULTI_DATA_WO_PREFIX_STRING_RESP "+QIRD: 32\r123243154354364576587utrhfgdghfg" #define CELLULAR_URC_TOKEN_STRING_INPUT "RDY" #define CELLULAR_URC_TOKEN_STRING_INPUT_START_PLUS "+RDY" +#define CELLULAR_URC_TOKEN_STRING_INPUT_WITH_PAYLOAD "+RDY:START" #define CELLULAR_URC_TOKEN_STRING_GREATER_INPUT "RDYY" #define CELLULAR_URC_TOKEN_STRING_SMALLER_INPUT "RD" #define CELLULAR_PLUS_TOKEN_ONLY_STRING "+" @@ -327,6 +328,38 @@ uint16_t MockvQueueDelete( QueueHandle_t queue ) return 1; } +CellularATError_t Cellular_ATIsPrefixPresent( const char * pString, + bool * pResult ) +{ + CellularATError_t atStatus = CELLULAR_AT_SUCCESS; + + TEST_ASSERT( pString != NULL ); + TEST_ASSERT( pResult != NULL ); + + if( strcmp( pString, CELLULAR_AT_MULTI_DATA_WO_PREFIX_STRING_RESP ) == 0 ) + { + *pResult = true; + } + else if( strcmp( pString, CELLULAR_PLUS_TOKEN_ONLY_STRING ) == 0 ) + { + *pResult = true; + } + else if( strcmp( pString, CELLULAR_URC_TOKEN_STRING_INPUT_WITH_PAYLOAD ) == 0 ) + { + *pResult = true; + } + else if( strcmp( pString, CELLULAR_URC_TOKEN_STRING_INPUT_START_PLUS ) == 0 ) + { + *pResult = false; + } + else + { + *pResult = false; + } + + return atStatus; +} + CellularATError_t _CMOCK_Cellular_ATStrDup_CALLBACK( char ** ppDst, const char * pSrc, int cmock_num_calls ) @@ -623,10 +656,45 @@ void test__Cellular_HandlePacket_AT_UNSOLICITED_Happy_Path( void ) /* set for cellularAtParseTokenHandler function */ passCompareString = false; - pCompareString = getStringAfterColon( CELLULAR_URC_TOKEN_STRING_INPUT_START_PLUS ); + pCompareString = getStringAfterColon( CELLULAR_URC_TOKEN_STRING_INPUT_WITH_PAYLOAD ); + + pktStatus = _Cellular_HandlePacket( &context, AT_UNSOLICITED, CELLULAR_URC_TOKEN_STRING_INPUT_WITH_PAYLOAD ); + TEST_ASSERT_EQUAL( CELLULAR_PKT_STATUS_OK, pktStatus ); + TEST_ASSERT_EQUAL( true, passCompareString ); +} + +/** + * @brief Test input string without payload for _Cellular_HandlePacket. + * + * URC input string "+RDY" should be regarded as URC without prefix. + * If there is a handler function registered in the table, the handler function is + * called with pInputStr point to "+RDY" string. + */ +void test__Cellular_HandlePacket_AT_UNSOLICITED_Input_String_without_payload( void ) +{ + CellularContext_t context; + CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK; + CellularAtParseTokenMap_t cellularTestUrcHandlerTable[] = + { + /* Use the URC string instead of the URC prefix in the mapping table. */ + { CELLULAR_URC_TOKEN_STRING_INPUT_START_PLUS, cellularAtParseTokenHandler } + }; + + memset( &context, 0, sizeof( CellularContext_t ) ); + context.tokenTable.pCellularUrcHandlerTable = cellularTestUrcHandlerTable; + context.tokenTable.cellularPrefixToParserMapSize = 1; + + Cellular_ATStrDup_StubWithCallback( _CMOCK_Cellular_ATStrDup_CALLBACK ); + + /* set for cellularAtParseTokenHandler function */ + passCompareString = false; + pCompareString = 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 ); + + /* passCompareString is set to true in cellularAtParseTokenHandler if pCompareString + * equals to parameter pInputStr. */ TEST_ASSERT_EQUAL( true, passCompareString ); }