rz.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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. */
  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 <stdio.h>
  17. #include "zdef.h"
  18. void zr_start(char *path);
  19. static rt_err_t zrec_init(rt_uint8_t *rxbuf,struct zfile *zf);
  20. static rt_err_t zrec_files(struct zfile *zf);
  21. static rt_err_t zwrite_file(rt_uint8_t *buf,rt_uint16_t size,struct zfile *zf);
  22. static rt_err_t zrec_file_data(rt_uint8_t *buf,struct zfile *zf);;
  23. static rt_err_t zrec_file(rt_uint8_t *rxbuf,struct zfile *zf);
  24. static rt_err_t zget_file_info(char *name,struct zfile *zf);
  25. static rt_err_t zwrite_file(rt_uint8_t *buf,rt_uint16_t size,struct zfile *zf);
  26. static void zrec_ack_bibi(void);
  27. /* start zmodem receive proccess */
  28. void zr_start(char *path)
  29. {
  30. struct zfile *zf;
  31. rt_uint8_t n;
  32. char ch;
  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. rt_kprintf("\r\n");
  44. res = zrec_files(zf);
  45. if (res == RT_EOK)
  46. {
  47. rt_kprintf("\b\b\bfile: %s \r\n",zf->fname+1);
  48. rt_kprintf("size: %ld bytes\r\n",zf->bytes_received);
  49. rt_kprintf("receive completed.\r\n");
  50. close(zf->fd);
  51. rt_free(zf->fname);
  52. rt_free(zf);
  53. }
  54. else
  55. {
  56. rt_kprintf("\b\b\bfile: %s \r\n",zf->fname+1);
  57. rt_kprintf("size: 0 bytes\r\n");
  58. rt_kprintf("receive failed.\r\n");
  59. if (zf->fd >= 0)
  60. {
  61. close(zf->fd);
  62. unlink(zf->fname); /* remove this file */
  63. }
  64. rt_free(zf->fname);
  65. rt_free(zf);
  66. }
  67. /* waiting,clear console buffer */
  68. rt_thread_delay(RT_TICK_PER_SECOND/2);
  69. while(1)
  70. {
  71. n=rt_device_read(shell->device, 0, &ch, 1);
  72. if (n == 0) break;
  73. }
  74. return ;
  75. }
  76. /* receiver init, wait for ack */
  77. static rt_err_t zrec_init(rt_uint8_t *rxbuf,struct zfile *zf)
  78. {
  79. rt_uint8_t err_cnt = 0;
  80. rt_err_t res = -RT_ERROR;
  81. for (;;)
  82. {
  83. zput_pos(0L);
  84. tx_header[ZF0] = ZF0_CMD;
  85. tx_header[ZF1] = ZF1_CMD;
  86. tx_header[ZF2] = ZF2_CMD;
  87. zsend_hex_header(ZRINIT, tx_header);
  88. again:
  89. res = zget_header(rx_header);
  90. switch(res)
  91. {
  92. case ZFILE:
  93. ZF0_CMD = rx_header[ZF0];
  94. ZF1_CMD = rx_header[ZF1];
  95. ZF2_CMD = rx_header[ZF2];
  96. ZF3_CMD = rx_header[ZF3];
  97. res = zget_data(rxbuf, RX_BUFFER_SIZE);
  98. if (res == GOTCRCW)
  99. {
  100. if ((res =zget_file_info((char*)rxbuf,zf))!= RT_EOK)
  101. {
  102. zsend_hex_header(ZSKIP, tx_header);
  103. return (res);
  104. }
  105. return RT_EOK;;
  106. }
  107. zsend_hex_header(ZNAK, tx_header);
  108. goto again;
  109. case ZSINIT:
  110. if (zget_data((rt_uint8_t*)Attn, ZATTNLEN) == GOTCRCW) /* send zack */
  111. {
  112. zsend_hex_header(ZACK, tx_header);
  113. goto again;
  114. }
  115. zsend_hex_header(ZNAK, tx_header); /* send znak */
  116. goto again;
  117. case ZRQINIT:
  118. continue;
  119. case ZEOF:
  120. continue;
  121. case ZCOMPL:
  122. goto again;
  123. case ZFIN: /* end file session */
  124. zrec_ack_bibi();
  125. return res;
  126. default:
  127. if (++err_cnt >1000) return -RT_ERROR;
  128. continue;
  129. }
  130. }
  131. }
  132. /* receive files */
  133. static rt_err_t zrec_files(struct zfile *zf)
  134. {
  135. rt_uint8_t *rxbuf;
  136. rt_err_t res = -RT_ERROR;
  137. zinit_parameter();
  138. rxbuf = rt_malloc(RX_BUFFER_SIZE*sizeof(rt_uint8_t));
  139. if (rxbuf == RT_NULL)
  140. {
  141. rt_kprintf("not enough memory\r\n");
  142. return -RT_ERROR;
  143. }
  144. rt_kprintf("rz: ready...\r\n"); /* here ready to receive things */
  145. if ((res = zrec_init(rxbuf,zf))!= RT_EOK)
  146. {
  147. rt_kprintf("\b\b\breceive init failed\r\n");
  148. rt_free(rxbuf);
  149. return -RT_ERROR;
  150. }
  151. res = zrec_file(rxbuf,zf);
  152. if (res == ZFIN)
  153. {
  154. rt_free(rxbuf);
  155. return RT_EOK; /* if finish session */
  156. }
  157. else if (res == ZCAN)
  158. {
  159. rt_free(rxbuf);
  160. return ZCAN; /* cancel by sender */
  161. }
  162. else
  163. {
  164. zsend_can();
  165. rt_free(rxbuf);
  166. return res;
  167. }
  168. }
  169. /* receive file */
  170. static rt_err_t zrec_file(rt_uint8_t *rxbuf,struct zfile *zf)
  171. {
  172. rt_err_t res = - RT_ERROR;
  173. rt_uint16_t err_cnt = 0;
  174. do
  175. {
  176. zput_pos(zf->bytes_received);
  177. zsend_hex_header(ZRPOS, tx_header);
  178. again:
  179. res = zget_header(rx_header);
  180. switch (res)
  181. {
  182. case ZDATA:
  183. zget_pos(Rxpos);
  184. if (Rxpos != zf->bytes_received)
  185. {
  186. zsend_break(Attn);
  187. continue;
  188. }
  189. err_cnt = 0;
  190. res = zrec_file_data(rxbuf,zf);
  191. if (res == -RT_ERROR)
  192. {
  193. zsend_break(Attn);
  194. continue;
  195. }
  196. else if (res == GOTCAN) return res;
  197. else goto again;
  198. case ZRPOS:
  199. zget_pos(Rxpos);
  200. continue;
  201. case ZEOF:
  202. err_cnt = 0;
  203. zget_pos(Rxpos);
  204. if (Rxpos != zf->bytes_received || Rxpos != zf->bytes_total)
  205. {
  206. continue;
  207. }
  208. return (zrec_init(rxbuf,zf)); /* resend ZRINIT packet,ready to receive next file */
  209. case ZFIN:
  210. zrec_ack_bibi();
  211. return ZCOMPL;
  212. case ZCAN:
  213. #ifdef ZDEBUG
  214. rt_kprintf("error code: sender cancelled \r\n");
  215. #endif
  216. unlink(zf->fname);
  217. zf->bytes_received = 0L; /* throw the received data */
  218. return res;
  219. case ZSKIP:
  220. return res;
  221. case -RT_ERROR:
  222. zsend_break(Attn);
  223. continue;
  224. case ZNAK:
  225. case TIMEOUT:
  226. default:
  227. continue;
  228. }
  229. } while(++err_cnt < 100);
  230. return res;
  231. }
  232. /* proccess file infomation */
  233. static rt_err_t zget_file_info(char *name,struct zfile *zf)
  234. {
  235. char *p;
  236. char *ftemp,*ptr;
  237. rt_uint16_t i,len;
  238. rt_err_t res = -RT_ERROR;
  239. struct statfs buf;
  240. struct stat finfo;
  241. if (zf->fname == RT_NULL) /* extract file path */
  242. {
  243. len = strlen(name)+2;
  244. }
  245. else
  246. len = strlen(zf->fname)+strlen(name)+2;
  247. ftemp = rt_malloc(len);
  248. if (ftemp == RT_NULL)
  249. {
  250. zsend_can();
  251. rt_kprintf("\b\b\bftemp: out of memory\n");
  252. return -RT_ERROR;
  253. }
  254. memset(ftemp,0,len);
  255. for (i=0,ptr=zf->fname;i<len-strlen(name)-2;i++)
  256. ftemp[i] = *ptr++;
  257. ftemp[len-strlen(name)-2] = '/';
  258. /* check if is a directory */
  259. if ((zf->fd=open(ftemp, DFS_O_DIRECTORY,0)) < 0)
  260. {
  261. zsend_can();
  262. rt_kprintf("\b\b\bcan not open file:%s\r\n",zf->fname+1);
  263. close(zf->fd);
  264. zf->fd = -1;
  265. return res;
  266. }
  267. fstat(zf->fd, &finfo);
  268. if ((finfo.st_mode&S_IFDIR) != S_IFDIR)
  269. {
  270. close(zf->fd);
  271. zf->fd = -1;
  272. return res;
  273. }
  274. close(zf->fd);
  275. /* get fullpath && file attributes */
  276. strcat(ftemp,name);
  277. zf->fname = ftemp;
  278. p = strlen(name)+name+1;
  279. sscanf((const char *)p, "%ld%lo%o", &zf->bytes_total,&zf->ctime,&zf->mode);
  280. dfs_statfs(working_directory,&buf);
  281. if (zf->bytes_total > (buf.f_blocks * buf.f_bfree))
  282. {
  283. zsend_can();
  284. rt_kprintf("\b\b\bnot enough disk space\r\n");
  285. zf->fd = -1;
  286. return -RT_ERROR;
  287. }
  288. zf->bytes_received = 0L;
  289. if ((zf->fd = open(zf->fname,DFS_O_CREAT|DFS_O_WRONLY,0)) < 0) /* create or replace exist file */
  290. {
  291. zsend_can();
  292. rt_kprintf("\b\b\bcan not create file:%s \r\n",zf->fname);
  293. return -RT_ERROR;
  294. }
  295. return RT_EOK;
  296. }
  297. /* receive file data,continously, no ack */
  298. static rt_err_t zrec_file_data(rt_uint8_t *buf,struct zfile *zf)
  299. {
  300. rt_err_t res = -RT_ERROR;
  301. more_data:
  302. res = zget_data(buf,RX_BUFFER_SIZE);
  303. switch(res)
  304. {
  305. case GOTCRCW: /* zack received */
  306. zwrite_file(buf,Rxcount,zf);
  307. zf->bytes_received += Rxcount;
  308. zput_pos(zf->bytes_received);
  309. zsend_line(XON);
  310. zsend_hex_header(ZACK, tx_header);
  311. return RT_EOK;
  312. case GOTCRCQ:
  313. zwrite_file(buf,Rxcount,zf);
  314. zf->bytes_received += Rxcount;
  315. zput_pos(zf->bytes_received);
  316. zsend_hex_header(ZACK, tx_header);
  317. goto more_data;
  318. case GOTCRCG:
  319. zwrite_file(buf,Rxcount,zf);
  320. zf->bytes_received += Rxcount;
  321. goto more_data;
  322. case GOTCRCE:
  323. zwrite_file(buf,Rxcount,zf);
  324. zf->bytes_received += Rxcount;
  325. return RT_EOK;
  326. case GOTCAN:
  327. #ifdef ZDEBUG
  328. rt_kprintf("error code : ZCAN \r\n");
  329. #endif
  330. return res;
  331. case TIMEOUT:
  332. return res;
  333. case -RT_ERROR:
  334. zsend_break(Attn);
  335. return res;
  336. default:
  337. return res;
  338. }
  339. }
  340. /* write file */
  341. static rt_err_t zwrite_file(rt_uint8_t *buf,rt_uint16_t size,struct zfile *zf)
  342. {
  343. // return 0;
  344. return (write(zf->fd,buf,size));
  345. }
  346. /* ack bibi */
  347. static void zrec_ack_bibi(void)
  348. {
  349. rt_uint8_t i;
  350. zput_pos(0L);
  351. for (i=0;i<3;i++)
  352. {
  353. zsend_hex_header(ZFIN, tx_header);
  354. switch (zread_line(100))
  355. {
  356. case 'O':
  357. zread_line(1);
  358. return;
  359. case RCDO:
  360. return;
  361. case TIMEOUT:
  362. default:
  363. break;
  364. }
  365. }
  366. }
  367. /* end of rz.c */