shellmatta_ymodem.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /**
  2. * @file shellmatta_ymodem.c
  3. * @brief ymodem functions of shellmatta
  4. * @author Simon Fischer <dev@s-fischer.net>
  5. */
  6. #include "shellmatta_ymodem.h"
  7. #include "shellmatta_crc.h"
  8. #include "shellmatta_utils.h"
  9. #include <stddef.h>
  10. /* current ymodem packet size */
  11. uint16_t yModemPacketSize = YMODEM_PACKET_SIZE;
  12. /* packet counter - counts all correctly received packets during one transmission */
  13. uint16_t shellmatta_ymodem_packet_counter = 0u;
  14. /* counts total amount of data bytes received during one transmission */
  15. uint32_t shellmatta_ymodem_total_bytes_received = 0u;
  16. /* counts total amount of data bytes received during one packet */
  17. uint16_t shellmatta_ymodem_byte_counter = 0u;
  18. uint8_t fileNameDelimiterPosition = 255u;
  19. uint8_t fileSizeDelimiterPosition = 255u;
  20. /* structure of a packet consisting of data and metadata */
  21. shellmatta_ymodem_packet_t shellmatta_ymodem_packet;
  22. /* holds information about which data type is currently actice: YMODEM_NONE, YMODEM_HEADER, YMODEM_BODY, YMODEM_FOOTER */
  23. shellmatta_ymodem_datatype_t shellmatta_ymodem_current_data_type = YMODEM_NONE;
  24. /* structure of ymodem callback functions */
  25. shellmatta_ymodem_callbacks_t shellmatta_ymodem_callbacks;
  26. /**
  27. * @brief Initialise the ymodem prior to actually receiving data
  28. * @param[in, out] handle shellmatta handle of the instance
  29. * @param[in] recvBuffer pointer to the buffer to save the received payload in
  30. * @param[in] fileSize pointer to the file size variable
  31. * @param[in] packetSize pointer to the packet size variable
  32. * @param[in] callbacks callback functions for the ymodem module
  33. */
  34. void shellmatta_ymodem_init(shellmatta_handle_t handle,
  35. uint8_t* recvBuffer,
  36. uint32_t* fileSize,
  37. uint16_t* packetSize,
  38. shellmatta_ymodem_callbacks_t callbacks)
  39. {
  40. if ((void*)0u == recvBuffer) return;
  41. /* init packet structure */
  42. shellmatta_ymodem_packet.packetNumber = 0u;
  43. shellmatta_ymodem_packet.reversePacketNumber = 0u;
  44. shellmatta_ymodem_packet.packetCrc = 0u;
  45. shellmatta_ymodem_packet.packetSize = packetSize;
  46. shellmatta_ymodem_packet.fileSize = fileSize;
  47. shellmatta_ymodem_packet.packetData = recvBuffer;
  48. /* init callbacks */
  49. shellmatta_ymodem_callbacks = callbacks;
  50. /* init ymodem state */
  51. shellmatta_ymodem_set_state(handle, WAIT_FOR_START);
  52. /* init current data type */
  53. shellmatta_ymodem_current_data_type = YMODEM_NONE;
  54. }
  55. /**
  56. * @brief change the current state of the ymodem module
  57. * @param[in, out] handle shellmatta handle of the instance
  58. * @param[in] newState the state the ymodem module should be changed to
  59. */
  60. void shellmatta_ymodem_set_state(shellmatta_handle_t handle, shellmatta_ymodem_state_t newState)
  61. {
  62. ((shellmatta_instance_t*)handle)->ymodemState = newState;
  63. }
  64. /**
  65. * @brief Returns the current state of the ymodem module
  66. * @param[in, out] handle shellmatta handle of the instance
  67. * @return the current state of the ymodem module
  68. */
  69. shellmatta_ymodem_state_t shellmatta_ymodem_get_state(shellmatta_handle_t handle)
  70. {
  71. return ((shellmatta_instance_t*)handle)->ymodemState;
  72. }
  73. /**
  74. * @brief State machine that processes bytewise input during active ymodem transmission
  75. * @param[in, out] handle shellmatta handle of the instance
  76. * @param[in] byteIn the byte to be processed
  77. * @note won't do anything if ymodem module is not initialized
  78. */
  79. void shellmatta_ymodem_receive_packet(shellmatta_handle_t handle, uint8_t byteIn)
  80. {
  81. static uint32_t fileSize = 0u;
  82. static char fileSizeStr[7u]; /* hopefully no more bytes than a million will ever be transmitted */
  83. shellmatta_ymodem_rcv_retcode_t recvRetCode;
  84. recvRetCode = shellmatta_ymodem_receive_byte(handle, byteIn);
  85. switch (shellmatta_ymodem_get_state(handle))
  86. {
  87. case INACTIVE:
  88. /* cant do anything if ymodem module was not correctly initialized */
  89. return;
  90. case WAIT_FOR_START:
  91. /* wait for start symbol of a packet */
  92. switch (shellmatta_ymodem_current_data_type)
  93. {
  94. case YMODEM_NONE: /* go here if the header packet is to be expected */
  95. if (recvRetCode == SOH_RECEIVED || recvRetCode == STX_RECEIVED)
  96. {
  97. /* reset packet counter */
  98. shellmatta_ymodem_packet_counter = 0u;
  99. shellmatta_ymodem_byte_counter = 0u;
  100. shellmatta_ymodem_set_state(handle, RECEIVE_PACKET);
  101. shellmatta_ymodem_current_data_type = YMODEM_HEADER;
  102. }
  103. break;
  104. case YMODEM_HEADER: /* go here if the first body packet is to be expected */
  105. if (recvRetCode == STX_RECEIVED || recvRetCode == SOH_RECEIVED)
  106. {
  107. shellmatta_ymodem_byte_counter = 0u;
  108. shellmatta_ymodem_set_state(handle, RECEIVE_PACKET);
  109. shellmatta_ymodem_current_data_type = YMODEM_BODY;
  110. }
  111. break;
  112. case YMODEM_BODY: /* go here if the data transmission loop is active */
  113. if (recvRetCode == SOH_RECEIVED || recvRetCode == STX_RECEIVED)
  114. {
  115. shellmatta_ymodem_byte_counter = 0u;
  116. /* stay in body when SOH was received */
  117. shellmatta_ymodem_set_state(handle, RECEIVE_PACKET);
  118. shellmatta_ymodem_current_data_type = YMODEM_BODY;
  119. }
  120. else /* go here if the end of transmission symbol is received */
  121. if (recvRetCode == EOT_RECEIVED)
  122. {
  123. shellmatta_ymodem_byte_counter = 0u;
  124. /* answer with ACK */
  125. shellmatta_ymodem_ack(handle);
  126. /* then send 0x43 symbol */
  127. shellmatta_ymodem_control(handle, YMODEM_CRC);
  128. /* go to footer when EOT was received */
  129. shellmatta_ymodem_current_data_type = YMODEM_FOOTER;
  130. /* then wait for SOH */
  131. }
  132. break;
  133. case YMODEM_FOOTER: /* go here if the end of transmission packet is to be expected */
  134. /* it _may_ be, that EOT is sent multiple times, repeat previous procedure */
  135. if (recvRetCode == EOT_RECEIVED)
  136. {
  137. /* answer with ACK */
  138. shellmatta_ymodem_ack(handle);
  139. /* then send 0x43 symbol */
  140. shellmatta_ymodem_control(handle, YMODEM_CRC);
  141. }
  142. if (recvRetCode == SOH_RECEIVED)
  143. {
  144. /* reset packet counter */
  145. shellmatta_ymodem_packet_counter = 0u;
  146. /* reset byte counter to avoid error by one caused by previously received EOT symbol */
  147. shellmatta_ymodem_byte_counter = 0u;
  148. shellmatta_ymodem_set_state(handle, RECEIVE_PACKET);
  149. }
  150. break;
  151. default:
  152. break;
  153. }
  154. break;
  155. case RECEIVE_PACKET:
  156. /* receiving data */
  157. if (recvRetCode == DATA_RECEIVED)
  158. {
  159. switch (shellmatta_ymodem_current_data_type)
  160. {
  161. case YMODEM_HEADER:
  162. switch (shellmatta_ymodem_byte_counter)
  163. {
  164. /* first two bytes are packet number and reverse packet number */
  165. case 0:
  166. shellmatta_ymodem_packet.packetNumber = byteIn;
  167. break;
  168. case 1:
  169. shellmatta_ymodem_packet.reversePacketNumber = byteIn;
  170. break;
  171. default:
  172. break;
  173. }
  174. /* after packet numbers, data field begins */
  175. if ((shellmatta_ymodem_byte_counter >= YMODEM_HEADER_DATA_OFFSET) &&
  176. (shellmatta_ymodem_byte_counter < YMODEM_HEADER_CRC_POSITION))
  177. {
  178. shellmatta_ymodem_packet.packetData[shellmatta_ymodem_byte_counter - YMODEM_HEADER_DATA_OFFSET] = byteIn;
  179. /* check for filename */
  180. if (shellmatta_ymodem_byte_counter < fileNameDelimiterPosition)
  181. {
  182. /* find NULL-Terminator in filename */
  183. if (byteIn == YMODEM_NULL)
  184. {
  185. fileNameDelimiterPosition = shellmatta_ymodem_byte_counter + 1;
  186. }
  187. }
  188. /* after filename the filesize begins */
  189. else
  190. if (shellmatta_ymodem_byte_counter >= fileNameDelimiterPosition &&
  191. (shellmatta_ymodem_byte_counter < fileSizeDelimiterPosition))
  192. {
  193. /* find space as delimiter after filesize */
  194. if (byteIn == YMODEM_SPACE)
  195. {
  196. fileSizeDelimiterPosition = shellmatta_ymodem_byte_counter;
  197. /* convert file size string to actual number */
  198. fileSize = utils_shellAsciiToUInt32(fileSizeStr, fileSizeDelimiterPosition - fileNameDelimiterPosition);
  199. *shellmatta_ymodem_packet.fileSize = fileSize;
  200. }
  201. /* save characters in string otherwise */
  202. else
  203. {
  204. fileSizeStr[shellmatta_ymodem_byte_counter - fileNameDelimiterPosition] = byteIn;
  205. }
  206. }
  207. else
  208. {
  209. /* some meta data from sender, possibly file date */
  210. /* not needed for now */
  211. }
  212. }
  213. /* after data field, crc begins */
  214. if (shellmatta_ymodem_byte_counter >= YMODEM_HEADER_CRC_POSITION)
  215. {
  216. if (shellmatta_ymodem_byte_counter == YMODEM_HEADER_CRC_POSITION)
  217. {
  218. /* upper byte */
  219. shellmatta_ymodem_packet.packetCrc = byteIn << 8u;
  220. }
  221. if (shellmatta_ymodem_byte_counter == YMODEM_HEADER_CRC_POSITION + 1)
  222. {
  223. /* lower byte */
  224. shellmatta_ymodem_packet.packetCrc |= byteIn;
  225. /* change ymodem state to check packet */
  226. shellmatta_ymodem_check_packet(handle);
  227. }
  228. }
  229. shellmatta_ymodem_byte_counter++;
  230. break;
  231. case YMODEM_BODY:
  232. switch (shellmatta_ymodem_byte_counter)
  233. {
  234. case 0:
  235. shellmatta_ymodem_packet.packetNumber = byteIn;
  236. break;
  237. case 1:
  238. shellmatta_ymodem_packet.reversePacketNumber = byteIn;
  239. break;
  240. default:
  241. break;
  242. }
  243. /* after data field, crc begins */
  244. if (shellmatta_ymodem_byte_counter >= yModemPacketSize + YMODEM_HEADER_DATA_OFFSET)
  245. {
  246. if (shellmatta_ymodem_byte_counter == yModemPacketSize + YMODEM_HEADER_DATA_OFFSET)
  247. {
  248. /* upper byte */
  249. shellmatta_ymodem_packet.packetCrc = byteIn << 8u;
  250. }
  251. if (shellmatta_ymodem_byte_counter == yModemPacketSize + YMODEM_HEADER_DATA_OFFSET + 1)
  252. {
  253. /* lower byte */
  254. shellmatta_ymodem_packet.packetCrc |= byteIn;
  255. /* change ymodem state to check packet */
  256. shellmatta_ymodem_check_packet(handle);
  257. }
  258. }
  259. else
  260. if ((shellmatta_ymodem_byte_counter > 1) &&
  261. (shellmatta_ymodem_byte_counter < (yModemPacketSize + YMODEM_HEADER_DATA_OFFSET)))
  262. {
  263. shellmatta_ymodem_packet.packetData[shellmatta_ymodem_byte_counter - YMODEM_HEADER_DATA_OFFSET] = byteIn;
  264. }
  265. shellmatta_ymodem_byte_counter++;
  266. break;
  267. case YMODEM_FOOTER:
  268. /* reset packet counter */
  269. shellmatta_ymodem_packet_counter = 0;
  270. switch (shellmatta_ymodem_byte_counter)
  271. {
  272. case 0:
  273. shellmatta_ymodem_packet.packetNumber = byteIn;
  274. break;
  275. case 1:
  276. shellmatta_ymodem_packet.reversePacketNumber = byteIn;
  277. break;
  278. default:
  279. break;
  280. }
  281. /* after data field, crc begins */
  282. if (shellmatta_ymodem_byte_counter >= yModemPacketSize + YMODEM_HEADER_DATA_OFFSET)
  283. {
  284. if (shellmatta_ymodem_byte_counter == yModemPacketSize + YMODEM_HEADER_DATA_OFFSET)
  285. {
  286. /* upper byte */
  287. shellmatta_ymodem_packet.packetCrc = byteIn << 8u;
  288. }
  289. if (shellmatta_ymodem_byte_counter == yModemPacketSize + YMODEM_HEADER_DATA_OFFSET + 1)
  290. {
  291. /* lower byte */
  292. shellmatta_ymodem_packet.packetCrc |= byteIn;
  293. /* change ymodem state to check packet */
  294. shellmatta_ymodem_check_packet(handle);
  295. }
  296. }
  297. else
  298. if ((shellmatta_ymodem_byte_counter > 1) &&
  299. (shellmatta_ymodem_byte_counter < (yModemPacketSize + YMODEM_HEADER_DATA_OFFSET)))
  300. {
  301. /* save data */
  302. shellmatta_ymodem_packet.packetData[shellmatta_ymodem_byte_counter - YMODEM_HEADER_DATA_OFFSET] = byteIn;
  303. }
  304. shellmatta_ymodem_byte_counter++;
  305. break;
  306. default:
  307. break;
  308. }
  309. }
  310. break;
  311. default:
  312. break;
  313. }
  314. }
  315. shellmatta_retCode_t shellmatta_ymodem_processByte(shellmatta_handle_t handle, char data)
  316. {
  317. shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
  318. uint32_t i;
  319. /** -# check if session is cancelled -accept only if ymodem is between packets */
  320. if(('\x03' == data) && (inst->ymodemState == WAIT_FOR_START))
  321. {
  322. /** -# explicitly reset ymodem with cancel, if it was active */
  323. shellmatta_ymodem_reset(handle, true);
  324. utils_terminateInput(inst);
  325. return SHELLMATTA_ERROR;
  326. }
  327. shellmatta_ymodem_receive_packet(handle, data);
  328. if ((0u == size) && (inst->ymodemState == WAIT_FOR_START))
  329. {
  330. /* send initial ymodem symbol to start transmission */
  331. shellmatta_ymodem_control(handle, YMODEM_CRC);
  332. }
  333. return SHELLMATTA_OK;
  334. }
  335. /**
  336. * @brief Gives a return code depending on symbol received at different states of the ymodem module
  337. * @param[in, out] handle shellmatta handle of the instance
  338. * @param[in] byteIn currently processed input byte
  339. */
  340. shellmatta_ymodem_rcv_retcode_t shellmatta_ymodem_receive_byte(shellmatta_handle_t handle, uint8_t byteIn)
  341. {
  342. shellmatta_ymodem_rcv_retcode_t ret;
  343. if (WAIT_FOR_START == shellmatta_ymodem_get_state(handle))
  344. {
  345. switch (byteIn)
  346. {
  347. case YMODEM_SOH:
  348. /* start of header -> default packet size */
  349. yModemPacketSize = YMODEM_PACKET_SIZE;
  350. ret = SOH_RECEIVED;
  351. break;
  352. case YMODEM_STX:
  353. /* start of header -> extended packet size */
  354. yModemPacketSize = YMODEM_PACKET_SIZE_1K;
  355. ret = STX_RECEIVED;
  356. break;
  357. case YMODEM_EOT:
  358. /* end of transmission -> data transmission complete */
  359. ret = EOT_RECEIVED;
  360. break;
  361. case YMODEM_CA:
  362. /* cancel transmssion -> reset state machine */
  363. ret = CA_RECEIVED;
  364. break;
  365. default:
  366. /* no other data should be received in this state */
  367. ret = ERROR;
  368. break;
  369. }
  370. /* give packet size back to upper layer */
  371. *shellmatta_ymodem_packet.packetSize = yModemPacketSize;
  372. }
  373. else
  374. if (RECEIVE_PACKET == shellmatta_ymodem_get_state(handle))
  375. {
  376. ret = DATA_RECEIVED;
  377. }
  378. return ret;
  379. }
  380. /**
  381. * @brief Checks packet data for validity and sends ACK or NAK accordingly
  382. * @param[in, out] handle shellmatta handle of the instance
  383. * @note Only to be called after full packet is received
  384. * @note Will call yModemRecvPacketCallback when packet is received correctly
  385. * @note Will call ymodemTransmissionCompleteCallback when transmission is completed
  386. */
  387. void shellmatta_ymodem_check_packet(shellmatta_handle_t handle)
  388. {
  389. uint16_t computedCrc = 0u;
  390. if (shellmatta_ymodem_packet.packetNumber != (0xFF - shellmatta_ymodem_packet.reversePacketNumber))
  391. {
  392. shellmatta_ymodem_nak(handle);
  393. return;
  394. }
  395. /* compare to internal packet counter */
  396. if (shellmatta_ymodem_packet.packetNumber != ((uint8_t)shellmatta_ymodem_packet_counter)) /* uint8_t cast to cause overflow */
  397. {
  398. shellmatta_ymodem_nak(handle);
  399. return;
  400. }
  401. /* compare packet crc only after other checks succeeded */
  402. computedCrc = crc16Calc((const char*)shellmatta_ymodem_packet.packetData, yModemPacketSize);
  403. //! uncomment to ignore crc check for debug purposes
  404. if (shellmatta_ymodem_packet.packetCrc != computedCrc)
  405. {
  406. shellmatta_ymodem_nak(handle);
  407. return;
  408. }
  409. /* if previous checks passed, packet is acknowledged */
  410. (void) computedCrc;
  411. shellmatta_ymodem_total_bytes_received += shellmatta_ymodem_byte_counter;
  412. shellmatta_ymodem_byte_counter = 0u;
  413. shellmatta_ymodem_ack(handle);
  414. if (shellmatta_ymodem_current_data_type == YMODEM_HEADER)
  415. {
  416. /* send additional CRC symbol if the packet was a header packet */
  417. shellmatta_ymodem_control(handle, YMODEM_CRC);
  418. }
  419. /* callback handling */
  420. switch (shellmatta_ymodem_current_data_type)
  421. {
  422. case YMODEM_NONE:
  423. /* shouldn't happen */
  424. break;
  425. case YMODEM_HEADER:
  426. /* nothing to do after receiving the header packet */
  427. break;
  428. case YMODEM_BODY:
  429. /* call the ymodem receive packet callback */
  430. if (NULL != shellmatta_ymodem_callbacks.yModemRecvPacketCallback)
  431. {
  432. shellmatta_ymodem_callbacks.yModemRecvPacketCallback();
  433. }
  434. break;
  435. case YMODEM_FOOTER:
  436. /* call the ymodem transmission complete callback */
  437. if (NULL != shellmatta_ymodem_callbacks.ymodemTransmissionCompleteCallback)
  438. {
  439. shellmatta_ymodem_callbacks.ymodemTransmissionCompleteCallback();
  440. }
  441. break;
  442. default:
  443. break;
  444. }
  445. }
  446. /**
  447. * @brief Acknowledge handling. Will send ACK and set ymodem state back to WAIT_FOR_START
  448. * @param[in, out] handle shellmatta handle of the instance
  449. */
  450. void shellmatta_ymodem_ack(shellmatta_handle_t handle)
  451. {
  452. shellmatta_ymodem_control(handle, YMODEM_ACK);
  453. shellmatta_ymodem_packet_counter++;
  454. shellmatta_ymodem_set_state(handle, WAIT_FOR_START);
  455. }
  456. /**
  457. * @brief Not-Acknowledge handling. Will send NAK and set ymodem state back to WAIT_FOR_START
  458. * @param[in, out] handle shellmatta handle of the instance
  459. */
  460. void shellmatta_ymodem_nak(shellmatta_handle_t handle)
  461. {
  462. shellmatta_ymodem_set_state(handle, WAIT_FOR_START);
  463. /* set back current data type to prevent false forward stepping */
  464. switch (shellmatta_ymodem_current_data_type)
  465. {
  466. case YMODEM_NONE:
  467. /* no handling needed */
  468. break;
  469. case YMODEM_HEADER:
  470. shellmatta_ymodem_control(handle, YMODEM_NAK);
  471. break;
  472. case YMODEM_BODY:
  473. /* YMODEM_BODY stays in YMODEM_BODY */
  474. shellmatta_ymodem_control(handle, YMODEM_NAK);
  475. shellmatta_ymodem_current_data_type = YMODEM_BODY;
  476. break;
  477. case YMODEM_FOOTER:
  478. /* YMODEM_FOOTER as well */
  479. shellmatta_ymodem_current_data_type = YMODEM_FOOTER;
  480. break;
  481. default:
  482. break;
  483. }
  484. }
  485. /**
  486. * @brief forwards the given character to write-function without formatting
  487. * @param[in] handle shellmatta handle of the instance
  488. * @param[in] c character to be sent
  489. */
  490. void shellmatta_ymodem_control(shellmatta_handle_t handle, const char c)
  491. {
  492. ((shellmatta_instance_t*)handle)->write(&c, 1);
  493. }
  494. /**
  495. * @brief reset function for the ymodem module
  496. * @param[in, out] handle shellmatta handle of the instance
  497. * @param[in] doCancel flag to execute the cancel-callback
  498. */
  499. void shellmatta_ymodem_reset(shellmatta_handle_t handle, bool doCancel)
  500. {
  501. /* call cancel callback function */
  502. if (doCancel)
  503. {
  504. /* send cancel symbol */
  505. shellmatta_ymodem_control(handle, YMODEM_CA);
  506. if (NULL != shellmatta_ymodem_callbacks.yModemCancelCallback)
  507. {
  508. shellmatta_ymodem_callbacks.yModemCancelCallback();
  509. }
  510. }
  511. /* reset global variables */
  512. shellmatta_ymodem_byte_counter = 0u;
  513. shellmatta_ymodem_packet_counter = 0u;
  514. shellmatta_ymodem_total_bytes_received = 0u;
  515. fileNameDelimiterPosition = 255u;
  516. fileSizeDelimiterPosition = 255u;
  517. /* reset all ymodem_packet data */
  518. shellmatta_ymodem_packet.packetNumber = 0u;
  519. shellmatta_ymodem_packet.reversePacketNumber = 0u;
  520. shellmatta_ymodem_packet.packetCrc = 0u;
  521. shellmatta_ymodem_packet.packetSize = 0u;
  522. shellmatta_ymodem_packet.fileSize = 0u;
  523. shellmatta_ymodem_packet.packetData = 0u;
  524. /* set ymodem to inactive */
  525. shellmatta_ymodem_set_state(handle, INACTIVE);
  526. shellmatta_ymodem_current_data_type = YMODEM_NONE;
  527. #ifdef SHELLMATTA_TRANSPORT
  528. /* re-enable transport layer */
  529. ((shellmatta_instance_t*)handle)->transportEnabled = true;
  530. #endif
  531. }
  532. shellmatta_ymodem_datatype_t shellmatta_ymodem_get_current_datatype(void)
  533. {
  534. return shellmatta_ymodem_current_data_type;
  535. }
  536. /**
  537. * @brief starts the ymodem receive module
  538. * @param[in] handle shellmatta instance handle
  539. * @param[in] buffer pointer to where the received data is stored
  540. * @param[in] fileSize pointer to where the file size is stored
  541. * @param[in] packetSize pointer to where the packet size is stored
  542. * @param[in] callbacks callback functions for ymodem module
  543. * @note disables the transport layer if active
  544. */
  545. uint8_t shellmatta_ymodem( shellmatta_handle_t handle,
  546. uint8_t* buffer,
  547. uint32_t* fileSize,
  548. uint16_t* packetSize,
  549. shellmatta_ymodem_callbacks_t callbacks)
  550. {
  551. shellmatta_ymodem_init(handle, buffer, fileSize, packetSize, callbacks);
  552. /* send initial ymodem symbol to start transmission */
  553. shellmatta_ymodem_control(handle, YMODEM_CRC);
  554. return 0;
  555. }
  556. /**
  557. * @brief Resets the ymodem module
  558. * @param[in] doCancel Set this flag to execute the cancel-callback function within the ymodem-reset function
  559. * @note call this function after file transmission is done or cancelled
  560. */
  561. void shellmatta_ymodem_end(shellmatta_handle_t handle, bool doCancel)
  562. {
  563. shellmatta_ymodem_reset(handle, doCancel);
  564. /* clear any possibly leftover inputs */
  565. utils_clearInput((shellmatta_instance_t*)handle);
  566. }
  567. bool shellmatta_ymodem_is_active(void)
  568. {
  569. return shellmatta_ymodem_get_current_datatype() != YMODEM_NONE;
  570. }