luat_ymodem.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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. memcpy(ctrl->packet_data, data, len);
  262. ctrl->data_pos += len;
  263. if (len >= ctrl->data_max) goto YMODEM_DATA_CHECK;
  264. }
  265. else
  266. {
  267. if ((ctrl->data_pos + len) >= ctrl->data_max)
  268. {
  269. memcpy(&ctrl->packet_data[ctrl->data_pos], data, ctrl->data_max - ctrl->data_pos);
  270. YMODEM_DATA_CHECK:
  271. switch(ctrl->packet_data[0])
  272. {
  273. case XMODEM_SOH:
  274. if (ctrl->packet_data[1] != ctrl->next_sn || ctrl->packet_data[2] != (255 - ctrl->next_sn))
  275. {
  276. LLOGD("head %x %x %x,%d", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2],ctrl->next_sn);
  277. goto DATA_RECIEVE_ERROR;
  278. }
  279. crc16_org = ctrl->packet_data[XMODEM_SOH_DATA_LEN + 3];
  280. crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_SOH_DATA_LEN + 4];
  281. crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_SOH_DATA_LEN, 0);
  282. if (crc16 != crc16_org)
  283. {
  284. LLOGD("crc16 %x %x ", crc16, crc16_org);
  285. goto DATA_RECIEVE_ERROR;
  286. }
  287. LenEnd = ((ctrl->file_size - ctrl->write_size) > XMODEM_SOH_DATA_LEN)?XMODEM_SOH_DATA_LEN:(ctrl->file_size - ctrl->write_size);
  288. #ifdef __LUATOS__
  289. luat_fs_fwrite(ctrl->packet_data+3, LenEnd, 1, ctrl->fd);
  290. #else
  291. ctrl->cb(ctrl->packet_data+3, LenEnd);
  292. #endif
  293. ctrl->write_size += LenEnd;
  294. goto DATA_RECIEVE_OK;
  295. break;
  296. case XMODEM_STX:
  297. if (ctrl->packet_data[1] != ctrl->next_sn || (ctrl->packet_data[2] != (255 - ctrl->next_sn)))
  298. {
  299. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  300. goto DATA_RECIEVE_ERROR;
  301. }
  302. crc16_org = ctrl->packet_data[XMODEM_STX_DATA_LEN + 3];
  303. crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_STX_DATA_LEN + 4];
  304. crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_STX_DATA_LEN, 0);
  305. if (crc16 != crc16_org)
  306. {
  307. LLOGD("crc16 %x %x ", crc16, crc16_org);
  308. goto DATA_RECIEVE_ERROR;
  309. }
  310. //写入
  311. LenEnd = ((ctrl->file_size - ctrl->write_size) > XMODEM_STX_DATA_LEN)?XMODEM_STX_DATA_LEN:(ctrl->file_size - ctrl->write_size);
  312. #ifdef __LUATOS__
  313. luat_fs_fwrite(ctrl->packet_data+3, LenEnd, 1, ctrl->fd);
  314. #else
  315. ctrl->cb(ctrl->packet_data+3, LenEnd);
  316. #endif
  317. ctrl->write_size += LenEnd;
  318. goto DATA_RECIEVE_OK;
  319. break;
  320. default:
  321. if (ctrl->packet_data[1] != ctrl->next_sn || ctrl->packet_data[2] != ~ctrl->next_sn)
  322. {
  323. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  324. goto DATA_RECIEVE_ERROR;
  325. }
  326. goto DATA_RECIEVE_OK;
  327. }
  328. }
  329. else
  330. {
  331. memcpy(&ctrl->packet_data[ctrl->data_pos], data, len);
  332. ctrl->data_pos += len;
  333. }
  334. }
  335. break;
  336. case 2:
  337. if (!data || !len)
  338. {
  339. return 0;
  340. }
  341. switch(data[0])
  342. {
  343. case XMODEM_EOT:
  344. ctrl->state++;
  345. ctrl->data_pos = 0;
  346. *flag = 0;
  347. *ack = XMODEM_NAK;
  348. #ifdef __LUATOS__
  349. if (ctrl->fd) luat_fs_fclose(ctrl->fd);
  350. ctrl->fd = NULL;
  351. #else
  352. ctrl->cb(NULL, 0);
  353. #endif
  354. break;
  355. case XMODEM_CAN:
  356. luat_ymodem_reset(handler);
  357. *ack = XMODEM_ACK;
  358. *all_done = 1;
  359. return 0;
  360. default:
  361. goto DATA_RECIEVE_ERROR;
  362. }
  363. return 0;
  364. case 3:
  365. if (data[0] == XMODEM_EOT)
  366. {
  367. ctrl->state = 0;
  368. *flag = XMODEM_FLAG;
  369. *ack = XMODEM_ACK;
  370. return 0;
  371. }
  372. else
  373. {
  374. goto DATA_RECIEVE_ERROR;
  375. }
  376. break;
  377. default:
  378. return -1;
  379. }
  380. *ack = 0;
  381. return 0;
  382. DATA_RECIEVE_ERROR:
  383. ctrl->data_pos = 0;
  384. *ack = XMODEM_NAK;
  385. *flag = 0;
  386. *all_done = 0;
  387. return -1;
  388. DATA_RECIEVE_OK:
  389. ctrl->data_pos = 0;
  390. ctrl->next_sn++;
  391. *ack = XMODEM_ACK;
  392. if (ctrl->file_size && (ctrl->write_size >= ctrl->file_size))
  393. {
  394. #ifdef __LUATOS__
  395. luat_fs_fclose(ctrl->fd);
  396. ctrl->fd = NULL;
  397. #else
  398. #endif
  399. ctrl->state = 2;
  400. *file_ok = 1;
  401. }
  402. return 0;
  403. }
  404. void luat_ymodem_reset(void *handler)
  405. {
  406. ymodem_ctrlstruct *ctrl = handler;
  407. ctrl->state = 0;
  408. ctrl->next_sn = 0;
  409. ctrl->file_size = 0;
  410. #ifdef __LUATOS__
  411. if (ctrl->fd) luat_fs_fclose(ctrl->fd);
  412. ctrl->fd = NULL;
  413. #else
  414. ctrl->cb(NULL, 0);
  415. #endif
  416. }
  417. void luat_ymodem_release(void *handler)
  418. {
  419. ymodem_ctrlstruct *ctrl = handler;
  420. luat_ymodem_reset(handler);
  421. #ifdef __LUATOS__
  422. luat_heap_free(ctrl->save_path);
  423. #endif
  424. luat_heap_free(handler);
  425. }