mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-02 14:23:19 +08:00
fix(ymodem): improve send read loop and unify session cleanup
- Accumulate short reads, mark finishing on EOF - Track begin/end callback states and cleanup on error paths - Add ACK handling with retry/error counting in send flow
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
* Date Author Notes
|
||||
* 2019-12-09 Steven Liu the first version
|
||||
* 2021-04-14 Meco Man Check the file path's legitimacy of 'sy' command
|
||||
* 2026-02-01 wdfk-prog update ymodem transfer behaviors
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
@@ -157,20 +158,35 @@ static enum rym_code _rym_send_data(
|
||||
{
|
||||
struct custom_ctx *cctx = (struct custom_ctx *)ctx;
|
||||
rt_size_t read_size;
|
||||
int retry_read;
|
||||
int rlen;
|
||||
|
||||
read_size = 0;
|
||||
for (retry_read = 0; retry_read < 10; retry_read++)
|
||||
/* Loop until we fill one YMODEM data block, hit EOF, or get a read error. */
|
||||
while (read_size < len)
|
||||
{
|
||||
read_size += read(cctx->fd, buf + read_size, len - read_size);
|
||||
if (read_size == len)
|
||||
rlen = read(cctx->fd, buf + read_size, len - read_size);
|
||||
if (rlen > 0)
|
||||
{
|
||||
read_size += rlen;
|
||||
if (read_size == len)
|
||||
break;
|
||||
}
|
||||
else if (rlen == 0)
|
||||
{
|
||||
/* EOF: mark finishing so sender switches to EOT after padding. */
|
||||
ctx->stage = RYM_STAGE_FINISHING;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read error: abort transfer and report file error to the protocol. */
|
||||
return RYM_ERR_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
if (read_size < len)
|
||||
{
|
||||
rt_memset(buf + read_size, 0x1A, len - read_size);
|
||||
ctx->stage = RYM_STAGE_FINISHING;
|
||||
}
|
||||
|
||||
if (read_size > 128)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@
|
||||
* 2013-04-14 Grissiom initial implementation
|
||||
* 2019-12-09 Steven Liu add YMODEM send protocol
|
||||
* 2022-08-04 Meco Man move error codes to rym_code to silence warnings
|
||||
* 2026-02-01 wdfk-prog update ymodem callbacks and error handling
|
||||
*/
|
||||
|
||||
#ifndef __YMODEM_H__
|
||||
@@ -81,13 +82,22 @@ enum rym_stage
|
||||
};
|
||||
|
||||
struct rym_ctx;
|
||||
/* When receiving files, the buf will be the data received from ymodem protocol
|
||||
/**
|
||||
* @brief YMODEM callback signature.
|
||||
*
|
||||
* @param ctx The context of the current session.
|
||||
*
|
||||
* @note 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.
|
||||
*
|
||||
* @note Keep this typedef unchanged for compatibility with external packages.
|
||||
* To allow error-aware handling without breaking ABI, add state fields
|
||||
* (e.g. ctx->last_err) in rym_ctx for callbacks to inspect.
|
||||
*/
|
||||
typedef enum rym_code(*rym_callback)(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len);
|
||||
|
||||
@@ -98,14 +108,37 @@ typedef enum rym_code(*rym_callback)(struct rym_ctx *ctx, rt_uint8_t *buf, rt_si
|
||||
*/
|
||||
struct rym_ctx
|
||||
{
|
||||
/**
|
||||
* @brief Data callback for each received/sent block.
|
||||
*/
|
||||
rym_callback on_data;
|
||||
/**
|
||||
* @brief Begin callback for the initial header block.
|
||||
*/
|
||||
rym_callback on_begin;
|
||||
/**
|
||||
* @brief End callback for session finalization.
|
||||
* Callers should check ctx->last_err to distinguish success vs failure.
|
||||
*/
|
||||
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;
|
||||
/**
|
||||
* @brief Callback lifecycle state: set when on_begin succeeds.
|
||||
*/
|
||||
rt_uint8_t begin_called;
|
||||
/**
|
||||
* @brief Callback lifecycle state: set when on_end is invoked.
|
||||
*/
|
||||
rt_uint8_t end_called;
|
||||
/**
|
||||
* @brief Last transfer error seen by the core state machine.
|
||||
* on_end can inspect this to distinguish success vs failure.
|
||||
*/
|
||||
rt_err_t last_err;
|
||||
|
||||
struct rt_semaphore sem;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user