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