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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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