#define SCPI_CORE_STATE__ENDOFDATAPROCESSING_GUARD #include "app/scpi/CommandParserStates/handle_error.h" #define SCPI_CORE_PRIVATE // access to 'scpi_core_private.h' #define SCPI_END_OF_PROCESS_DATA_C // access to some const variables in 'scpi_core_private.h' #include "app/scpi/scpi_core_private.h" // ================================================================================= // @sEndOfDataProcessingContext_t // State's private context typedef typedef struct { bool bKeepParserContext; } sEndOfDataProcessingContext_t; // ================================================================================= // @ctx_EndOfDataProcessing // State's private context sEndOfDataProcessingContext_t ctx_EndOfDataProcessing; // ================================================================================= // @fsqvbl_EndOfDataProcessing // State's virtual table static void fsqe_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx ); static void fsql_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx ); static const struct fFSeqEntry_t * fsqf_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx, const struct fFSeqEntry_t * * pnext ); const fFSeqVTable_t fsqvbl_EndOfDataProcessing = { .f = fsqf_EndOfDataProcessing, .enter = fsqe_EndOfDataProcessing, .leave = fsql_EndOfDataProcessing }; static void fsqe_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx ) { sScpiParserContext_t * global_ctx = ctx; sEndOfDataProcessingContext_t * private_ctx = fsq_GetPrivateCtxRef(this); // init keep-parser-context indicator private_ctx->bKeepParserContext = false; (void)global_ctx; } static void fsql_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx ) { } static const struct fFSeqEntry_t * fsqf_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx, const struct fFSeqEntry_t * * pnext ) { sScpiParserContext_t * global_ctx = ctx; sEndOfDataProcessingContext_t * private_ctx = fsq_GetPrivateCtxRef(this); const fFSeqEntry_t * nextstate = fsq_GetStateById(this,eHandleError); // go next state: eHandleError by default switch( global_ctx->sEvent.eCode ) { case eScpiEventRestart: { // go to reset state nextstate = fsq_GetStateById(this,eParserResetState); } break; case eScpiEventError: // Transport error. { // Enter error state nextstate = fsq_GetStateById(this,eHandleError); // enter the error state } break; case eScpiEventWrite: case eScpiEventRead: { nextstate = NULL; // stay in current state if( eScpiStatus_failed == global_ctx->sEvent.eStatus ) { // Enter error state fsq_RaiseError( SCPI_ERROR_STATE, NULL, NULL, 0 ); nextstate = fsq_GetStateById(this,eHandleError); // enter the error state } else if ( (eScpiStatus_need_data == global_ctx->sEvent.eStatus) && (eScpiEventWrite == global_ctx->sEvent.eCode) ) { private_ctx->bKeepParserContext = true; // keep parser context til next call nextstate = NULL; // NULL, do not change state } else { // Retrieve the last parsed entity tail and // ... update current input buffer iterator @sMessage.pStr getParsedEntityDetails( &(global_ctx->sParser.xCtxObj), NULL, (void const**)&global_ctx->sMessage.pStr, NULL ); // Is there unprocessed command in input buffer? if( ((ptrdiff_t)global_ctx->sMessage.pEnd - (ptrdiff_t)global_ctx->sMessage.pStr) > 0 ) { (void)global_ctx->sEvent.eCode; global_ctx->sEvent.eStatus = eScpiStatus_need_data; // reset status code (void)global_ctx->sWrite.pData; (void)global_ctx->sWrite.nDataLength; (void)global_ctx->sMessage.w_bEndOfMessage; global_ctx->sMessage.r_bEndOfMessage = false; global_ctx->sMessage.bQuery = false; (void)global_ctx->sMessage.pStr; (void)global_ctx->sMessage.pEnd; (void)global_ctx->sRead.nTotalLength; // see scpi_WriteChunkOutput (void)global_ctx->sRead.pBufferIdx; // see scpi_WriteChunkOutput (void)global_ctx->sRead.nBufferSize; // see scpi_WriteChunkOutput global_ctx->sMessage.bLeadResponseSep = (global_ctx->sRead.vLastBufferIdx != global_ctx->sRead.pBufferIdx); global_ctx->sRead.vLastBufferIdx = global_ctx->sRead.pBufferIdx; // remember the pointer value before the next command nextstate = fsq_GetStateById(this,eSearchForCommandHeader); // try to parse the rest part of data } else { // go to idle state: endof_process_data + eScpiEventEmpty global_ctx->sEvent.eCode = eScpiEventEmpty; (void)global_ctx->sMessage.r_bEndOfMessage; nextstate = this; // stay this state and recall it now } } // "6.1.10.2.1 Message Available Message (MAV)", [1] // The state changed to 'endof_process_data' as far as all the data has been send to host // Reset Message Available indicator scpi_UpdateMessageAvailable(); } break; case eScpiEventEmpty: // idle state { // Respond with empty string: if( global_ctx->sRead.nDataLength == 0 ) // no response in output buffer if( global_ctx->sRead.nBufferSize >= 1 ) // there is vacant room in output buffer { scpi_WriteCharOutput( ' ' ); } scpi_UpdateMessageAvailable(); global_ctx->sMessage.r_bEndOfMessage = true; // no more data available global_ctx->sEvent.eStatus = eScpiStatus_success; nextstate = NULL; // stay this state } break; } return nextstate; }