shellmatta_transport.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /**
  2. * @file shellmatta_transport.c
  3. * @brief transport layer functions of shellmatta
  4. * @author Simon Fischer <fischer.simon.1991@gmail.com>
  5. */
  6. #include "shellmatta_transport.h"
  7. #include "shellmatta_crc.h"
  8. #include <string.h>
  9. /* init global variables */
  10. uint8_t protocolVersion = 0u;
  11. shellmatta_transport_packet_t packetType = 0u;
  12. uint8_t payloadLength = 0u;
  13. uint8_t source = 0u;
  14. uint8_t destination = 0u;
  15. uint32_t crc32 = 0u;
  16. uint8_t payloadCounter = 0u;
  17. uint8_t crcCounter = 0u;
  18. uint32_t packetSequenceCounter_h2s = 0u;
  19. uint32_t packetSequenceCounter_s2h = 0u;
  20. shellmatta_transport_layer_t transportLayerInst = {
  21. 0,
  22. 0,
  23. STATE_GET_SOH,
  24. false,
  25. false,
  26. false,
  27. NULL
  28. };
  29. char payloadBuffer[SHELLMATTA_PAYLOAD_MAXLENGTH + 1];
  30. shellmatta_retCode_t shellmatta_init_transport_inst()
  31. {
  32. transportLayerInst.h2s_sequenceCnt = 0;
  33. transportLayerInst.s2h_sequenceCnt = 0;
  34. transportLayerInst.state = STATE_GET_SOH;
  35. transportLayerInst.mandatory = false;
  36. transportLayerInst.active = false;
  37. transportLayerInst.continueStep = false;
  38. memset(payloadBuffer, 0, SHELLMATTA_PAYLOAD_MAXLENGTH + 1);
  39. return SHELLMATTA_OK;
  40. }
  41. shellmatta_retCode_t shellmatta_reset_transport()
  42. {
  43. transportLayerInst.state = STATE_GET_SOH;
  44. protocolVersion = 0u;
  45. packetType = 0u;
  46. payloadLength = 0u;
  47. source = 0u;
  48. destination = 0u;
  49. crc32 = 0u;
  50. payloadCounter = 0u;
  51. crcCounter = 0u;
  52. transportLayerInst.active = false;
  53. memset(payloadBuffer, 0, SHELLMATTA_PAYLOAD_MAXLENGTH + 1);
  54. return SHELLMATTA_OK;
  55. }
  56. shellmatta_retCode_t shellmatta_handle_transport_fsm(char *data)
  57. {
  58. switch (transportLayerInst.state)
  59. {
  60. case STATE_GET_SOH:
  61. if (SHELLMATTA_START_OF_HEADER == *data)
  62. {
  63. transportLayerInst.state = STATE_GET_PROTOCOL_VERSION;
  64. transportLayerInst.active = true;
  65. }
  66. else
  67. {
  68. transportLayerInst.state = STATE_MANUAL_INPUT;
  69. transportLayerInst.active = false;
  70. }
  71. break;
  72. case STATE_MANUAL_INPUT:
  73. break;
  74. case STATE_GET_PROTOCOL_VERSION:
  75. transportLayerInst.state = STATE_GET_PACKET_TYPE;
  76. break;
  77. case STATE_GET_PACKET_TYPE:
  78. transportLayerInst.state = STATE_GET_PAYLOAD_LENGTH;
  79. break;
  80. case STATE_GET_PAYLOAD_LENGTH:
  81. transportLayerInst.state = STATE_GET_SOURCE;
  82. break;
  83. case STATE_GET_SOURCE:
  84. transportLayerInst.state = STATE_GET_DESTINATION;
  85. break;
  86. case STATE_GET_DESTINATION:
  87. transportLayerInst.state = STATE_GET_H2S_SEQUENCE_CNT;
  88. break;
  89. case STATE_GET_H2S_SEQUENCE_CNT:
  90. transportLayerInst.state = STATE_GET_S2H_SEQUENCE_CNT;
  91. break;
  92. case STATE_GET_S2H_SEQUENCE_CNT:
  93. transportLayerInst.state = STATE_GET_PAYLOAD;
  94. break;
  95. case STATE_GET_PAYLOAD:
  96. if ( (payloadLength <= payloadCounter)
  97. && (true == transportLayerInst.active))
  98. {
  99. transportLayerInst.state = STATE_GET_CRC;
  100. }
  101. break;
  102. case STATE_GET_CRC:
  103. if (SHELLMATTA_LENGTH_CRC <= crcCounter)
  104. {
  105. char data[SHELLMATTA_PAYLOAD_MAXLENGTH + 1 + SHELLMATTA_HEADER_LENGTH];
  106. memset(data, 0, SHELLMATTA_PAYLOAD_MAXLENGTH + 1 + SHELLMATTA_HEADER_LENGTH);
  107. data[0] = SHELLMATTA_START_OF_HEADER;
  108. data[1] = protocolVersion;
  109. data[2] = packetType;
  110. data[3] = payloadLength;
  111. data[4] = source;
  112. data[5] = destination;
  113. data[6] = transportLayerInst.h2s_sequenceCnt;
  114. data[7] = transportLayerInst.s2h_sequenceCnt;
  115. strncat(&data[8], payloadBuffer, payloadLength);
  116. uint32_t refCrc;
  117. refCrc = crc32Calc(data, SHELLMATTA_HEADER_LENGTH + payloadLength);
  118. if (crc32 == refCrc)
  119. {
  120. /* crc is correct */
  121. switch (packetType)
  122. {
  123. case PACKET_DATA:
  124. transportLayerInst.state = STATE_PROCESS_PAYLOAD;
  125. transportLayerInst.h2s_sequenceCnt++;
  126. break;
  127. case PACKET_SEQ_CNT_REQUEST:
  128. transportLayerInst.h2s_sequenceCnt++;
  129. break;
  130. case PACKET_SEQ_CNT_RESPOND:
  131. transportLayerInst.h2s_sequenceCnt++;
  132. break;
  133. case PACKET_MAX_BUFFERSIZE_REQUEST:
  134. transportLayerInst.h2s_sequenceCnt++;
  135. break;
  136. case PACKET_MAX_BUFFERSIZE_RESPOND:
  137. transportLayerInst.h2s_sequenceCnt++;
  138. break;
  139. case PACKET_SEARCH_DEVICE_REQUEST:
  140. transportLayerInst.h2s_sequenceCnt++;
  141. break;
  142. case PACKET_SEARCH_DEVICE_RESPOND:
  143. transportLayerInst.h2s_sequenceCnt++;
  144. break;
  145. case PACKET_SET_ADDRESS_REQUEST:
  146. transportLayerInst.h2s_sequenceCnt++;
  147. break;
  148. case PACKET_SET_ADDRESS_RESPOND:
  149. transportLayerInst.h2s_sequenceCnt++;
  150. break;
  151. /* should not happen */
  152. default:
  153. break;
  154. }
  155. break;
  156. }
  157. else
  158. {
  159. /* crc is incorrect */
  160. return SHELLMATTA_ERROR;
  161. }
  162. }
  163. break;
  164. case STATE_PROCESS_PAYLOAD:
  165. transportLayerInst.state = STATE_GET_SOH;
  166. protocolVersion = 0u;
  167. packetType = 0u;
  168. payloadLength = 0u;
  169. source = 0u;
  170. destination = 0u;
  171. crc32 = 0u;
  172. payloadCounter = 0u;
  173. crcCounter = 0u;
  174. transportLayerInst.active = false;
  175. memset(payloadBuffer, 0, SHELLMATTA_PAYLOAD_MAXLENGTH + 1);
  176. break;
  177. default:
  178. break;
  179. }
  180. return SHELLMATTA_OK;
  181. }
  182. shellmatta_retCode_t shellmatta_write_transport(const char* data, uint32_t length)
  183. {
  184. uint8_t outputBuffer[ SHELLMATTA_HEADER_LENGTH + /* length of header */
  185. SHELLMATTA_PAYLOAD_MAXLENGTH + 1 + /* max length of payload */
  186. SHELLMATTA_LENGTH_CRC]; /* length of crc */
  187. uint8_t outPayloadLength = length + SHELLMATTA_HEADER_LENGTH + SHELLMATTA_LENGTH_CRC;
  188. outputBuffer[0] = SHELLMATTA_START_OF_HEADER;
  189. outputBuffer[1] = 0x01u;
  190. outputBuffer[2] = 0x00u;
  191. outputBuffer[3] = length;
  192. outputBuffer[4] = 0x01u;
  193. outputBuffer[5] = 0x00u;
  194. outputBuffer[6] = transportLayerInst.h2s_sequenceCnt;
  195. outputBuffer[7] = ++transportLayerInst.s2h_sequenceCnt;
  196. memcpy(&outputBuffer[8], data, length);
  197. uint32_t outCrc = crc32Calc((char*) outputBuffer, SHELLMATTA_HEADER_LENGTH + length);
  198. outputBuffer[length + SHELLMATTA_HEADER_LENGTH + 0] = (uint8_t)(outCrc >> 0);
  199. outputBuffer[length + SHELLMATTA_HEADER_LENGTH + 1] = (uint8_t)(outCrc >> 8);
  200. outputBuffer[length + SHELLMATTA_HEADER_LENGTH + 2] = (uint8_t)(outCrc >> 16);
  201. outputBuffer[length + SHELLMATTA_HEADER_LENGTH + 3] = (uint8_t)(outCrc >> 24);
  202. shellmatta_retCode_t ret = transportLayerInst.originalWrite((char*) outputBuffer, outPayloadLength);
  203. return ret;
  204. }