xref: /nrf52832-nimble/rt-thread/components/utilities/zmodem/sz.c (revision 104654410c56c573564690304ae786df310c91fc)
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