luat_ymodem.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. #include "luat_base.h"
  2. #include "stdlib.h"
  3. #include "luat_ymodem.h"
  4. #ifdef __LUATOS__
  5. #include "luat_fs.h"
  6. #include "luat_timer.h"
  7. #endif
  8. #include "luat_mem.h"
  9. #define LUAT_LOG_TAG "ymodem"
  10. #include "luat_log.h"
  11. #define XMODEM_FLAG 'C'
  12. #define XMODEM_SOH 0x01
  13. #define XMODEM_STX 0x02
  14. #define XMODEM_EOT 0x04
  15. #define XMODEM_ACK 0x06
  16. #define XMODEM_NAK 0x15
  17. #define XMODEM_CAN 0x18
  18. #define XMODEM_DATA_POS (3)
  19. #define XMODEM_SOH_DATA_LEN (128)
  20. #define XMODEM_STX_DATA_LEN (1024)
  21. typedef struct
  22. {
  23. #ifdef __LUATOS__
  24. char *save_path;
  25. const char *force_save_path;
  26. FILE* fd;
  27. #else
  28. luat_ymodem_callback cb;
  29. #endif
  30. uint32_t file_size;
  31. uint32_t write_size;
  32. uint16_t data_pos;
  33. uint16_t data_max;
  34. uint8_t state;
  35. uint8_t next_sn;
  36. uint8_t packet_data[XMODEM_STX_DATA_LEN + 8];
  37. }ymodem_ctrlstruct;
  38. static uint16_t CRC16_Cal(void *Data, uint16_t Len, uint16_t CRC16Last)
  39. {
  40. uint16_t i;
  41. uint16_t CRC16 = CRC16Last;
  42. uint8_t *Src = (uint8_t *)Data;
  43. while (Len--)
  44. {
  45. for (i = 8; i > 0; i--)
  46. {
  47. if ((CRC16 & 0x8000) != 0)
  48. {
  49. CRC16 <<= 1;
  50. CRC16 ^= 0x1021;
  51. }
  52. else
  53. {
  54. CRC16 <<= 1;
  55. }
  56. if ((*Src&(1 << (i - 1))) != 0)
  57. {
  58. CRC16 ^= 0x1021;
  59. }
  60. }
  61. Src++;
  62. }
  63. return CRC16;
  64. }
  65. #ifdef __LUATOS__
  66. void *luat_ymodem_create_handler(const char *save_path, const char *force_save_path)
  67. #else
  68. void *luat_ymodem_create_handler(luat_ymodem_callback cb)
  69. #endif
  70. {
  71. ymodem_ctrlstruct *handler = luat_heap_malloc(sizeof(ymodem_ctrlstruct));
  72. if (handler)
  73. {
  74. memset(handler, 0, sizeof(ymodem_ctrlstruct));
  75. #ifdef __LUATOS__
  76. if (save_path)
  77. {
  78. if (save_path[strlen(save_path)-1] == '/'){
  79. handler->save_path = luat_heap_malloc(strlen(save_path) + 1);
  80. strcpy(handler->save_path, save_path);
  81. handler->save_path[strlen(save_path)] = 0;
  82. }else{
  83. handler->save_path = luat_heap_malloc(strlen(save_path) + 2);
  84. strcpy(handler->save_path, save_path);
  85. handler->save_path[strlen(save_path)] = '/';
  86. handler->save_path[strlen(save_path)+1] = 0;
  87. }
  88. }
  89. if (force_save_path)
  90. {
  91. handler->force_save_path = luat_heap_malloc(strlen(force_save_path) + 1);
  92. strcpy((char*)handler->force_save_path, force_save_path);
  93. }
  94. #else
  95. handler->cb = cb;
  96. #endif
  97. }
  98. return handler;
  99. }
  100. int luat_ymodem_receive(void *handler, uint8_t *data, uint32_t len, uint8_t *ack, uint8_t *flag, uint8_t *file_ok, uint8_t *all_done)
  101. {
  102. ymodem_ctrlstruct *ctrl = handler;
  103. uint16_t crc16_org, crc16;
  104. uint32_t i, NameEnd, LenEnd;
  105. char path[128];
  106. *file_ok = 0;
  107. *all_done = 0;
  108. *ack = 0;
  109. *flag = 0;
  110. switch (ctrl->state)
  111. {
  112. case 0:
  113. if (!data || !len)
  114. {
  115. *ack = XMODEM_FLAG;
  116. return 0;
  117. }
  118. else
  119. {
  120. if (ctrl->data_pos > 0)
  121. {
  122. }
  123. else
  124. {
  125. switch(data[0])
  126. {
  127. case XMODEM_STX:
  128. ctrl->data_max = XMODEM_STX_DATA_LEN;
  129. break;
  130. case XMODEM_SOH:
  131. ctrl->data_max = XMODEM_SOH_DATA_LEN;
  132. break;
  133. case XMODEM_CAN:
  134. luat_ymodem_reset(handler);
  135. *ack = XMODEM_ACK;
  136. *all_done = 1;
  137. return 0;
  138. default:
  139. goto DATA_RECIEVE_ERROR;
  140. break;
  141. }
  142. }
  143. if ((ctrl->data_pos + len) >= (ctrl->data_max + 5))
  144. {
  145. //memcpy(&ctrl->packet_data[ctrl->data_pos], data, (XMODEM_SOH_DATA_LEN + 5) - ctrl->data_pos);
  146. memcpy(&ctrl->packet_data[ctrl->data_pos], data, (ctrl->data_max + 5) - ctrl->data_pos);
  147. //if (ctrl->packet_data[0] != XMODEM_SOH || ctrl->packet_data[1] != 0x00 || ctrl->packet_data[2] != 0xff)
  148. if (ctrl->packet_data[1] != 0x00 || ctrl->packet_data[2] != 0xff)
  149. {
  150. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  151. goto DATA_RECIEVE_ERROR;
  152. }
  153. //crc16_org = ctrl->packet_data[XMODEM_SOH_DATA_LEN + 3];
  154. //crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_SOH_DATA_LEN + 4];
  155. //crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_SOH_DATA_LEN, 0);
  156. crc16_org = ctrl->packet_data[ctrl->data_max + 3];
  157. crc16_org = (crc16_org << 8) + ctrl->packet_data[ctrl->data_max + 4];
  158. crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], ctrl->data_max, 0);
  159. if (crc16 != crc16_org)
  160. {
  161. LLOGD("crc16 %x %x ", crc16, crc16_org);
  162. goto DATA_RECIEVE_ERROR;
  163. }
  164. else
  165. {
  166. if (!ctrl->packet_data[XMODEM_DATA_POS])
  167. {
  168. luat_ymodem_reset(handler);
  169. *flag = 0;
  170. *ack = XMODEM_ACK;
  171. *all_done = 1;
  172. return 0;
  173. }
  174. NameEnd = 0;
  175. //for(i = XMODEM_DATA_POS; i < (XMODEM_SOH_DATA_LEN + 5); i++)
  176. for(i = XMODEM_DATA_POS; i < (ctrl->data_max + 5); i++)
  177. {
  178. if (!ctrl->packet_data[i])
  179. {
  180. NameEnd = i;
  181. break;
  182. }
  183. }
  184. if (!NameEnd)
  185. {
  186. LLOGD("name end");
  187. goto DATA_RECIEVE_ERROR;
  188. }
  189. LenEnd = 0;
  190. //for(i = (NameEnd + 1); i < (XMODEM_SOH_DATA_LEN + 5); i++)
  191. for(i = (NameEnd + 1); i < (ctrl->data_max + 5); i++)
  192. {
  193. if (!ctrl->packet_data[i])
  194. {
  195. LenEnd = i;
  196. break;
  197. }
  198. }
  199. if (!LenEnd)
  200. {
  201. LLOGD("len end");
  202. goto DATA_RECIEVE_ERROR;
  203. }
  204. ctrl->file_size = strtol((const char*)&ctrl->packet_data[NameEnd + 1], NULL, 10);
  205. ctrl->write_size = 0;
  206. #ifdef __LUATOS__
  207. if (ctrl->force_save_path)
  208. {
  209. ctrl->fd = luat_fs_fopen(ctrl->force_save_path, "w");
  210. LLOGD("%s,%u,%x", ctrl->force_save_path, ctrl->file_size, ctrl->fd);
  211. }
  212. else
  213. {
  214. sprintf_(path, "%s%s", ctrl->save_path, &ctrl->packet_data[XMODEM_DATA_POS]);
  215. ctrl->fd = luat_fs_fopen(path, "w");
  216. LLOGD("%s,%u,%x", path, ctrl->file_size, ctrl->fd);
  217. }
  218. #else
  219. ctrl->cb(&ctrl->packet_data[XMODEM_DATA_POS], 0);
  220. ctrl->cb(NULL, ctrl->file_size);
  221. #endif
  222. ctrl->state++;
  223. ctrl->next_sn = 0;
  224. ctrl->data_max = (XMODEM_STX_DATA_LEN + 5);
  225. *flag = XMODEM_FLAG;
  226. goto DATA_RECIEVE_OK;
  227. }
  228. }
  229. else
  230. {
  231. memcpy(&ctrl->packet_data[ctrl->data_pos], data, len);
  232. ctrl->data_pos += len;
  233. }
  234. }
  235. break;
  236. case 1:
  237. if (!data || !len)
  238. {
  239. return 0;
  240. }
  241. if (!ctrl->data_pos)
  242. {
  243. switch(data[0])
  244. {
  245. case XMODEM_STX:
  246. ctrl->data_max = (XMODEM_STX_DATA_LEN + 5);
  247. break;
  248. case XMODEM_SOH:
  249. ctrl->data_max = (XMODEM_SOH_DATA_LEN + 5);
  250. break;
  251. case XMODEM_CAN:
  252. luat_ymodem_reset(handler);
  253. *ack = XMODEM_ACK;
  254. *all_done = 1;
  255. return 0;
  256. default:
  257. LLOGD("%x", data[0]);
  258. goto DATA_RECIEVE_ERROR;
  259. break;
  260. }
  261. if (len > (XMODEM_STX_DATA_LEN + 8)) //防止溢出死机
  262. {
  263. len = XMODEM_STX_DATA_LEN + 8;
  264. }
  265. memcpy(ctrl->packet_data, data, len);
  266. ctrl->data_pos += len;
  267. if (len >= ctrl->data_max) goto YMODEM_DATA_CHECK;
  268. }
  269. else
  270. {
  271. if ((ctrl->data_pos + len) >= ctrl->data_max)
  272. {
  273. memcpy(&ctrl->packet_data[ctrl->data_pos], data, ctrl->data_max - ctrl->data_pos);
  274. YMODEM_DATA_CHECK:
  275. switch(ctrl->packet_data[0])
  276. {
  277. case XMODEM_SOH:
  278. if (ctrl->packet_data[1] != ctrl->next_sn || ctrl->packet_data[2] != (255 - ctrl->next_sn))
  279. {
  280. LLOGD("head %x %x %x,%d", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2],ctrl->next_sn);
  281. goto DATA_RECIEVE_ERROR;
  282. }
  283. crc16_org = ctrl->packet_data[XMODEM_SOH_DATA_LEN + 3];
  284. crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_SOH_DATA_LEN + 4];
  285. crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_SOH_DATA_LEN, 0);
  286. if (crc16 != crc16_org)
  287. {
  288. LLOGD("crc16 %x %x ", crc16, crc16_org);
  289. goto DATA_RECIEVE_ERROR;
  290. }
  291. LenEnd = ((ctrl->file_size - ctrl->write_size) > XMODEM_SOH_DATA_LEN)?XMODEM_SOH_DATA_LEN:(ctrl->file_size - ctrl->write_size);
  292. #ifdef __LUATOS__
  293. luat_fs_fwrite(ctrl->packet_data+3, LenEnd, 1, ctrl->fd);
  294. #else
  295. ctrl->cb(ctrl->packet_data+3, LenEnd);
  296. #endif
  297. ctrl->write_size += LenEnd;
  298. goto DATA_RECIEVE_OK;
  299. break;
  300. case XMODEM_STX:
  301. if (ctrl->packet_data[1] != ctrl->next_sn || (ctrl->packet_data[2] != (255 - ctrl->next_sn)))
  302. {
  303. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  304. goto DATA_RECIEVE_ERROR;
  305. }
  306. crc16_org = ctrl->packet_data[XMODEM_STX_DATA_LEN + 3];
  307. crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_STX_DATA_LEN + 4];
  308. crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_STX_DATA_LEN, 0);
  309. if (crc16 != crc16_org)
  310. {
  311. LLOGD("crc16 %x %x ", crc16, crc16_org);
  312. goto DATA_RECIEVE_ERROR;
  313. }
  314. //写入
  315. LenEnd = ((ctrl->file_size - ctrl->write_size) > XMODEM_STX_DATA_LEN)?XMODEM_STX_DATA_LEN:(ctrl->file_size - ctrl->write_size);
  316. #ifdef __LUATOS__
  317. luat_fs_fwrite(ctrl->packet_data+3, LenEnd, 1, ctrl->fd);
  318. #else
  319. ctrl->cb(ctrl->packet_data+3, LenEnd);
  320. #endif
  321. ctrl->write_size += LenEnd;
  322. goto DATA_RECIEVE_OK;
  323. break;
  324. default:
  325. if (ctrl->packet_data[1] != ctrl->next_sn || ctrl->packet_data[2] != ~ctrl->next_sn)
  326. {
  327. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  328. goto DATA_RECIEVE_ERROR;
  329. }
  330. goto DATA_RECIEVE_OK;
  331. }
  332. }
  333. else
  334. {
  335. memcpy(&ctrl->packet_data[ctrl->data_pos], data, len);
  336. ctrl->data_pos += len;
  337. }
  338. }
  339. break;
  340. case 2:
  341. if (!data || !len)
  342. {
  343. return 0;
  344. }
  345. switch(data[0])
  346. {
  347. case XMODEM_EOT:
  348. ctrl->state++;
  349. ctrl->data_pos = 0;
  350. *flag = 0;
  351. *ack = XMODEM_NAK;
  352. #ifdef __LUATOS__
  353. if (ctrl->fd) luat_fs_fclose(ctrl->fd);
  354. ctrl->fd = NULL;
  355. #else
  356. ctrl->cb(NULL, 0);
  357. #endif
  358. break;
  359. case XMODEM_CAN:
  360. luat_ymodem_reset(handler);
  361. *ack = XMODEM_ACK;
  362. *all_done = 1;
  363. return 0;
  364. default:
  365. goto DATA_RECIEVE_ERROR;
  366. }
  367. return 0;
  368. case 3:
  369. if (data[0] == XMODEM_EOT)
  370. {
  371. ctrl->state = 0;
  372. *flag = XMODEM_FLAG;
  373. *ack = XMODEM_ACK;
  374. return 0;
  375. }
  376. else
  377. {
  378. goto DATA_RECIEVE_ERROR;
  379. }
  380. break;
  381. default:
  382. return -1;
  383. }
  384. *ack = 0;
  385. return 0;
  386. DATA_RECIEVE_ERROR:
  387. ctrl->data_pos = 0;
  388. *ack = XMODEM_NAK;
  389. *flag = 0;
  390. *all_done = 0;
  391. return -1;
  392. DATA_RECIEVE_OK:
  393. ctrl->data_pos = 0;
  394. ctrl->next_sn++;
  395. *ack = XMODEM_ACK;
  396. if (ctrl->file_size && (ctrl->write_size >= ctrl->file_size))
  397. {
  398. #ifdef __LUATOS__
  399. luat_fs_fclose(ctrl->fd);
  400. ctrl->fd = NULL;
  401. #else
  402. #endif
  403. ctrl->state = 2;
  404. *file_ok = 1;
  405. }
  406. return 0;
  407. }
  408. void luat_ymodem_reset(void *handler)
  409. {
  410. ymodem_ctrlstruct *ctrl = handler;
  411. ctrl->state = 0;
  412. ctrl->next_sn = 0;
  413. ctrl->file_size = 0;
  414. #ifdef __LUATOS__
  415. if (ctrl->fd) luat_fs_fclose(ctrl->fd);
  416. ctrl->fd = NULL;
  417. #else
  418. ctrl->cb(NULL, 0);
  419. #endif
  420. }
  421. void luat_ymodem_release(void *handler)
  422. {
  423. ymodem_ctrlstruct *ctrl = handler;
  424. luat_ymodem_reset(handler);
  425. #ifdef __LUATOS__
  426. luat_heap_free(ctrl->save_path);
  427. #endif
  428. luat_heap_free(handler);
  429. }