| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 | /* * COPYRIGHT (C) 2012, Real-Thread Information Technology Ltd * All rights reserved * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date           Author       Notes * 2013-04-14     Grissiom     initial implementation * 2019-12-09     Steven Liu   add YMODEM send protocol */#ifndef __YMODEM_H__#define __YMODEM_H__#include "rtthread.h"#include <string.h>/* The word "RYM" is stand for "Real-YModem". */enum rym_code{    RYM_CODE_NONE = 0x00,    RYM_CODE_SOH  = 0x01,    RYM_CODE_STX  = 0x02,    RYM_CODE_EOT  = 0x04,    RYM_CODE_ACK  = 0x06,    RYM_CODE_NAK  = 0x15,    RYM_CODE_CAN  = 0x18,    RYM_CODE_C    = 0x43,};/* RYM error code * * We use the rt_err_t to return error values. We take use of current error * codes available in RTT and append ourselves. *//* timeout on handshake */#define RYM_ERR_TMO  0x70/* wrong code, wrong SOH, STX etc. */#define RYM_ERR_CODE 0x71/* wrong sequence number */#define RYM_ERR_SEQ  0x72/* wrong CRC checksum */#define RYM_ERR_CRC  0x73/* not enough data received */#define RYM_ERR_DSZ  0x74/* the transmission is aborted by user */#define RYM_ERR_CAN  0x75/* wrong answer, wrong ACK or C */#define RYM_ERR_ACK  0x76/* transmit file invalid */#define RYM_ERR_FILE 0x77/* how many ticks wait for chars between packet. */#ifndef RYM_WAIT_CHR_TICK#define RYM_WAIT_CHR_TICK (RT_TICK_PER_SECOND * 3)#endif/* how many ticks wait for between packet. */#ifndef RYM_WAIT_PKG_TICK#define RYM_WAIT_PKG_TICK (RT_TICK_PER_SECOND * 3)#endif/* how many ticks between two handshake code. */#ifndef RYM_CHD_INTV_TICK#define RYM_CHD_INTV_TICK (RT_TICK_PER_SECOND * 3)#endif/* how many CAN be sent when user active end the session. */#ifndef RYM_END_SESSION_SEND_CAN_NUM#define RYM_END_SESSION_SEND_CAN_NUM  0x07#endifenum rym_stage{    RYM_STAGE_NONE,    /* set when C is send */    RYM_STAGE_ESTABLISHING,    /* set when we've got the packet 0 and sent ACK and second C */    RYM_STAGE_ESTABLISHED,    /* set when the sender respond to our second C and recviever got a real     * data packet. */    RYM_STAGE_TRANSMITTING,    /* set when the sender send a EOT */    RYM_STAGE_FINISHING,    /* set when transmission is really finished, i.e., after the NAK, C, final     * NULL packet stuff. */    RYM_STAGE_FINISHED,};struct rym_ctx;/* When receiving files, the buf will be the data received from ymodem protocol * and the len is the data size. * * When sending files, the len is the buf size in RYM. The callback need to * fill the buf with data to send. Returning RYM_CODE_EOT will terminate the * transfer and the buf will be discarded. Any other return values will cause * the transfer continue. */typedef enum rym_code(*rym_callback)(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len);/* Currently RYM only support one transfer session(ctx) for simplicity. * * In case we could support multiple sessions in The future, the first argument * of APIs are (struct rym_ctx*). */struct rym_ctx{    rym_callback on_data;    rym_callback on_begin;    rym_callback on_end;    /* When error happened, user need to check this to get when the error has     * happened. */    enum rym_stage stage;    /* user could get the error content through this */    rt_uint8_t *buf;    struct rt_semaphore sem;    rt_device_t dev;};/* recv a file on device dev with ymodem session ctx. * * If an error happens, you can get where it is failed from ctx->stage. * * @param on_begin The callback will be invoked when the first packet arrived. * This packet often contain file names and the size of the file, if the sender * support it. So if you want to save the data to a file, you may need to * create the file on need. It is the on_begin's responsibility to parse the * data content. The on_begin can be NULL, in which case the transmission will * continue without any side-effects. * * @param on_data The callback will be invoked on the packets received.  The * callback should save the data to the destination. The return value will be * sent to the sender and in turn, only RYM_{ACK,CAN} is valid. When on_data is * NULL, RYM will barely send ACK on every packet and have no side-effects. * * @param on_end The callback will be invoked when one transmission is * finished. The data should be 128 bytes of NULL. You can do some cleaning job * in this callback such as closing the file. The return value of this callback * is ignored. As above, this parameter can be NULL if you don't need such * function. * * @param handshake_timeout the timeout when hand shaking. The unit is in * second. */rt_err_t rym_recv_on_device(struct rym_ctx *ctx, rt_device_t dev, rt_uint16_t oflag,                            rym_callback on_begin, rym_callback on_data, rym_callback on_end,                            int handshake_timeout);/* send a file on device dev with ymodem session ctx. * * If an error happens, you can get where it is failed from ctx->stage. * * @param on_begin The callback will be invoked when the first packet is sent. * This packet often contain file names and the size of the file. It is the * on_begin's responsibility to parse the basic information of the file. The * on_begin can not be NULL. * * @param on_data The callback will be invoked when the data packets is sent. * The callback should read file system and prepare the data packets. The * on_data can not be NULL. * * @param on_end The callback will be invoked when one transmission is * finished. The data should be 128 bytes of NULL. The on_end can not be NULL. * * @param handshake_timeout the timeout when hand shaking. The unit is in * second. */rt_err_t rym_send_on_device(struct rym_ctx *ctx, rt_device_t dev, rt_uint16_t oflag,                            rym_callback on_begin, rym_callback on_data, rym_callback on_end,                            int handshake_timeout);#endif
 |