ymodem.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * COPYRIGHT (C) 2012, Real-Thread Information Technology Ltd
  3. * All rights reserved
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2013-04-14 Grissiom initial implementation
  10. * 2019-12-09 Steven Liu add YMODEM send protocol
  11. */
  12. #ifndef __YMODEM_H__
  13. #define __YMODEM_H__
  14. #include "rtthread.h"
  15. #include <string.h>
  16. /* RT-FOTA module define */
  17. #define RT_FOTA_SW_VERSION "1.0.0"
  18. /* Enable Ymodem OTA */
  19. #define PKG_USING_YMODEM_OTA
  20. /* FOTA application partition name */
  21. #ifndef RT_FOTA_APP_PART_NAME
  22. #define RT_FOTA_APP_PART_NAME "app"
  23. #endif
  24. /* FOTA download partition name */
  25. #ifndef RT_FOTA_FM_PART_NAME
  26. #define RT_FOTA_FM_PART_NAME "fm_area"
  27. #endif
  28. /* FOTA default partition name */
  29. #ifndef RT_FOTA_DF_PART_NAME
  30. #define RT_FOTA_DF_PART_NAME "df_area"
  31. #endif
  32. /* AES256 encryption algorithm option */
  33. #define RT_FOTA_ALGO_AES_IV "0123456789ABCDEF"
  34. #define RT_FOTA_ALGO_AES_KEY "0123456789ABCDEF0123456789ABCDEF"
  35. /* The word "RYM" is stand for "Real-YModem". */
  36. enum rym_code
  37. {
  38. RYM_CODE_NONE = 0x00,
  39. RYM_CODE_SOH = 0x01,
  40. RYM_CODE_STX = 0x02,
  41. RYM_CODE_EOT = 0x04,
  42. RYM_CODE_ACK = 0x06,
  43. RYM_CODE_NAK = 0x15,
  44. RYM_CODE_CAN = 0x18,
  45. RYM_CODE_C = 0x43,
  46. };
  47. /* RYM error code
  48. *
  49. * We use the rt_err_t to return error values. We take use of current error
  50. * codes available in RTT and append ourselves.
  51. */
  52. /* timeout on handshake */
  53. #define RYM_ERR_TMO 0x70
  54. /* wrong code, wrong SOH, STX etc. */
  55. #define RYM_ERR_CODE 0x71
  56. /* wrong sequence number */
  57. #define RYM_ERR_SEQ 0x72
  58. /* wrong CRC checksum */
  59. #define RYM_ERR_CRC 0x73
  60. /* not enough data received */
  61. #define RYM_ERR_DSZ 0x74
  62. /* the transmission is aborted by user */
  63. #define RYM_ERR_CAN 0x75
  64. /* wrong answer, wrong ACK or C */
  65. #define RYM_ERR_ACK 0x76
  66. /* transmit file invalid */
  67. #define RYM_ERR_FILE 0x77
  68. /* how many ticks wait for chars between packet. */
  69. #ifndef RYM_WAIT_CHR_TICK
  70. #define RYM_WAIT_CHR_TICK (RT_TICK_PER_SECOND * 3)
  71. #endif
  72. /* how many ticks wait for between packet. */
  73. #ifndef RYM_WAIT_PKG_TICK
  74. #define RYM_WAIT_PKG_TICK (RT_TICK_PER_SECOND * 3)
  75. #endif
  76. /* how many ticks between two handshake code. */
  77. #ifndef RYM_CHD_INTV_TICK
  78. #define RYM_CHD_INTV_TICK (RT_TICK_PER_SECOND * 3)
  79. #endif
  80. /* how many CAN be sent when user active end the session. */
  81. #ifndef RYM_END_SESSION_SEND_CAN_NUM
  82. #define RYM_END_SESSION_SEND_CAN_NUM 0x07
  83. #endif
  84. enum rym_stage
  85. {
  86. RYM_STAGE_NONE,
  87. /* set when C is send */
  88. RYM_STAGE_ESTABLISHING,
  89. /* set when we've got the packet 0 and sent ACK and second C */
  90. RYM_STAGE_ESTABLISHED,
  91. /* set when the sender respond to our second C and recviever got a real
  92. * data packet. */
  93. RYM_STAGE_TRANSMITTING,
  94. /* set when the sender send a EOT */
  95. RYM_STAGE_FINISHING,
  96. /* set when transmission is really finished, i.e., after the NAK, C, final
  97. * NULL packet stuff. */
  98. RYM_STAGE_FINISHED,
  99. };
  100. struct rym_ctx;
  101. /* When receiving files, the buf will be the data received from ymodem protocol
  102. * and the len is the data size.
  103. *
  104. * When sending files, the len is the buf size in RYM. The callback need to
  105. * fill the buf with data to send. Returning RYM_CODE_EOT will terminate the
  106. * transfer and the buf will be discarded. Any other return values will cause
  107. * the transfer continue.
  108. */
  109. typedef enum rym_code(*rym_callback)(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len);
  110. /* Currently RYM only support one transfer session(ctx) for simplicity.
  111. *
  112. * In case we could support multiple sessions in The future, the first argument
  113. * of APIs are (struct rym_ctx*).
  114. */
  115. struct rym_ctx
  116. {
  117. rym_callback on_data;
  118. rym_callback on_begin;
  119. rym_callback on_end;
  120. /* When error happened, user need to check this to get when the error has
  121. * happened. */
  122. enum rym_stage stage;
  123. /* user could get the error content through this */
  124. rt_uint8_t *buf;
  125. struct rt_semaphore sem;
  126. rt_device_t dev;
  127. };
  128. /* recv a file on device dev with ymodem session ctx.
  129. *
  130. * If an error happens, you can get where it is failed from ctx->stage.
  131. *
  132. * @param on_begin The callback will be invoked when the first packet arrived.
  133. * This packet often contain file names and the size of the file, if the sender
  134. * support it. So if you want to save the data to a file, you may need to
  135. * create the file on need. It is the on_begin's responsibility to parse the
  136. * data content. The on_begin can be NULL, in which case the transmission will
  137. * continue without any side-effects.
  138. *
  139. * @param on_data The callback will be invoked on the packets received. The
  140. * callback should save the data to the destination. The return value will be
  141. * sent to the sender and in turn, only RYM_{ACK,CAN} is valid. When on_data is
  142. * NULL, RYM will barely send ACK on every packet and have no side-effects.
  143. *
  144. * @param on_end The callback will be invoked when one transmission is
  145. * finished. The data should be 128 bytes of NULL. You can do some cleaning job
  146. * in this callback such as closing the file. The return value of this callback
  147. * is ignored. As above, this parameter can be NULL if you don't need such
  148. * function.
  149. *
  150. * @param handshake_timeout the timeout when hand shaking. The unit is in
  151. * second.
  152. */
  153. rt_err_t rym_recv_on_device(struct rym_ctx *ctx, rt_device_t dev, rt_uint16_t oflag,
  154. rym_callback on_begin, rym_callback on_data, rym_callback on_end,
  155. int handshake_timeout);
  156. /* send a file on device dev with ymodem session ctx.
  157. *
  158. * If an error happens, you can get where it is failed from ctx->stage.
  159. *
  160. * @param on_begin The callback will be invoked when the first packet is sent.
  161. * This packet often contain file names and the size of the file. It is the
  162. * on_begin's responsibility to parse the basic information of the file. The
  163. * on_begin can not be NULL.
  164. *
  165. * @param on_data The callback will be invoked when the data packets is sent.
  166. * The callback should read file system and prepare the data packets. The
  167. * on_data can not be NULL.
  168. *
  169. * @param on_end The callback will be invoked when one transmission is
  170. * finished. The data should be 128 bytes of NULL. The on_end can not be NULL.
  171. *
  172. * @param handshake_timeout the timeout when hand shaking. The unit is in
  173. * second.
  174. */
  175. rt_err_t rym_send_on_device(struct rym_ctx *ctx, rt_device_t dev, rt_uint16_t oflag,
  176. rym_callback on_begin, rym_callback on_data, rym_callback on_end,
  177. int handshake_timeout);
  178. void ymodem_ota(uint8_t argc, char **argv);
  179. #endif