endof_process_data.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #define SCPI_CORE_STATE__ENDOFDATAPROCESSING_GUARD
  2. #include "app/scpi/CommandParserStates/handle_error.h"
  3. #define SCPI_CORE_PRIVATE // access to 'scpi_core_private.h'
  4. #define SCPI_END_OF_PROCESS_DATA_C // access to some const variables in 'scpi_core_private.h'
  5. #include "app/scpi/scpi_core_private.h"
  6. // =================================================================================
  7. // @sEndOfDataProcessingContext_t
  8. // State's private context typedef
  9. typedef struct
  10. {
  11. bool bKeepParserContext;
  12. }
  13. sEndOfDataProcessingContext_t;
  14. // =================================================================================
  15. // @ctx_EndOfDataProcessing
  16. // State's private context
  17. sEndOfDataProcessingContext_t ctx_EndOfDataProcessing;
  18. // =================================================================================
  19. // @fsqvbl_EndOfDataProcessing
  20. // State's virtual table
  21. static void fsqe_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx );
  22. static void fsql_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx );
  23. static const struct fFSeqEntry_t * fsqf_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx, const struct fFSeqEntry_t * * pnext );
  24. const fFSeqVTable_t fsqvbl_EndOfDataProcessing =
  25. {
  26. .f = fsqf_EndOfDataProcessing,
  27. .enter = fsqe_EndOfDataProcessing,
  28. .leave = fsql_EndOfDataProcessing
  29. };
  30. static void fsqe_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx )
  31. {
  32. sScpiParserContext_t * global_ctx = ctx;
  33. sEndOfDataProcessingContext_t * private_ctx = fsq_GetPrivateCtxRef(this);
  34. // init keep-parser-context indicator
  35. private_ctx->bKeepParserContext = false;
  36. (void)global_ctx;
  37. }
  38. static void fsql_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx )
  39. {
  40. }
  41. static const struct fFSeqEntry_t * fsqf_EndOfDataProcessing( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx, const struct fFSeqEntry_t * * pnext )
  42. {
  43. sScpiParserContext_t * global_ctx = ctx;
  44. sEndOfDataProcessingContext_t * private_ctx = fsq_GetPrivateCtxRef(this);
  45. const fFSeqEntry_t * nextstate = fsq_GetStateById(this,eHandleError); // go next state: eHandleError by default
  46. switch( global_ctx->sEvent.eCode )
  47. {
  48. case eScpiEventRestart:
  49. {
  50. // go to reset state
  51. nextstate = fsq_GetStateById(this,eParserResetState);
  52. }
  53. break;
  54. case eScpiEventError: // Transport error.
  55. {
  56. // Enter error state
  57. nextstate = fsq_GetStateById(this,eHandleError); // enter the error state
  58. }
  59. break;
  60. case eScpiEventWrite:
  61. case eScpiEventRead:
  62. {
  63. nextstate = NULL; // stay in current state
  64. if( eScpiStatus_failed == global_ctx->sEvent.eStatus )
  65. {
  66. // Enter error state
  67. fsq_RaiseError( SCPI_ERROR_STATE, NULL, NULL, 0 );
  68. nextstate = fsq_GetStateById(this,eHandleError); // enter the error state
  69. }
  70. else if (
  71. (eScpiStatus_need_data == global_ctx->sEvent.eStatus)
  72. &&
  73. (eScpiEventWrite == global_ctx->sEvent.eCode)
  74. )
  75. {
  76. private_ctx->bKeepParserContext = true; // keep parser context til next call
  77. nextstate = NULL; // NULL, do not change state
  78. }
  79. else
  80. {
  81. // Retrieve the last parsed entity tail and
  82. // ... update current input buffer iterator @sMessage.pStr
  83. getParsedEntityDetails( &(global_ctx->sParser.xCtxObj), NULL,
  84. (void const**)&global_ctx->sMessage.pStr, NULL );
  85. // Is there unprocessed command in input buffer?
  86. if( ((ptrdiff_t)global_ctx->sMessage.pEnd - (ptrdiff_t)global_ctx->sMessage.pStr) > 0 )
  87. {
  88. (void)global_ctx->sEvent.eCode;
  89. global_ctx->sEvent.eStatus = eScpiStatus_need_data; // reset status code
  90. (void)global_ctx->sWrite.pData;
  91. (void)global_ctx->sWrite.nDataLength;
  92. (void)global_ctx->sMessage.w_bEndOfMessage;
  93. global_ctx->sMessage.r_bEndOfMessage = false;
  94. global_ctx->sMessage.bQuery = false;
  95. (void)global_ctx->sMessage.pStr;
  96. (void)global_ctx->sMessage.pEnd;
  97. (void)global_ctx->sRead.nTotalLength; // see scpi_WriteChunkOutput
  98. (void)global_ctx->sRead.pBufferIdx; // see scpi_WriteChunkOutput
  99. (void)global_ctx->sRead.nBufferSize; // see scpi_WriteChunkOutput
  100. global_ctx->sMessage.bLeadResponseSep = (global_ctx->sRead.vLastBufferIdx != global_ctx->sRead.pBufferIdx);
  101. global_ctx->sRead.vLastBufferIdx = global_ctx->sRead.pBufferIdx; // remember the pointer value before the next command
  102. nextstate = fsq_GetStateById(this,eSearchForCommandHeader); // try to parse the rest part of data
  103. }
  104. else
  105. {
  106. // go to idle state: endof_process_data + eScpiEventEmpty
  107. global_ctx->sEvent.eCode = eScpiEventEmpty;
  108. (void)global_ctx->sMessage.r_bEndOfMessage;
  109. nextstate = this; // stay this state and recall it now
  110. }
  111. }
  112. // "6.1.10.2.1 Message Available Message (MAV)", [1]
  113. // The state changed to 'endof_process_data' as far as all the data has been send to host
  114. // Reset Message Available indicator
  115. scpi_UpdateMessageAvailable();
  116. }
  117. break;
  118. case eScpiEventEmpty: // idle state
  119. {
  120. // Respond with empty string:
  121. if( global_ctx->sRead.nDataLength == 0 ) // no response in output buffer
  122. if( global_ctx->sRead.nBufferSize >= 1 ) // there is vacant room in output buffer
  123. {
  124. scpi_WriteCharOutput( ' ' );
  125. }
  126. scpi_UpdateMessageAvailable();
  127. global_ctx->sMessage.r_bEndOfMessage = true; // no more data available
  128. global_ctx->sEvent.eStatus = eScpiStatus_success;
  129. nextstate = NULL; // stay this state
  130. }
  131. break;
  132. }
  133. return nextstate;
  134. }