1 /*
2 * File : rz.c
3 * the implemention of receiving files from the remote computers
4 * through the zmodem protocol.
5 * Change Logs:
6 * Date Author Notes
7 * 2011-03-29 itspy
8 * 2011-12-12 aozima fixed syntax error.
9 */
10
11 #include <rtthread.h>
12 #include <finsh.h>
13 #include <shell.h>
14 #include <rtdef.h>
15 #include <dfs.h>
16 #include <dfs_file.h>
17 #include <dfs_posix.h>
18 #include <stdio.h>
19 #include "zdef.h"
20
21
22 void zr_start(char *path);
23 static rt_err_t zrec_init(rt_uint8_t *rxbuf, struct zfile *zf);
24 static rt_err_t zrec_files(struct zfile *zf);
25 static rt_err_t zwrite_file(rt_uint8_t *buf, rt_uint16_t size, struct zfile *zf);
26 static rt_err_t zrec_file_data(rt_uint8_t *buf, struct zfile *zf);;
27 static rt_err_t zrec_file(rt_uint8_t *rxbuf, struct zfile *zf);
28 static rt_err_t zget_file_info(char *name, struct zfile *zf);
29 static rt_err_t zwrite_file(rt_uint8_t *buf, rt_uint16_t size, struct zfile *zf);
30 static void zrec_ack_bibi(void);
31
32
33 /* start zmodem receive proccess */
zr_start(char * path)34 void zr_start(char *path)
35 {
36 struct zfile *zf;
37 rt_uint8_t n;
38 char ch,*p,*q;
39 rt_err_t res = -RT_ERROR;
40
41 zf = rt_malloc(sizeof(struct zfile));
42 if (zf == RT_NULL)
43 {
44 rt_kprintf("zf: out of memory\r\n");
45 return;
46 }
47 memset(zf, 0, sizeof(struct zfile));
48 zf->fname = path;
49 zf->fd = -1;
50 res = zrec_files(zf);
51 p = zf->fname;
52 for (;;)
53 {
54 q = strstr(p,"/");
55 if (q == RT_NULL) break;
56 p = q+1;
57 }
58 if (res == RT_EOK)
59 {
60 rt_kprintf("\b\b\bfile: %s \r\n",p);
61 rt_kprintf("size: %ld bytes\r\n",zf->bytes_received);
62 rt_kprintf("receive completed.\r\n");
63 close(zf->fd);
64 rt_free(zf->fname);
65 }
66 else
67 {
68 rt_kprintf("\b\b\bfile: %s \r\n",p);
69 rt_kprintf("size: 0 bytes\r\n");
70 rt_kprintf("receive failed.\r\n");
71 if (zf->fd >= 0)
72 {
73 close(zf->fd);
74 unlink(zf->fname); /* remove this file */
75 rt_free(zf->fname);
76 }
77 }
78 rt_free(zf);
79 /* waiting,clear console buffer */
80 rt_thread_delay(RT_TICK_PER_SECOND/2);
81 while(1)
82 {
83 n=rt_device_read(shell->device, 0, &ch, 1);
84 if (n == 0) break;
85 }
86
87 return ;
88 }
89
90 /* receiver init, wait for ack */
zrec_init(rt_uint8_t * rxbuf,struct zfile * zf)91 static rt_err_t zrec_init(rt_uint8_t *rxbuf, struct zfile *zf)
92 {
93 rt_uint8_t err_cnt = 0;
94 rt_err_t res = -RT_ERROR;
95
96 for (;;)
97 {
98 zput_pos(0L);
99 tx_header[ZF0] = ZF0_CMD;
100 tx_header[ZF1] = ZF1_CMD;
101 tx_header[ZF2] = ZF2_CMD;
102 zsend_hex_header(ZRINIT, tx_header);
103 again:
104 res = zget_header(rx_header);
105 switch(res)
106 {
107 case ZFILE:
108 ZF0_CMD = rx_header[ZF0];
109 ZF1_CMD = rx_header[ZF1];
110 ZF2_CMD = rx_header[ZF2];
111 ZF3_CMD = rx_header[ZF3];
112 res = zget_data(rxbuf, RX_BUFFER_SIZE);
113 if (res == GOTCRCW)
114 {
115 if ((res =zget_file_info((char*)rxbuf,zf))!= RT_EOK)
116 {
117 zsend_hex_header(ZSKIP, tx_header);
118 return (res);
119 }
120 return RT_EOK;;
121 }
122 zsend_hex_header(ZNAK, tx_header);
123 goto again;
124 case ZSINIT:
125 if (zget_data((rt_uint8_t*)Attn, ZATTNLEN) == GOTCRCW) /* send zack */
126 {
127 zsend_hex_header(ZACK, tx_header);
128 goto again;
129 }
130 zsend_hex_header(ZNAK, tx_header); /* send znak */
131 goto again;
132 case ZRQINIT:
133 continue;
134 case ZEOF:
135 continue;
136 case ZCOMPL:
137 goto again;
138 case ZFIN: /* end file session */
139 zrec_ack_bibi();
140 return res;
141 default:
142 if (++err_cnt >1000) return -RT_ERROR;
143 continue;
144 }
145 }
146 }
147
148 /* receive files */
zrec_files(struct zfile * zf)149 static rt_err_t zrec_files(struct zfile *zf)
150 {
151 rt_uint8_t *rxbuf;
152 rt_err_t res = -RT_ERROR;
153
154 zinit_parameter();
155 rxbuf = rt_malloc(RX_BUFFER_SIZE*sizeof(rt_uint8_t));
156 if (rxbuf == RT_NULL)
157 {
158 rt_kprintf("rxbuf: out of memory\r\n");
159 return -RT_ERROR;
160 }
161 rt_kprintf("\r\nrz: ready...\r\n"); /* here ready to receive things */
162 if ((res = zrec_init(rxbuf,zf))!= RT_EOK)
163 {
164 rt_kprintf("\b\b\breceive init failed\r\n");
165 rt_free(rxbuf);
166 return -RT_ERROR;
167 }
168 res = zrec_file(rxbuf,zf);
169 if (res == ZFIN)
170 {
171 rt_free(rxbuf);
172 return RT_EOK; /* if finish session */
173 }
174 else if (res == ZCAN)
175 {
176 rt_free(rxbuf);
177 return ZCAN; /* cancel by sender */
178 }
179 else
180 {
181 zsend_can();
182 rt_free(rxbuf);
183 return res;
184 }
185 }
186 /* receive file */
zrec_file(rt_uint8_t * rxbuf,struct zfile * zf)187 static rt_err_t zrec_file(rt_uint8_t *rxbuf, struct zfile *zf)
188 {
189 rt_err_t res = - RT_ERROR;
190 rt_uint16_t err_cnt = 0;
191
192 do
193 {
194 zput_pos(zf->bytes_received);
195 zsend_hex_header(ZRPOS, tx_header);
196 again:
197 res = zget_header(rx_header);
198 switch (res)
199 {
200 case ZDATA:
201 zget_pos(Rxpos);
202 if (Rxpos != zf->bytes_received)
203 {
204 zsend_break(Attn);
205 continue;
206 }
207 err_cnt = 0;
208 res = zrec_file_data(rxbuf,zf);
209 if (res == -RT_ERROR)
210 {
211 zsend_break(Attn);
212 continue;
213 }
214 else if (res == GOTCAN) return res;
215 else goto again;
216 case ZRPOS:
217 zget_pos(Rxpos);
218 continue;
219 case ZEOF:
220 err_cnt = 0;
221 zget_pos(Rxpos);
222 if (Rxpos != zf->bytes_received || Rxpos != zf->bytes_total)
223 {
224 continue;
225 }
226 return (zrec_init(rxbuf,zf)); /* resend ZRINIT packet,ready to receive next file */
227 case ZFIN:
228 zrec_ack_bibi();
229 return ZCOMPL;
230 case ZCAN:
231 #ifdef ZDEBUG
232 rt_kprintf("error code: sender cancelled \r\n");
233 #endif
234 zf->bytes_received = 0L; /* throw the received data */
235 return res;
236 case ZSKIP:
237 return res;
238 case -RT_ERROR:
239 zsend_break(Attn);
240 continue;
241 case ZNAK:
242 case TIMEOUT:
243 default:
244 continue;
245 }
246 } while(++err_cnt < 100);
247
248 return res;
249 }
250
251 /* proccess file infomation */
zget_file_info(char * name,struct zfile * zf)252 static rt_err_t zget_file_info(char *name, struct zfile *zf)
253 {
254 char *p;
255 char *full_path,*ptr;
256 rt_uint16_t i,len;
257 rt_err_t res = -RT_ERROR;
258 struct statfs buf;
259 struct stat finfo;
260
261 if (zf->fname == RT_NULL) /* extract file path */
262 {
263 len = strlen(name)+2;
264 }
265 else
266 len = strlen(zf->fname)+strlen(name)+2;
267 full_path = rt_malloc(len);
268 if (full_path == RT_NULL)
269 {
270 zsend_can();
271 rt_kprintf("\b\b\bfull_path: out of memory\n");
272 rt_free(full_path);
273 return -RT_ERROR;
274 }
275 memset(full_path,0,len);
276
277 for (i=0,ptr=zf->fname;i<len-strlen(name)-2;i++)
278 full_path[i] = *ptr++;
279 full_path[len-strlen(name)-2] = '/';
280 /* check if is a directory */
281 if ((zf->fd=open(full_path, DFS_O_DIRECTORY,0)) < 0)
282 {
283 zsend_can();
284 rt_kprintf("\b\b\bcan not open file:%s\r\n",zf->fname+1);
285 close(zf->fd);
286 zf->fd = -1;
287 rt_free(full_path);
288 return res;
289 }
290 fstat(zf->fd, &finfo);
291 if ((finfo.st_mode&S_IFDIR) != S_IFDIR)
292 {
293 close(zf->fd);
294 zf->fd = -1;
295 return res;
296 }
297 close(zf->fd);
298 /* get fullpath && file attributes */
299 strcat(full_path,name);
300 zf->fname = full_path;
301 p = strlen(name)+name+1;
302 sscanf((const char *)p, "%ld%lo%o", &zf->bytes_total,&zf->ctime,&zf->mode);
303 #if defined(RT_USING_DFS) && defined(DFS_USING_WORKDIR)
304 dfs_statfs(working_directory,&buf);
305 if (zf->bytes_total > (buf.f_blocks * buf.f_bfree))
306 {
307 zsend_can();
308 rt_kprintf("\b\b\bnot enough disk space\r\n");
309 zf->fd = -1;
310 rt_free(full_path);
311 return -RT_ERROR;
312 }
313 #else
314 buf = buf;
315 #endif
316 zf->bytes_received = 0L;
317 if ((zf->fd = open(zf->fname,DFS_O_CREAT|DFS_O_WRONLY,0)) < 0) /* create or replace exist file */
318 {
319 zsend_can();
320 rt_kprintf("\b\b\bcan not create file:%s \r\n",zf->fname);
321 return -RT_ERROR;
322 }
323
324 return RT_EOK;
325 }
326
327 /* receive file data,continously, no ack */
zrec_file_data(rt_uint8_t * buf,struct zfile * zf)328 static rt_err_t zrec_file_data(rt_uint8_t *buf, struct zfile *zf)
329 {
330 rt_err_t res = -RT_ERROR;
331
332 more_data:
333 res = zget_data(buf,RX_BUFFER_SIZE);
334 switch(res)
335 {
336 case GOTCRCW: /* zack received */
337 zwrite_file(buf,Rxcount,zf);
338 zf->bytes_received += Rxcount;
339 zput_pos(zf->bytes_received);
340 zsend_line(XON);
341 zsend_hex_header(ZACK, tx_header);
342 return RT_EOK;
343 case GOTCRCQ:
344 zwrite_file(buf,Rxcount,zf);
345 zf->bytes_received += Rxcount;
346 zput_pos(zf->bytes_received);
347 zsend_hex_header(ZACK, tx_header);
348 goto more_data;
349 case GOTCRCG:
350 zwrite_file(buf,Rxcount,zf);
351 zf->bytes_received += Rxcount;
352 goto more_data;
353 case GOTCRCE:
354 zwrite_file(buf,Rxcount,zf);
355 zf->bytes_received += Rxcount;
356 return RT_EOK;
357 case GOTCAN:
358 #ifdef ZDEBUG
359 rt_kprintf("error code : ZCAN \r\n");
360 #endif
361 return res;
362 case TIMEOUT:
363 return res;
364 case -RT_ERROR:
365 zsend_break(Attn);
366 return res;
367 default:
368 return res;
369 }
370 }
371
372 /* write file */
zwrite_file(rt_uint8_t * buf,rt_uint16_t size,struct zfile * zf)373 static rt_err_t zwrite_file(rt_uint8_t *buf,rt_uint16_t size, struct zfile *zf)
374 {
375 return (write(zf->fd,buf,size));
376 }
377
378 /* ack bibi */
zrec_ack_bibi(void)379 static void zrec_ack_bibi(void)
380 {
381 rt_uint8_t i;
382
383 zput_pos(0L);
384 for (i=0;i<3;i++)
385 {
386 zsend_hex_header(ZFIN, tx_header);
387 switch (zread_line(100))
388 {
389 case 'O':
390 zread_line(1);
391 return;
392 case RCDO:
393 return;
394 case TIMEOUT:
395 default:
396 break;
397 }
398 }
399 }
400
401 /* end of rz.c */
402