1 /*
2 * File : sz.c
3 * the implemention of sending files to the remote computers
4 * through the zmodem protocol.
5 * Change Logs:
6 * Date Author Notes
7 * 2011-03-29 itspy
8 */
9
10 #include <rtthread.h>
11 #include <finsh.h>
12 #include <shell.h>
13 #include <rtdef.h>
14 #include <dfs.h>
15 #include <dfs_file.h>
16 #include <dfs_posix.h>
17 #include "zdef.h"
18
19
20 static rt_uint8_t TX_BUFFER[TX_BUFFER_SIZE]; /* sender buffer */
21 static rt_uint8_t file_cnt = 0; /* count of number of files opened */
22 static rt_uint8_t Rxflags = 0; /* rx parameter flags */
23 static rt_uint8_t ZF2_OP; /* file transfer option */
24
25 void zs_start(char *path);
26 static void zsend_init(void);
27 static rt_err_t zsend_files(struct zfile *zf);
28 static rt_err_t zsend_file(struct zfile *zf, rt_uint8_t *buf, rt_uint16_t len);
29 static rt_err_t zsend_file_data(struct zfile *zf);
30 static rt_uint16_t zfill_buffer(struct zfile *zf, rt_uint8_t *buf, rt_uint16_t size);
31 static rt_err_t zget_sync(void);
32 static void zsay_bibi(void);
33
34
35
36
37 /* start zmodem send process */
zs_start(char * path)38 void zs_start(char *path)
39 {
40 struct zfile *zf;
41 rt_err_t res = RT_ERROR;
42 char *p,*q;
43 zf = rt_malloc(sizeof(struct zfile));
44 if (zf == RT_NULL)
45 {
46 rt_kprintf("zf: out of memory\r\n");
47 return;
48 }
49 rt_kprintf("\r\nsz: ready...\r\n"); /* here ready to send things */
50 memset(zf, 0, sizeof(struct zfile));
51 zf->fname = path;
52 zf->fd = -1;
53 res = zsend_files(zf);
54 p = zf->fname;
55 for (;;)
56 {
57 q = strstr(p,"/");
58 if (q == RT_NULL) break;
59 p = q+1;
60 }
61 if (res == RT_EOK)
62 {
63 rt_kprintf("\r\nfile: %s \r\nsize: %ld bytes\r\nsend completed.\r\n",
64 p,zf->bytes_received);
65 }
66 else
67 {
68 rt_kprintf("\r\nfile: %s \r\nsize: 0 bytes\r\nsend failed.\r\n",p);
69 }
70 rt_free(zf);
71
72 return;
73 }
74
75 /* init the parameters */
zsend_init(void)76 static void zsend_init(void)
77 {
78 rt_err_t res = -RT_ERROR;
79
80 zinit_parameter();
81 for(;;) /* wait ZPAD */
82 {
83 res = zread_line(800);
84 if (res == ZPAD) break;
85 }
86 for (;;)
87 {
88 res = zget_header(rx_header);
89 if (res == ZRINIT) break;
90 }
91 if ((rx_header[ZF1] & ZRQNVH))
92 {
93 zput_pos(0x80L); /* Show we can var header */
94 zsend_hex_header(ZRQINIT, tx_header);
95 }
96 Rxflags = rx_header[ZF0] & 0377;
97 if (Rxflags & CANFC32) Txfcs32 = 1; /* used 32bits CRC check */
98
99 if (ZF2_OP == ZTRLE && (Rxflags & CANRLE)) /* for RLE packet */
100 Txfcs32 = 2;
101 else
102 ZF2_OP = 0;
103 /* send SINIT cmd */
104 return;
105 }
106
107 /* send files */
zsend_files(struct zfile * zf)108 static rt_err_t zsend_files(struct zfile *zf)
109 {
110 char *p,*q;
111 char *str = "/";
112 struct stat finfo;
113 rt_err_t res = -RT_ERROR;
114
115 if (zf->fname == RT_NULL)
116 {
117 rt_kprintf("\r\nerror: no file to be send.\r\n");
118 return res;
119 }
120 if ((zf->fd=open(zf->fname, DFS_O_RDONLY,0)) <0)
121 {
122 rt_kprintf("\r\ncan not open file:%s\r\n",zf->fname+1);
123 return res;
124 }
125
126 zf->file_end = 0;
127 ++file_cnt;
128 /* extract file name */
129 p = zf->fname;
130 for (;;)
131 {
132 q = strstr(p,str);
133 if (q == RT_NULL) break;
134 p = q+1;
135 }
136 q = (char*)TX_BUFFER;
137 for (;;)
138 {
139 *q++ = *p++;
140 if (*p == 0) break;
141 }
142 *q++ = 0;
143 p=q;
144 while (q < (char*)(TX_BUFFER + 1024))
145 *q++ = 0;
146 /* get file attributes */
147 fstat(zf->fd,&finfo);
148 Left_sizes += finfo.st_size;
149 rt_sprintf(p, "%lu %lo %o 3 %d %ld", (long)finfo.st_size, finfo.st_mtime,
150 finfo.st_mode, file_cnt, Left_sizes);
151 Left_sizes -= finfo.st_size;
152 TX_BUFFER[127] = (finfo.st_size + 127) >>7;
153 TX_BUFFER[126] = (finfo.st_size + 127) >>15;
154
155 zsend_init();
156 /* start sending files */
157 res = zsend_file(zf,TX_BUFFER, (p-(char*)TX_BUFFER)+strlen(p)+1);
158 zsay_bibi();
159 close(zf->fd);
160
161 return res;
162 }
163
164 /* send file name and related info */
zsend_file(struct zfile * zf,rt_uint8_t * buf,rt_uint16_t len)165 static rt_err_t zsend_file(struct zfile *zf, rt_uint8_t *buf, rt_uint16_t len)
166 {
167 rt_uint8_t cnt;
168 rt_err_t res = -RT_ERROR;
169
170 for (cnt=0;cnt<5;cnt++)
171 {
172 tx_header[ZF0] = ZF0_CMD; /* file conversion option */
173 tx_header[ZF1] = ZF1_CMD; /* file management option */
174 tx_header[ZF2] = (ZF3_CMD|ZF2_OP); /* file transfer option */
175 tx_header[ZF3] = ZF3_CMD;
176 zsend_bin_header(ZFILE, tx_header);
177 zsend_bin_data(buf, len, ZCRCW);
178 loop:
179 res = zget_header(rx_header);
180 switch (res)
181 {
182 case ZRINIT:
183 while ((res = zread_line(50)) > 0)
184 {
185 if (res == ZPAD)
186 {
187 goto loop;
188 }
189 }
190 break;
191 case ZCAN:
192 case TIMEOUT:
193 case ZABORT:
194 case ZFIN:
195 break;
196 case -RT_ERROR:
197 case ZNAK:
198 break;
199 case ZCRC: /* no CRC request */
200 goto loop;
201 case ZFERR:
202 case ZSKIP:
203 break;
204 case ZRPOS: /* here we want */
205 zget_pos(Rxpos);
206 Txpos = Rxpos;
207 return(zsend_file_data(zf));
208 default:
209 break;
210 }
211 }
212
213 return res;
214 }
215
216 /* send the file data */
zsend_file_data(struct zfile * zf)217 static rt_err_t zsend_file_data(struct zfile *zf)
218 {
219 rt_int16_t cnt;
220 rt_uint8_t cmd;
221 rt_err_t res = -RT_ERROR;
222 /* send ZDATA packet, start to send data */
223 start_send:
224 zput_pos(Txpos);
225 zsend_bin_header(ZDATA, tx_header);
226 do
227 {
228 cnt = zfill_buffer(zf,TX_BUFFER,RX_BUFFER_SIZE);
229 if (cnt < RX_BUFFER_SIZE )
230 cmd = ZCRCE;
231 else
232 cmd = ZCRCG;
233 zsend_bin_data(TX_BUFFER, cnt, cmd);
234 zf->bytes_received= Txpos += cnt;
235 if (cmd == ZCRCW)
236 goto get_syn1;
237 } while (cnt == RX_BUFFER_SIZE);
238 for (;;) /* get ack and check if send finish */
239 {
240 zput_pos(Txpos);
241 zsend_bin_header(ZEOF, tx_header);
242 get_syn1:
243 res = zget_sync();
244 switch (res)
245 {
246 case ZACK:
247 goto get_syn1;
248 case ZNAK:
249 continue;
250 case ZRPOS: /* resend here */
251 lseek(zf->fd,Txpos,0);
252 goto start_send;
253 case ZRINIT: /* send finish,then begin to send next file */
254 return RT_EOK;
255 case ZSKIP:
256 case -RT_ERROR:
257 return res;
258 default:
259 return res;
260 }
261 }
262 }
263
264 /* fill file data to buffer*/
zfill_buffer(struct zfile * zf,rt_uint8_t * buf,rt_uint16_t size)265 static rt_uint16_t zfill_buffer(struct zfile *zf, rt_uint8_t *buf, rt_uint16_t size)
266 {
267 return (read(zf->fd,buf,size));
268 }
269
270 /* wait sync(ack) from the receiver */
zget_sync(void)271 static rt_err_t zget_sync(void)
272 {
273 rt_err_t res = -RT_ERROR;
274
275 for (;;)
276 {
277 res = zget_header(rx_header);
278 switch (res)
279 {
280 case ZCAN:
281 case ZABORT:
282 case ZFIN:
283 case TIMEOUT:
284 return -RT_ERROR;
285 case ZRPOS: /* get pos, need to resend */
286 zget_pos(Rxpos);
287 Txpos = Rxpos;
288 return res;
289 case ZACK:
290 return res;
291 case ZRINIT: /* get ZRINIT indicate that the prev file send completed */
292 return res;
293 case ZSKIP:
294 return res;
295 case -RT_ERROR:
296 default:
297 zsend_bin_header(ZNAK, tx_header);
298 continue;
299 }
300 }
301 }
302
303 /* say "bibi" to the receiver */
zsay_bibi(void)304 static void zsay_bibi(void)
305 {
306 for (;;)
307 {
308 zput_pos(0L); /* reninit position of next file*/
309 zsend_hex_header(ZFIN, tx_header); /* send finished session cmd */
310 switch (zget_header(rx_header))
311 {
312 case ZFIN:
313 zsend_line('O');
314 zsend_line('O');
315 case ZCAN:
316 case TIMEOUT:
317 return;
318 }
319 }
320 }
321 /* end of sz.c */
322