luat_ymodem.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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. handler->save_path = luat_heap_malloc(strlen(save_path) + 1);
  65. strcpy(handler->save_path, save_path);
  66. }
  67. if (force_save_path)
  68. {
  69. handler->force_save_path = luat_heap_malloc(strlen(force_save_path) + 1);
  70. strcpy((char*)handler->force_save_path, force_save_path);
  71. }
  72. }
  73. return handler;
  74. }
  75. 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)
  76. {
  77. ymodem_ctrlstruct *ctrl = handler;
  78. uint16_t crc16_org, crc16;
  79. uint32_t i, NameEnd, LenEnd;
  80. char path[128];
  81. *file_ok = 0;
  82. *all_done = 0;
  83. *flag = 0;
  84. if (data)
  85. {
  86. if (data[0] == XMODEM_CAN)
  87. {
  88. luat_ymodem_reset(handler);
  89. *ack = XMODEM_ACK;
  90. *all_done = 1;
  91. return 0;
  92. }
  93. }
  94. switch (ctrl->state)
  95. {
  96. case 0:
  97. if (!data)
  98. {
  99. *ack = XMODEM_FLAG;
  100. return 0;
  101. }
  102. else
  103. {
  104. if ((ctrl->data_pos + len) >= (XMODEM_SOH_DATA_LEN + 5))
  105. {
  106. memcpy(&ctrl->packet_data[ctrl->data_pos], data, (XMODEM_SOH_DATA_LEN + 5) - ctrl->data_pos);
  107. if (ctrl->packet_data[0] != XMODEM_SOH || ctrl->packet_data[1] != 0x00 || ctrl->packet_data[2] != 0xff)
  108. {
  109. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  110. goto DATA_RECIEVE_ERROR;
  111. }
  112. crc16_org = ctrl->packet_data[XMODEM_SOH_DATA_LEN + 3];
  113. crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_SOH_DATA_LEN + 4];
  114. crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_SOH_DATA_LEN, 0);
  115. if (crc16 != crc16_org)
  116. {
  117. LLOGD("crc16 %x %x ", crc16, crc16_org);
  118. goto DATA_RECIEVE_ERROR;
  119. }
  120. else
  121. {
  122. if (!ctrl->packet_data[XMODEM_DATA_POS])
  123. {
  124. luat_ymodem_reset(handler);
  125. *ack = XMODEM_ACK;
  126. *all_done = 1;
  127. return 0;
  128. }
  129. NameEnd = NULL;
  130. for(i = XMODEM_DATA_POS; i < (XMODEM_SOH_DATA_LEN + 5); i++)
  131. {
  132. if (!ctrl->packet_data[i])
  133. {
  134. NameEnd = i;
  135. break;
  136. }
  137. }
  138. if (!NameEnd)
  139. {
  140. LLOGD("name end");
  141. goto DATA_RECIEVE_ERROR;
  142. }
  143. LenEnd = NULL;
  144. for(i = (NameEnd + 1); i < (XMODEM_SOH_DATA_LEN + 5); i++)
  145. {
  146. if (!ctrl->packet_data[i])
  147. {
  148. LenEnd = i;
  149. break;
  150. }
  151. }
  152. if (!LenEnd)
  153. {
  154. LLOGD("len end");
  155. goto DATA_RECIEVE_ERROR;
  156. }
  157. ctrl->file_size = strtol((const char*)&ctrl->packet_data[NameEnd + 1], NULL, 10);
  158. ctrl->write_size = 0;
  159. if (ctrl->force_save_path)
  160. {
  161. ctrl->fd = luat_fs_fopen(ctrl->force_save_path, "w");
  162. LLOGD("%s,%u,%x", ctrl->force_save_path, ctrl->file_size, ctrl->fd);
  163. }
  164. else
  165. {
  166. sprintf_(path, "%s%s", ctrl->save_path, &ctrl->packet_data[XMODEM_DATA_POS]);
  167. ctrl->fd = luat_fs_fopen(path, "w");
  168. LLOGD("%s,%u,%x", path, ctrl->file_size, ctrl->fd);
  169. }
  170. ctrl->state++;
  171. ctrl->next_sn = 0;
  172. ctrl->data_max = (XMODEM_STX_DATA_LEN + 5);
  173. *flag = XMODEM_FLAG;
  174. goto DATA_RECIEVE_OK;
  175. }
  176. }
  177. else
  178. {
  179. memcpy(&ctrl->packet_data[ctrl->data_pos], data, len);
  180. ctrl->data_pos += len;
  181. }
  182. }
  183. break;
  184. case 1:
  185. if (!ctrl->data_pos)
  186. {
  187. switch(data[0])
  188. {
  189. case XMODEM_STX:
  190. ctrl->data_max = (XMODEM_STX_DATA_LEN + 5);
  191. break;
  192. case XMODEM_SOH:
  193. ctrl->data_max = (XMODEM_SOH_DATA_LEN + 5);
  194. break;
  195. default:
  196. goto DATA_RECIEVE_ERROR;
  197. break;
  198. }
  199. memcpy(ctrl->packet_data, data, len);
  200. if (len >= ctrl->data_max) goto YMODEM_DATA_CHECK;
  201. }
  202. else
  203. {
  204. if ((ctrl->data_pos + len) >= ctrl->data_max)
  205. {
  206. memcpy(&ctrl->packet_data[ctrl->data_pos], data, ctrl->data_max - ctrl->data_pos);
  207. YMODEM_DATA_CHECK:
  208. switch(ctrl->packet_data[0])
  209. {
  210. case XMODEM_SOH:
  211. if (ctrl->packet_data[1] != ctrl->next_sn || ctrl->packet_data[2] != (255 - ctrl->next_sn))
  212. {
  213. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  214. goto DATA_RECIEVE_ERROR;
  215. }
  216. crc16_org = ctrl->packet_data[XMODEM_SOH_DATA_LEN + 3];
  217. crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_SOH_DATA_LEN + 4];
  218. crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_SOH_DATA_LEN, 0);
  219. if (crc16 != crc16_org)
  220. {
  221. LLOGD("crc16 %x %x ", crc16, crc16_org);
  222. goto DATA_RECIEVE_ERROR;
  223. }
  224. LenEnd = ((ctrl->file_size - ctrl->write_size) > XMODEM_SOH_DATA_LEN)?XMODEM_SOH_DATA_LEN:(ctrl->file_size - ctrl->write_size);
  225. luat_fs_fwrite(ctrl->packet_data, LenEnd, 1, ctrl->fd);
  226. ctrl->write_size += LenEnd;
  227. goto DATA_RECIEVE_OK;
  228. break;
  229. case XMODEM_STX:
  230. if (ctrl->packet_data[1] != ctrl->next_sn || (ctrl->packet_data[2] != (255 - ctrl->next_sn)))
  231. {
  232. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  233. goto DATA_RECIEVE_ERROR;
  234. }
  235. crc16_org = ctrl->packet_data[XMODEM_STX_DATA_LEN + 3];
  236. crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_STX_DATA_LEN + 4];
  237. crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_STX_DATA_LEN, 0);
  238. if (crc16 != crc16_org)
  239. {
  240. LLOGD("crc16 %x %x ", crc16, crc16_org);
  241. goto DATA_RECIEVE_ERROR;
  242. }
  243. //写入
  244. LenEnd = ((ctrl->file_size - ctrl->write_size) > XMODEM_STX_DATA_LEN)?XMODEM_STX_DATA_LEN:(ctrl->file_size - ctrl->write_size);
  245. luat_fs_fwrite(ctrl->packet_data, LenEnd, 1, ctrl->fd);
  246. ctrl->write_size += LenEnd;
  247. goto DATA_RECIEVE_OK;
  248. break;
  249. default:
  250. if (ctrl->packet_data[1] != ctrl->next_sn || ctrl->packet_data[2] != ~ctrl->next_sn)
  251. {
  252. LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
  253. goto DATA_RECIEVE_ERROR;
  254. }
  255. goto DATA_RECIEVE_OK;
  256. }
  257. }
  258. else
  259. {
  260. memcpy(&ctrl->packet_data[ctrl->data_pos], data, len);
  261. ctrl->data_pos += len;
  262. }
  263. }
  264. break;
  265. case 2:
  266. ctrl->state++;
  267. ctrl->data_pos = 0;
  268. *ack = XMODEM_NAK;
  269. return 0;
  270. case 3:
  271. if (data[0] == XMODEM_EOT)
  272. {
  273. ctrl->state = 0;
  274. *flag = XMODEM_FLAG;
  275. *ack = XMODEM_ACK;
  276. return 0;
  277. }
  278. else
  279. {
  280. goto DATA_RECIEVE_ERROR;
  281. }
  282. break;
  283. default:
  284. return -1;
  285. }
  286. *ack = 0;
  287. return 0;
  288. DATA_RECIEVE_ERROR:
  289. ctrl->data_pos = 0;
  290. *ack = XMODEM_NAK;
  291. *flag = 0;
  292. *all_done = 0;
  293. return -1;
  294. DATA_RECIEVE_OK:
  295. ctrl->data_pos = 0;
  296. ctrl->next_sn++;
  297. *ack = XMODEM_ACK;
  298. if (ctrl->file_size && (ctrl->write_size >= ctrl->file_size))
  299. {
  300. luat_fs_fclose(ctrl->fd);
  301. ctrl->fd = NULL;
  302. ctrl->state = 2;
  303. *file_ok = 1;
  304. }
  305. return 0;
  306. }
  307. void luat_ymodem_reset(void *handler)
  308. {
  309. ymodem_ctrlstruct *ctrl = handler;
  310. ctrl->state = 0;
  311. ctrl->next_sn = 0;
  312. ctrl->file_size = 0;
  313. if (ctrl->fd) luat_fs_fclose(ctrl->fd);
  314. ctrl->fd = NULL;
  315. }
  316. void luat_ymodem_release(void *handler)
  317. {
  318. ymodem_ctrlstruct *ctrl = handler;
  319. luat_ymodem_reset(handler);
  320. luat_heap_free(ctrl->save_path);
  321. luat_heap_free(handler);
  322. }