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