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