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