luat_ymodem.c 9.6 KB

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