sz.c 7.0 KB

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