| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- #include "luat_base.h"
- #include "stdlib.h"
- #include "luat_ymodem.h"
- #ifdef __LUATOS__
- #include "luat_fs.h"
- #include "luat_timer.h"
- #endif
- #include "luat_mem.h"
- #define LUAT_LOG_TAG "ymodem"
- #include "luat_log.h"
- #define XMODEM_FLAG 'C'
- #define XMODEM_SOH 0x01
- #define XMODEM_STX 0x02
- #define XMODEM_EOT 0x04
- #define XMODEM_ACK 0x06
- #define XMODEM_NAK 0x15
- #define XMODEM_CAN 0x18
- #define XMODEM_DATA_POS (3)
- #define XMODEM_SOH_DATA_LEN (128)
- #define XMODEM_STX_DATA_LEN (1024)
- typedef struct
- {
- #ifdef __LUATOS__
- char *save_path;
- const char *force_save_path;
- FILE* fd;
- #else
- luat_ymodem_callback cb;
- #endif
- uint32_t file_size;
- uint32_t write_size;
- uint16_t data_pos;
- uint16_t data_max;
- uint8_t state;
- uint8_t next_sn;
- uint8_t packet_data[XMODEM_STX_DATA_LEN + 8];
- }ymodem_ctrlstruct;
- static uint16_t CRC16_Cal(void *Data, uint16_t Len, uint16_t CRC16Last)
- {
- uint16_t i;
- uint16_t CRC16 = CRC16Last;
- uint8_t *Src = (uint8_t *)Data;
- while (Len--)
- {
- for (i = 8; i > 0; i--)
- {
- if ((CRC16 & 0x8000) != 0)
- {
- CRC16 <<= 1;
- CRC16 ^= 0x1021;
- }
- else
- {
- CRC16 <<= 1;
- }
- if ((*Src&(1 << (i - 1))) != 0)
- {
- CRC16 ^= 0x1021;
- }
- }
- Src++;
- }
- return CRC16;
- }
- #ifdef __LUATOS__
- void *luat_ymodem_create_handler(const char *save_path, const char *force_save_path)
- #else
- void *luat_ymodem_create_handler(luat_ymodem_callback cb)
- #endif
- {
- ymodem_ctrlstruct *handler = luat_heap_malloc(sizeof(ymodem_ctrlstruct));
- if (handler)
- {
- memset(handler, 0, sizeof(ymodem_ctrlstruct));
- #ifdef __LUATOS__
- if (save_path)
- {
- if (save_path[strlen(save_path)-1] == '/'){
- handler->save_path = luat_heap_malloc(strlen(save_path) + 1);
- strcpy(handler->save_path, save_path);
- handler->save_path[strlen(save_path)] = 0;
- }else{
- handler->save_path = luat_heap_malloc(strlen(save_path) + 2);
- strcpy(handler->save_path, save_path);
- handler->save_path[strlen(save_path)] = '/';
- handler->save_path[strlen(save_path)+1] = 0;
- }
- }
- if (force_save_path)
- {
- handler->force_save_path = luat_heap_malloc(strlen(force_save_path) + 1);
- strcpy((char*)handler->force_save_path, force_save_path);
- }
- #else
- handler->cb = cb;
- #endif
- }
- return handler;
- }
- 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)
- {
- ymodem_ctrlstruct *ctrl = handler;
- uint16_t crc16_org, crc16;
- uint32_t i, NameEnd, LenEnd;
- char path[128];
- *file_ok = 0;
- *all_done = 0;
- *ack = 0;
- *flag = 0;
- switch (ctrl->state)
- {
- case 0:
- if (!data || !len)
- {
- *ack = XMODEM_FLAG;
- return 0;
- }
- else
- {
- if (ctrl->data_pos > 0)
- {
- }
- else
- {
- switch(data[0])
- {
- case XMODEM_STX:
- ctrl->data_max = XMODEM_STX_DATA_LEN;
- break;
- case XMODEM_SOH:
- ctrl->data_max = XMODEM_SOH_DATA_LEN;
- break;
- case XMODEM_CAN:
- luat_ymodem_reset(handler);
- *ack = XMODEM_ACK;
- *all_done = 1;
- return 0;
- default:
- goto DATA_RECIEVE_ERROR;
- break;
- }
- }
- if ((ctrl->data_pos + len) >= (ctrl->data_max + 5))
- {
- //memcpy(&ctrl->packet_data[ctrl->data_pos], data, (XMODEM_SOH_DATA_LEN + 5) - ctrl->data_pos);
- memcpy(&ctrl->packet_data[ctrl->data_pos], data, (ctrl->data_max + 5) - ctrl->data_pos);
- //if (ctrl->packet_data[0] != XMODEM_SOH || ctrl->packet_data[1] != 0x00 || ctrl->packet_data[2] != 0xff)
- if (ctrl->packet_data[1] != 0x00 || ctrl->packet_data[2] != 0xff)
- {
- LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
- goto DATA_RECIEVE_ERROR;
- }
- //crc16_org = ctrl->packet_data[XMODEM_SOH_DATA_LEN + 3];
- //crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_SOH_DATA_LEN + 4];
- //crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_SOH_DATA_LEN, 0);
- crc16_org = ctrl->packet_data[ctrl->data_max + 3];
- crc16_org = (crc16_org << 8) + ctrl->packet_data[ctrl->data_max + 4];
- crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], ctrl->data_max, 0);
- if (crc16 != crc16_org)
- {
- LLOGD("crc16 %x %x ", crc16, crc16_org);
- goto DATA_RECIEVE_ERROR;
- }
- else
- {
- if (!ctrl->packet_data[XMODEM_DATA_POS])
- {
- luat_ymodem_reset(handler);
- *flag = 0;
- *ack = XMODEM_ACK;
- *all_done = 1;
- return 0;
- }
- NameEnd = 0;
- //for(i = XMODEM_DATA_POS; i < (XMODEM_SOH_DATA_LEN + 5); i++)
- for(i = XMODEM_DATA_POS; i < (ctrl->data_max + 5); i++)
- {
- if (!ctrl->packet_data[i])
- {
- NameEnd = i;
- break;
- }
- }
- if (!NameEnd)
- {
- LLOGD("name end");
- goto DATA_RECIEVE_ERROR;
- }
- LenEnd = 0;
- //for(i = (NameEnd + 1); i < (XMODEM_SOH_DATA_LEN + 5); i++)
- for(i = (NameEnd + 1); i < (ctrl->data_max + 5); i++)
- {
- if (!ctrl->packet_data[i])
- {
- LenEnd = i;
- break;
- }
- }
- if (!LenEnd)
- {
- LLOGD("len end");
- goto DATA_RECIEVE_ERROR;
- }
- ctrl->file_size = strtol((const char*)&ctrl->packet_data[NameEnd + 1], NULL, 10);
- ctrl->write_size = 0;
- #ifdef __LUATOS__
- if (ctrl->force_save_path)
- {
- ctrl->fd = luat_fs_fopen(ctrl->force_save_path, "w");
- LLOGD("%s,%u,%x", ctrl->force_save_path, ctrl->file_size, ctrl->fd);
- }
- else
- {
- sprintf_(path, "%s%s", ctrl->save_path, &ctrl->packet_data[XMODEM_DATA_POS]);
- ctrl->fd = luat_fs_fopen(path, "w");
- LLOGD("%s,%u,%x", path, ctrl->file_size, ctrl->fd);
- }
- #else
- ctrl->cb(&ctrl->packet_data[XMODEM_DATA_POS], 0);
- ctrl->cb(NULL, ctrl->file_size);
- #endif
- ctrl->state++;
- ctrl->next_sn = 0;
- ctrl->data_max = (XMODEM_STX_DATA_LEN + 5);
- *flag = XMODEM_FLAG;
- goto DATA_RECIEVE_OK;
- }
- }
- else
- {
- memcpy(&ctrl->packet_data[ctrl->data_pos], data, len);
- ctrl->data_pos += len;
- }
- }
- break;
- case 1:
- if (!data || !len)
- {
- return 0;
- }
- if (!ctrl->data_pos)
- {
- switch(data[0])
- {
- case XMODEM_STX:
- ctrl->data_max = (XMODEM_STX_DATA_LEN + 5);
- break;
- case XMODEM_SOH:
- ctrl->data_max = (XMODEM_SOH_DATA_LEN + 5);
- break;
- case XMODEM_CAN:
- luat_ymodem_reset(handler);
- *ack = XMODEM_ACK;
- *all_done = 1;
- return 0;
- default:
- LLOGD("%x", data[0]);
- goto DATA_RECIEVE_ERROR;
- break;
- }
- memcpy(ctrl->packet_data, data, len);
- ctrl->data_pos += len;
- if (len >= ctrl->data_max) goto YMODEM_DATA_CHECK;
- }
- else
- {
- if ((ctrl->data_pos + len) >= ctrl->data_max)
- {
- memcpy(&ctrl->packet_data[ctrl->data_pos], data, ctrl->data_max - ctrl->data_pos);
- YMODEM_DATA_CHECK:
- switch(ctrl->packet_data[0])
- {
- case XMODEM_SOH:
- if (ctrl->packet_data[1] != ctrl->next_sn || ctrl->packet_data[2] != (255 - ctrl->next_sn))
- {
- LLOGD("head %x %x %x,%d", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2],ctrl->next_sn);
- goto DATA_RECIEVE_ERROR;
- }
- crc16_org = ctrl->packet_data[XMODEM_SOH_DATA_LEN + 3];
- crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_SOH_DATA_LEN + 4];
- crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_SOH_DATA_LEN, 0);
- if (crc16 != crc16_org)
- {
- LLOGD("crc16 %x %x ", crc16, crc16_org);
- goto DATA_RECIEVE_ERROR;
- }
- LenEnd = ((ctrl->file_size - ctrl->write_size) > XMODEM_SOH_DATA_LEN)?XMODEM_SOH_DATA_LEN:(ctrl->file_size - ctrl->write_size);
- #ifdef __LUATOS__
- luat_fs_fwrite(ctrl->packet_data+3, LenEnd, 1, ctrl->fd);
- #else
- ctrl->cb(ctrl->packet_data+3, LenEnd);
- #endif
- ctrl->write_size += LenEnd;
- goto DATA_RECIEVE_OK;
- break;
- case XMODEM_STX:
- if (ctrl->packet_data[1] != ctrl->next_sn || (ctrl->packet_data[2] != (255 - ctrl->next_sn)))
- {
- LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
- goto DATA_RECIEVE_ERROR;
- }
- crc16_org = ctrl->packet_data[XMODEM_STX_DATA_LEN + 3];
- crc16_org = (crc16_org << 8) + ctrl->packet_data[XMODEM_STX_DATA_LEN + 4];
- crc16 = CRC16_Cal(&ctrl->packet_data[XMODEM_DATA_POS], XMODEM_STX_DATA_LEN, 0);
- if (crc16 != crc16_org)
- {
- LLOGD("crc16 %x %x ", crc16, crc16_org);
- goto DATA_RECIEVE_ERROR;
- }
- //写入
- LenEnd = ((ctrl->file_size - ctrl->write_size) > XMODEM_STX_DATA_LEN)?XMODEM_STX_DATA_LEN:(ctrl->file_size - ctrl->write_size);
- #ifdef __LUATOS__
- luat_fs_fwrite(ctrl->packet_data+3, LenEnd, 1, ctrl->fd);
- #else
- ctrl->cb(ctrl->packet_data+3, LenEnd);
- #endif
- ctrl->write_size += LenEnd;
- goto DATA_RECIEVE_OK;
- break;
- default:
- if (ctrl->packet_data[1] != ctrl->next_sn || ctrl->packet_data[2] != ~ctrl->next_sn)
- {
- LLOGD("head %x %x %x", ctrl->packet_data[0], ctrl->packet_data[1], ctrl->packet_data[2]);
- goto DATA_RECIEVE_ERROR;
- }
- goto DATA_RECIEVE_OK;
- }
- }
- else
- {
- memcpy(&ctrl->packet_data[ctrl->data_pos], data, len);
- ctrl->data_pos += len;
- }
- }
- break;
- case 2:
- if (!data || !len)
- {
- return 0;
- }
- switch(data[0])
- {
- case XMODEM_EOT:
- ctrl->state++;
- ctrl->data_pos = 0;
- *flag = 0;
- *ack = XMODEM_NAK;
- #ifdef __LUATOS__
- if (ctrl->fd) luat_fs_fclose(ctrl->fd);
- ctrl->fd = NULL;
- #else
- ctrl->cb(NULL, 0);
- #endif
- break;
- case XMODEM_CAN:
- luat_ymodem_reset(handler);
- *ack = XMODEM_ACK;
- *all_done = 1;
- return 0;
- default:
- goto DATA_RECIEVE_ERROR;
- }
- return 0;
- case 3:
- if (data[0] == XMODEM_EOT)
- {
- ctrl->state = 0;
- *flag = XMODEM_FLAG;
- *ack = XMODEM_ACK;
- return 0;
- }
- else
- {
- goto DATA_RECIEVE_ERROR;
- }
- break;
- default:
- return -1;
- }
- *ack = 0;
- return 0;
- DATA_RECIEVE_ERROR:
- ctrl->data_pos = 0;
- *ack = XMODEM_NAK;
- *flag = 0;
- *all_done = 0;
- return -1;
- DATA_RECIEVE_OK:
- ctrl->data_pos = 0;
- ctrl->next_sn++;
- *ack = XMODEM_ACK;
- if (ctrl->file_size && (ctrl->write_size >= ctrl->file_size))
- {
- #ifdef __LUATOS__
- luat_fs_fclose(ctrl->fd);
- ctrl->fd = NULL;
- #else
- #endif
- ctrl->state = 2;
- *file_ok = 1;
- }
- return 0;
- }
- void luat_ymodem_reset(void *handler)
- {
- ymodem_ctrlstruct *ctrl = handler;
- ctrl->state = 0;
- ctrl->next_sn = 0;
- ctrl->file_size = 0;
- #ifdef __LUATOS__
- if (ctrl->fd) luat_fs_fclose(ctrl->fd);
- ctrl->fd = NULL;
- #else
- ctrl->cb(NULL, 0);
- #endif
- }
- void luat_ymodem_release(void *handler)
- {
- ymodem_ctrlstruct *ctrl = handler;
- luat_ymodem_reset(handler);
- #ifdef __LUATOS__
- luat_heap_free(ctrl->save_path);
- #endif
- luat_heap_free(handler);
- }
|