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