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