1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 */
9
10 #include <rtthread.h>
11 #include <ymodem.h>
12 #include <dfs_file.h>
13 #include <unistd.h>
14 #include <stdio.h>
15 #include <sys/stat.h>
16 #include <sys/statfs.h>
17 #include <stdlib.h>
18
19 #include <board.h>
20
21 struct custom_ctx
22 {
23 struct rym_ctx parent;
24 int fd;
25 int flen;
26 char fpath[256];
27 };
28
_rym_bg(struct rym_ctx * ctx,rt_uint8_t * buf,rt_size_t len)29 static enum rym_code _rym_bg(
30 struct rym_ctx *ctx,
31 rt_uint8_t *buf,
32 rt_size_t len)
33 {
34 struct custom_ctx *cctx = (struct custom_ctx*)ctx;
35 cctx->fpath[0] = '/';
36 /* the buf should be the file name */
37 strcpy(&(cctx->fpath[1]), (const char*)buf);
38 cctx->fd = open(cctx->fpath, O_CREAT | O_WRONLY | O_TRUNC, 0);
39 if (cctx->fd < 0)
40 {
41 rt_err_t err = rt_get_errno();
42 rt_kprintf("error creating file: %d\n", err);
43 rt_kprintf("abort transmission\n");
44 return RYM_CODE_CAN;
45 }
46
47 cctx->flen = atoi((const char*)buf+strlen((const char*)buf)+1);
48 if (cctx->flen == 0)
49 cctx->flen = -1;
50 return RYM_CODE_ACK;
51 }
52
_rym_tof(struct rym_ctx * ctx,rt_uint8_t * buf,rt_size_t len)53 static enum rym_code _rym_tof(
54 struct rym_ctx *ctx,
55 rt_uint8_t *buf,
56 rt_size_t len)
57 {
58 struct custom_ctx *cctx = (struct custom_ctx*)ctx;
59 RT_ASSERT(cctx->fd >= 0);
60 if (cctx->flen == -1)
61 {
62 write(cctx->fd, buf, len);
63 }
64 else
65 {
66 int wlen = len > cctx->flen ? cctx->flen : len;
67 write(cctx->fd, buf, wlen);
68 cctx->flen -= wlen;
69 }
70 return RYM_CODE_ACK;
71 }
72
_rym_end(struct rym_ctx * ctx,rt_uint8_t * buf,rt_size_t len)73 static enum rym_code _rym_end(
74 struct rym_ctx *ctx,
75 rt_uint8_t *buf,
76 rt_size_t len)
77 {
78 struct custom_ctx *cctx = (struct custom_ctx*)ctx;
79
80 RT_ASSERT(cctx->fd >= 0);
81 close(cctx->fd);
82 cctx->fd = -1;
83
84 return RYM_CODE_ACK;
85 }
86
rym_write_to_file(rt_device_t idev)87 rt_err_t rym_write_to_file(rt_device_t idev)
88 {
89 rt_err_t res;
90 struct custom_ctx *ctx = rt_malloc(sizeof(*ctx));
91
92 RT_ASSERT(idev);
93
94 rt_kprintf("entering RYM mode\n");
95
96 res = rym_recv_on_device(&ctx->parent, idev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
97 _rym_bg, _rym_tof, _rym_end, 1000);
98
99 /* there is no Ymodem traffic on the line so print out info. */
100 rt_kprintf("leaving RYM mode with code %d\n", res);
101 rt_kprintf("file %s has been created.\n", ctx->fpath);
102
103 rt_free(ctx);
104
105 return res;
106 }
107
108 #ifdef RT_USING_FINSH
109 #include <finsh.h>
ry(char * dname)110 rt_err_t ry(char *dname)
111 {
112 rt_err_t res;
113
114 rt_device_t dev = rt_device_find(dname);
115 if (!dev)
116 {
117 rt_kprintf("could not find device:%s\n", dname);
118 return -RT_ERROR;
119 }
120
121 res = rym_write_to_file(dev);
122
123 return res;
124 }
125 FINSH_FUNCTION_EXPORT(ry, receive files by ymodem protocol);
126 #endif
127