Skip to content

Commit

Permalink
Adding _Cellular_RegisterInputBufferCallback in common layer (#137)
Browse files Browse the repository at this point in the history
* Adding _Cellular_RegisterInputBufferCallback in common layer. Port can make use of this callback function to handle input buffer before pktio process the line.
  • Loading branch information
chinglee-iot authored May 23, 2023
1 parent e5862bd commit b341dfa
Show file tree
Hide file tree
Showing 8 changed files with 640 additions and 6 deletions.
10 changes: 5 additions & 5 deletions docs/doxygen/include/size_table.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<tr>
<td>cellular_common.c</td>
<td><center>1.7K</center></td>
<td><center>1.5K</center></td>
<td><center>1.6K</center></td>
</tr>
<tr>
<td>cellular_pkthandler.c</td>
Expand All @@ -39,12 +39,12 @@
</tr>
<tr>
<td>cellular_pktio.c</td>
<td><center>2.0K</center></td>
<td><center>1.8K</center></td>
<td><center>2.1K</center></td>
<td><center>1.9K</center></td>
</tr>
<tr>
<td><b>Total estimates</b></td>
<td><b><center>14.8K</center></b></td>
<td><b><center>13.4K</center></b></td>
<td><b><center>14.9K</center></b></td>
<td><b><center>13.6K</center></b></td>
</tr>
</table>
7 changes: 7 additions & 0 deletions lexicon.txt
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ efhplmnwact
eidrxlist
eidrxsettingslist
emerg
endcode
endcond
endif
endpatternlen
Expand Down Expand Up @@ -354,6 +355,7 @@ inet
ingroup
inidcate
init
inputbuffercallback
inputline
inputwithprefix
int
Expand All @@ -377,6 +379,7 @@ isurc
isvalidpdn
isvalidsocket
jan
keepprocess
keylist
keylistlen
kselacq
Expand Down Expand Up @@ -409,6 +412,7 @@ mcc
md
mem
memorystatus
memset
metadata
min
misra
Expand Down Expand Up @@ -484,6 +488,7 @@ pbandcfg
pbervalue
pbuf
pbuffer
pbufferlengthhandled
pbytesread
pc
pcallbackcontext
Expand Down Expand Up @@ -534,6 +539,7 @@ pgenericcallbackcontext
ph
phexdata
pinputbuf
pinputbuffercallbackcontext
pinputline
pinputptr
pinputstr
Expand Down Expand Up @@ -656,6 +662,7 @@ pstr
pstring
pstrvalue
ptemp
ptempline
ptempstring
ptestusrdata
ptofree
Expand Down
34 changes: 34 additions & 0 deletions source/cellular_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1137,3 +1137,37 @@ CellularError_t _Cellular_RegisterUndefinedRespCallback( CellularContext_t * pCo
}

/*-----------------------------------------------------------*/

CellularError_t _Cellular_RegisterInputBufferCallback( CellularContext_t * pContext,
CellularInputBufferCallback_t inputBufferCallback,
void * pInputBufferCallbackContext )
{
CellularError_t cellularStatus = CELLULAR_SUCCESS;

if( pContext == NULL )
{
LogError( ( "_Cellular_RegisterUrcDataCallback: invalid context." ) );
cellularStatus = CELLULAR_INVALID_HANDLE;
}
else
{
/* inputBufferCallback can be set to NULL to unregister the callback. */
PlatformMutex_Lock( &pContext->PktRespMutex );
pContext->inputBufferCallback = inputBufferCallback;

if( pContext->inputBufferCallback != NULL )
{
pContext->pInputBufferCallbackContext = pInputBufferCallbackContext;
}
else
{
pContext->pInputBufferCallbackContext = NULL;
}

PlatformMutex_Unlock( &pContext->PktRespMutex );
}

return cellularStatus;
}

/*-----------------------------------------------------------*/
93 changes: 92 additions & 1 deletion source/cellular_pktio.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ static uint32_t _handleRxDataEvent( CellularContext_t * pContext,
CellularATCommandResponse_t ** ppAtResp );
static void _pktioReadThread( void * pUserData );
static void _PktioInitProcessReadThreadStatus( CellularContext_t * pContext );
static bool _getNextLine( CellularContext_t * pContext,
char ** ppLine,
uint32_t * pBytesRead,
uint32_t currentLineLength,
CellularPktStatus_t pktStatus );
static bool _preprocessInputBuffer( CellularContext_t * pContext,
char ** pLine,
uint32_t * pBytesRead );

/*-----------------------------------------------------------*/

Expand Down Expand Up @@ -818,6 +826,80 @@ static bool _findLineInStream( CellularContext_t * pContext,

/*-----------------------------------------------------------*/

static bool _preprocessInputBuffer( CellularContext_t * pContext,
char ** pLine,
uint32_t * pBytesRead )
{
char * pTempLine = *pLine;
bool keepProcess = true;
uint32_t bufferLength = 0;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;

if( pContext->inputBufferCallback != NULL )
{
PlatformMutex_Lock( &pContext->PktRespMutex );
pktStatus = pContext->inputBufferCallback( pContext->pInputBufferCallbackContext,
pTempLine,
*pBytesRead,
&bufferLength );
PlatformMutex_Unlock( &pContext->PktRespMutex );

if( pktStatus == CELLULAR_PKT_STATUS_PREFIX_MISMATCH )
{
/* Input buffer is not handled in the callback. pktio should keep processing
* the input buffer. */
keepProcess = true;
}
else if( pktStatus == CELLULAR_PKT_STATUS_SIZE_MISMATCH )
{
/* Input buffer is handled in the callback. The callback expects to be called
* again with more data received. pktio won't keep process this input buffer. */
pContext->pPktioReadPtr = pTempLine;
pContext->partialDataRcvdLen = *pBytesRead;
keepProcess = false;
}
else if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
/* Modem returns unexpected response. */
LogError( ( "Input buffer callback returns error %d. Clean the read buffer.", pktStatus ) );

/* Clean the read buffer and read pointer. */
( void ) memset( pContext->pktioReadBuf, 0, PKTIO_READ_BUFFER_SIZE + 1U );
pContext->pPktioReadPtr = NULL;
pContext->partialDataRcvdLen = 0;
keepProcess = false;
}
else if( bufferLength > *pBytesRead )
{
/* The input buffer callback returns incorrect buffer length. */
LogError( ( "Input buffer callback returns bufferLength %u. Modem returns length %u. Clean the read buffer.",
bufferLength, *pBytesRead ) );

/* Clean the read buffer and read pointer. */
( void ) memset( pContext->pktioReadBuf, 0, PKTIO_READ_BUFFER_SIZE + 1U );
pContext->pPktioReadPtr = NULL;
pContext->partialDataRcvdLen = 0;
keepProcess = false;
}
else
{
/* The input buffer is handled in the callback successfully. Move
* the read pointer forward. pktio will keep processing the line
* after. */
pTempLine = &pTempLine[ bufferLength ];
*pLine = pTempLine;
pContext->pPktioReadPtr = *pLine;

/* Calculate remain bytes in the buffer. */
*pBytesRead = *pBytesRead - bufferLength;
}
}

return keepProcess;
}

/*-----------------------------------------------------------*/

static bool _preprocessLine( CellularContext_t * pContext,
char * pLine,
uint32_t * pBytesRead,
Expand Down Expand Up @@ -992,8 +1074,17 @@ static void _handleAllReceived( CellularContext_t * pContext,
bytesRead = bytesRead - 1U;
}

/* Preprocess the input buffer in the callback function. pktio processes the
* input buffer in line. This function allows the porting to process the input
* buffer before pktio processing lines in the buffer. For example, porting
* can make use of input buffer callback to handle binary stream in URC. */
keepProcess = _preprocessInputBuffer( pContext, &pTempLine, &bytesRead );

/* Preprocess line. */
keepProcess = _preprocessLine( pContext, pTempLine, &bytesRead, &pStartOfData );
if( keepProcess == true )
{
keepProcess = _preprocessLine( pContext, pTempLine, &bytesRead, &pStartOfData );
}

if( keepProcess == true )
{
Expand Down
37 changes: 37 additions & 0 deletions source/include/common/cellular_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,25 @@ typedef CellularPktStatus_t ( * CellularATCommandDataSendPrefixCallback_t ) ( vo
typedef CellularPktStatus_t ( * CellularUndefinedRespCallback_t )( void * pCallbackContext,
const char * pLine );

/**
* @ingroup cellular_common_datatypes_functionpointers
* @brief Callback used to process input buffer.
*
* @param[in] pInputBufferCallbackContext The pCallbackContext in CellularInputBufferCallback_t.
* @param[in] pBuffer The data buffer with modem response data.
* @param[in] bufferLength The length of the input buffer.
* @param[out] pBufferLengthHandled The length of the handled input buffer in pBuffer.
*
* @return CELLULAR_PKT_STATUS_OK if the operation is successful.
* CELLULAR_PKT_STATUS_SIZE_MISMATCH if more data is required.
* CELLULAR_PKT_STATUS_PREFIX_MISMATCH if the input buffer is not handled in the callback.
* Otherwise an error code indicating the cause of the error.
*/
typedef CellularPktStatus_t ( * CellularInputBufferCallback_t ) ( void * pInputBufferCallbackContext,
char * pBuffer,
uint32_t bufferLength,
uint32_t * pBufferLengthHandled );

/*-----------------------------------------------------------*/

/**
Expand Down Expand Up @@ -623,6 +642,24 @@ CellularError_t _Cellular_RegisterUndefinedRespCallback( CellularContext_t * pCo
CellularUndefinedRespCallback_t undefinedRespCallback,
void * pCallbackContext );

/**
* @brief Register input buffer callback.
*
* Cellular module can register the callback function to handler the input buffer
* before pktio continue to process the line in the buffer.
*
* @param[in] pContext The opaque cellular context pointer created by Cellular_Init.
* @param[in] inputBufferCallback The callback function to handle the URC data.
* @param[in] pInputBufferCallbackContext The pInputBufferCallbackContext passed to the inputBufferCallback
* callback function if inputBufferCallback is not NULL.
*
* @return CELLULAR_SUCCESS if the operation is successful, otherwise an error code
* indicating the cause of the error.
*/
CellularError_t _Cellular_RegisterInputBufferCallback( CellularContext_t * pContext,
CellularInputBufferCallback_t inputBufferCallback,
void * pInputBufferCallbackContext );

/* *INDENT-OFF* */
#ifdef __cplusplus
}
Expand Down
2 changes: 2 additions & 0 deletions source/include/private/cellular_common_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ struct CellularContext
_atRespType_t recvdMsgType; /**< The received AT response type. */
CellularUndefinedRespCallback_t undefinedRespCallback; /**< Undefined response callback function. */
void * pUndefinedRespCBContext; /**< The pCallbackContext passed to CellularUndefinedRespCallback_t. */
CellularInputBufferCallback_t inputBufferCallback; /**< URC data preprocess callback function. */
void * pInputBufferCallbackContext; /**< the callback context passed to inputBufferCallback. */

/* PktIo data handling. */
uint32_t dataLength; /**< The data length in pLine. */
Expand Down
77 changes: 77 additions & 0 deletions test/unit-test/cellular_common_utest.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,20 @@ void MockPlatformMutex_Destroy( PlatformMutex_t * pMutex )
pMutex->created = false;
}


static CellularPktStatus_t prvDummyInputBufferCallback( void * pInputBufferCallbackContext,
char * pBuffer,
uint32_t bufferLength,
uint32_t * pBufferLengthHandled )
{
( void ) pInputBufferCallbackContext;
( void ) pBuffer;
( void ) bufferLength;
( void ) pBufferLengthHandled;

return CELLULAR_PKT_STATUS_OK;
}

/* ========================================================================== */

/**
Expand Down Expand Up @@ -1640,3 +1654,66 @@ void test__Cellular_RegisterUndefinedRespCallback_Happy_Path( void )
TEST_ASSERT_NULL( context.undefinedRespCallback );
TEST_ASSERT_NULL( context.pUndefinedRespCBContext );
}

/**
* @brief _Cellular_RegisterInputBufferCallback - parameter null context.
* pContext parameter is NULL. Verify the return value.
*/
void test__Cellular_RegisterInputBufferCallback_Null_Context( void )
{
CellularError_t cellularStatus = CELLULAR_SUCCESS;

/* API call. */
cellularStatus = _Cellular_RegisterInputBufferCallback( NULL, NULL, NULL );

/* Validation. */
TEST_ASSERT_EQUAL( CELLULAR_INVALID_HANDLE, cellularStatus );
}

/**
* @brief _Cellular_RegisterInputBufferCallback - parameter NULL callback.
* inputBufferCallback parameter is NULL. Verify the member variable is updated.
*/
void test__Cellular_RegisterInputBufferCallback_Null_Callback( void )
{
CellularError_t cellularStatus = CELLULAR_SUCCESS;
CellularContext_t cellularContext;
uint32_t inputBufferCallbackContext;

/* Setup internal variable. */
memset( &cellularContext, 0, sizeof( CellularContext_t ) );
cellularContext.inputBufferCallback = prvDummyInputBufferCallback;
cellularContext.pInputBufferCallbackContext = &inputBufferCallbackContext;

/* API call. */
cellularStatus = _Cellular_RegisterInputBufferCallback( &cellularContext, NULL, &inputBufferCallbackContext );

/* Validation. */
TEST_ASSERT_EQUAL( CELLULAR_SUCCESS, cellularStatus );
TEST_ASSERT_EQUAL( NULL, cellularContext.inputBufferCallback );
/* The callback context will be cleaned when inputBufferCallback is NULL. */
TEST_ASSERT_EQUAL( NULL, cellularContext.pInputBufferCallbackContext );
}

/**
* @brief _Cellular_RegisterInputBufferCallback - Setup the URC data callback.
* Verify the URC data callback and callback context are set correctly.
*/
void test__Cellular_RegisterInputBufferCallback_Happy_Path( void )
{
CellularError_t cellularStatus = CELLULAR_SUCCESS;
CellularContext_t cellularContext;
uint32_t inputBufferCallbackContext;

/* Setup internal variable. */
memset( &cellularContext, 0, sizeof( CellularContext_t ) );
cellularContext.inputBufferCallback = NULL;

/* API call. */
cellularStatus = _Cellular_RegisterInputBufferCallback( &cellularContext, prvDummyInputBufferCallback, &inputBufferCallbackContext );

/* Validation. */
TEST_ASSERT_EQUAL( CELLULAR_SUCCESS, cellularStatus );
TEST_ASSERT_EQUAL( prvDummyInputBufferCallback, cellularContext.inputBufferCallback );
TEST_ASSERT_EQUAL( &inputBufferCallbackContext, cellularContext.pInputBufferCallbackContext );
}
Loading

0 comments on commit b341dfa

Please sign in to comment.