Skip to content

Commit b9052a5

Browse files
authored
Merge pull request #3264 from Steven-LiuSF/ymodem
[components]: utilities: ymodem: Add ymodem send protocol and ry_sy application.
2 parents bb9a558 + 3c5f464 commit b9052a5

File tree

4 files changed

+636
-55
lines changed

4 files changed

+636
-55
lines changed

components/utilities/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@ menu "Utilities"
22

33
config RT_USING_RYM
44
bool "Enable Ymodem"
5+
depends on RT_USING_DFS = y
56
default n
67

8+
if RT_USING_RYM
9+
config YMODEM_DISABLE_CRC_TABLE
10+
bool "Disable CRC Table"
11+
default n
12+
endif
13+
714
config RT_USING_ULOG
815
bool "Enable ulog"
916
default n
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/*
2+
* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2019-12-09 Steven Liu the first version
9+
*/
10+
11+
#include <rtthread.h>
12+
#include <ymodem.h>
13+
#include <dfs_posix.h>
14+
#include <stdlib.h>
15+
#include <board.h>
16+
#include <string.h>
17+
18+
struct custom_ctx
19+
{
20+
struct rym_ctx parent;
21+
int fd;
22+
int flen;
23+
char fpath[DFS_PATH_MAX];
24+
};
25+
26+
static enum rym_code _rym_recv_begin(
27+
struct rym_ctx *ctx,
28+
rt_uint8_t *buf,
29+
rt_size_t len)
30+
{
31+
struct custom_ctx *cctx = (struct custom_ctx *)ctx;
32+
33+
cctx->fpath[0] = '/';
34+
rt_strncpy(&(cctx->fpath[1]), (const char *)buf, len - 1);
35+
cctx->fd = open(cctx->fpath, O_CREAT | O_WRONLY | O_TRUNC, 0);
36+
if (cctx->fd < 0)
37+
{
38+
rt_err_t err = rt_get_errno();
39+
rt_kprintf("error creating file: %d\n", err);
40+
return RYM_CODE_CAN;
41+
}
42+
cctx->flen = atoi((const char *)buf + rt_strnlen((const char *)buf, len - 1));
43+
if (cctx->flen == 0)
44+
cctx->flen = -1;
45+
46+
return RYM_CODE_ACK;
47+
}
48+
49+
static enum rym_code _rym_recv_data(
50+
struct rym_ctx *ctx,
51+
rt_uint8_t *buf,
52+
rt_size_t len)
53+
{
54+
struct custom_ctx *cctx = (struct custom_ctx *)ctx;
55+
56+
RT_ASSERT(cctx->fd >= 0);
57+
if (cctx->flen == -1)
58+
{
59+
write(cctx->fd, buf, len);
60+
}
61+
else
62+
{
63+
int wlen = len > cctx->flen ? cctx->flen : len;
64+
write(cctx->fd, buf, wlen);
65+
cctx->flen -= wlen;
66+
}
67+
68+
return RYM_CODE_ACK;
69+
}
70+
71+
static enum rym_code _rym_recv_end(
72+
struct rym_ctx *ctx,
73+
rt_uint8_t *buf,
74+
rt_size_t len)
75+
{
76+
struct custom_ctx *cctx = (struct custom_ctx *)ctx;
77+
78+
RT_ASSERT(cctx->fd >= 0);
79+
close(cctx->fd);
80+
cctx->fd = -1;
81+
82+
return RYM_CODE_ACK;
83+
}
84+
85+
static enum rym_code _rym_send_begin(
86+
struct rym_ctx *ctx,
87+
rt_uint8_t *buf,
88+
rt_size_t len)
89+
{
90+
struct custom_ctx *cctx = (struct custom_ctx *)ctx;
91+
struct stat file_buf;
92+
char insert_0 = '\0';
93+
rt_err_t err;
94+
95+
cctx->fd = open(cctx->fpath, O_RDONLY);
96+
if (cctx->fd < 0)
97+
{
98+
err = rt_get_errno();
99+
rt_kprintf("error open file: %d\n", err);
100+
return RYM_ERR_FILE;
101+
}
102+
rt_memset(buf, 0, len);
103+
err = stat(cctx->fpath, &file_buf);
104+
if (err != RT_EOK)
105+
{
106+
rt_kprintf("error open file.\n");
107+
return RYM_ERR_FILE;
108+
}
109+
sprintf((char *)buf, "%s%c%ld", (char *) & (cctx->fpath[1]), insert_0, file_buf.st_size);
110+
111+
return RYM_CODE_SOH;
112+
}
113+
114+
static enum rym_code _rym_send_data(
115+
struct rym_ctx *ctx,
116+
rt_uint8_t *buf,
117+
rt_size_t len)
118+
{
119+
struct custom_ctx *cctx = (struct custom_ctx *)ctx;
120+
rt_size_t read_size;
121+
int retry_read;
122+
123+
read_size = 0;
124+
for (retry_read = 0; retry_read < 10; retry_read++)
125+
{
126+
read_size += read(cctx->fd, buf + read_size, len - read_size);
127+
if (read_size == len)
128+
break;
129+
}
130+
131+
if (read_size < len)
132+
{
133+
rt_memset(buf + read_size, 0x1A, len - read_size);
134+
/* stage = RYM_STAGE_FINISHING */
135+
ctx->stage = 4;
136+
}
137+
138+
return RYM_CODE_SOH;
139+
}
140+
141+
static enum rym_code _rym_send_end(
142+
struct rym_ctx *ctx,
143+
rt_uint8_t *buf,
144+
rt_size_t len)
145+
{
146+
rt_memset(buf, 0, len);
147+
148+
return RYM_CODE_SOH;
149+
}
150+
151+
static rt_err_t rym_download_file(rt_device_t idev)
152+
{
153+
rt_err_t res;
154+
struct custom_ctx *ctx = rt_calloc(1, sizeof(*ctx));
155+
156+
if (!ctx)
157+
{
158+
rt_kprintf("rt_malloc failed\n");
159+
return RT_ENOMEM;
160+
}
161+
ctx->fd = -1;
162+
RT_ASSERT(idev);
163+
res = rym_recv_on_device(&ctx->parent, idev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
164+
_rym_recv_begin, _rym_recv_data, _rym_recv_end, 1000);
165+
rt_free(ctx);
166+
167+
return res;
168+
}
169+
170+
static rt_err_t rym_upload_file(rt_device_t idev, const char *file_path)
171+
{
172+
rt_err_t res = 0;
173+
174+
struct custom_ctx *ctx = rt_calloc(1, sizeof(*ctx));
175+
if (!ctx)
176+
{
177+
rt_kprintf("rt_malloc failed\n");
178+
return RT_ENOMEM;
179+
}
180+
ctx->fd = -1;
181+
rt_strncpy(ctx->fpath, file_path, DFS_PATH_MAX);
182+
RT_ASSERT(idev);
183+
res = rym_send_on_device(&ctx->parent, idev,
184+
RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
185+
_rym_send_begin, _rym_send_data, _rym_send_end, 1000);
186+
rt_free(ctx);
187+
188+
return res;
189+
}
190+
191+
#ifdef RT_USING_FINSH
192+
#include <finsh.h>
193+
194+
static rt_err_t ry(uint8_t argc, char **argv)
195+
{
196+
rt_err_t res;
197+
rt_device_t dev;
198+
199+
if (argc > 1)
200+
dev = rt_device_find(argv[1]);
201+
else
202+
dev = rt_console_get_device();
203+
if (!dev)
204+
{
205+
rt_kprintf("could not find device.\n");
206+
return -RT_ERROR;
207+
}
208+
res = rym_download_file(dev);
209+
210+
return res;
211+
}
212+
MSH_CMD_EXPORT(ry, YMODEM Receive e.g: ry [uart0] default by console.);
213+
214+
static rt_err_t sy(uint8_t argc, char **argv)
215+
{
216+
rt_err_t res;
217+
/* temporarily support 1 file*/
218+
const char *file_path;
219+
rt_device_t dev;
220+
221+
if (argc > 2)
222+
dev = rt_device_find(argv[2]);
223+
else
224+
dev = rt_console_get_device();
225+
if (!dev)
226+
{
227+
rt_kprintf("could not find device.\n");
228+
return -RT_ERROR;
229+
}
230+
file_path = argv[1];
231+
res = rym_upload_file(dev, file_path);
232+
233+
return res;
234+
}
235+
MSH_CMD_EXPORT(sy, YMODEM Send e.g: sy file_path [uart0] default by console.);
236+
237+
#endif /* RT_USING_FINSH */

0 commit comments

Comments
 (0)