/* * PDA_FILE.c * * Created on: 2012-12-19 * Author: yangshuang */ #include "head.h" #define PDA_TYPE_FILE 0X20 #define PDA_FILE_ACK 0X80 #define PDA_FILE_NAK 0X40 #define FILE_ERR_OK 0x00 #define FILE_ERR_NAME 0x01 #define FILE_ERR_TYPE 0x02 #define FILE_ERR_BUSY 0x03 #define FILE_ERR_ADDR 0x04 #define FILE_ERR_SIZE 0x05 #define FILE_ERR_CRC 0x06 #define FILE_ERR_SAVE 0x07 #define FILE_ERR_PHASE 0x08 #define FILE_ERR_MEM 0x09 #define FILE_ERR_STATE 0x0a #define FILE_ERR_OTHER 0xff #define FILE_ATTR_UP 0X01 #define FILE_ATTR_DOWN 0X02 enum fState { FS_IDLE = 0, FS_VERIFY_DOWN, FS_VERIFY_UP, FS_INFO_DOWN, FS_INFO_UP, FS_DATA_DOWN, FS_DATA_UP, FS_RESULT_DOWN, FS_RESULT_UP, }; struct filePDA { enum fState state; s32 file_index; u8 file_type; u16 file_type_key; u16 file_nFrameSum; u16 file_nFrame; u32 file_length; u16 file_crc; u32 file_offset; u8 file_name[13]; u8 * file_buf; }; struct file_item_pda { s8 *file_name; s8 *file_dir; u32 file_attr; int (* file_func)(int); }; static int _PDA_file_check(s8 * name,u32 attr); static int _PDA_file_up_info(int index); static int _PDA_file_save_app(int index); static int _PDA_file_save_set(int index); static int _PDA_file_check_info(int index); static void _PDA_file_state_reset(void); extern void pda_data_echo(BYTE cmd,BYTE sum,BYTE *para); int printf_filePDA(void); static const char * szPdaTool = "ZHOL PDA DTU TOOL V1.00.01"; struct filePDA p_filePDA= {0}; struct file_item_pda p_file_item[] = { {"f308.ko","/app/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, {"iectable.bin","/app/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, {"sm2key0.bin","/app/data/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, {"sm2key1.bin","/app/data/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, {"sm2key2.bin","/app/data/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, {"sm2key3.bin","/app/data/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, {"userid.bin","/app/data/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, {FILE_NAME_SET_DESC,"/tmp/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, {"set_data.bin","/tmp/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_set}, {"set_data_h.bin","/tmp/",FILE_ATTR_UP,NULL}, {"tmp.bin","/app/",FILE_ATTR_UP|FILE_ATTR_DOWN,_PDA_file_save_app}, }; #define PDAFILE_ITEM_NUM (sizeof(p_file_item)/sizeof(struct file_item_pda)) int PDA_TransFile(PDA_COMM *pt,unsigned char *buf) { u8 cmd_len; u32 offset,NumOfData; s32 file_index; static u8 cmd_buf[256]; char name[256]; char from_file_name[64]; char to_file_name[64]; cmd_buf[0] = PDA_TYPE_FILE; cmd_buf[1] = buf[0]; file_index = 0; cmd_len =0; switch(buf[0]) { case 0x01: // 下载请求验证 // 复位状态机 _PDA_file_state_reset(); sprintf(cmd_buf+2,"ZHOL " EQUIP_NAME_STRING "版本号:V%d.%02d.%02d",(VER_NUM>>16)&0XFF,(VER_NUM>>8)&0XFF,VER_NUM&0XFF, VER_TIME "CRC:%04XH",m_CodeCrc); cmd_len = strlen(cmd_buf+2)+1+2; if(memcmp(buf+1,szPdaTool,20) != 0) // 具体版本号暂时不检查(匹配V1.XX.XX) { cmd_buf[1] |= PDA_FILE_NAK; break; } cmd_buf[1] |= PDA_FILE_ACK; p_filePDA.state = FS_VERIFY_DOWN; break; case 0x02: // 上传请求验证 // 复位状态机 _PDA_file_state_reset(); sprintf(cmd_buf+2,"ZHOL " EQUIP_NAME_STRING "版本号:V%d.%02d.%02d",(VER_NUM>>16)&0XFF,(VER_NUM>>8)&0XFF,VER_NUM&0XFF, VER_TIME "CRC:%04XH",m_CodeCrc); cmd_len = strlen(cmd_buf+2)+1+2; if(memcmp(buf+1,szPdaTool,20) != 0) // 具体版本号暂时不检查(匹配V1.XX.XX) { cmd_buf[1] |= PDA_FILE_NAK; break; } cmd_buf[1] |= PDA_FILE_ACK; p_filePDA.state = FS_VERIFY_UP; break; case 0x03: // 下载文件信息 p_filePDA.file_type = (int)buf[1]; p_filePDA.file_length = ((DWORD)buf[2]<<24)+((DWORD)buf[3]<<16)+((DWORD)buf[4]<<8)+buf[5]; p_filePDA.file_nFrameSum = ((DWORD)buf[6]<<8)+buf[7]; p_filePDA.file_offset = 0; memcpy(cmd_buf+2,buf+11,16); // copy file name cmd_buf[18] = 0; file_index = (int)p_filePDA.file_type; if(file_index == 1) { memcpy(&p_filePDA.file_crc,buf+8,2); // copy file_crc swap16(&p_filePDA.file_crc); } else { Swap_16_memcpy((BYTE*)&p_filePDA.file_crc,buf+8); // modify for am335x xxxxxx } // 检查文件阶段 if((p_filePDA.state != FS_VERIFY_DOWN) && (p_filePDA.state != FS_INFO_DOWN)) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[18] = FILE_ERR_PHASE; cmd_len = 19; break; } //检查文件名 if(file_index == 0) { memcpy(p_filePDA.file_name,buf+11,(int)buf[10]); p_filePDA.file_name[(int)buf[10]] = '\0'; rt_printf("%s\r\n",p_filePDA.file_name); p_filePDA.file_index = _PDA_file_check(p_filePDA.file_name,FILE_ATTR_DOWN); if(p_filePDA.file_index < 0 || p_filePDA.file_index != file_index ) { rt_printf("p_filePDA.file_index:%d\r\n",p_filePDA.file_index); _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[18] = FILE_ERR_NAME; cmd_len = 19; break; } } else if(file_index == 10) { p_filePDA.file_index = file_index; memcpy(p_filePDA.file_name,buf+11,(int)buf[10]); p_filePDA.file_name[(int)buf[10]] = '\0'; rt_printf("switch3:%s\r\n",p_filePDA.file_name); } else { p_filePDA.file_index = _PDA_file_check(cmd_buf+2,FILE_ATTR_DOWN); if(p_filePDA.file_index < 0 || p_filePDA.file_index != file_index ) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[18] = FILE_ERR_NAME; cmd_len = 19; break; } } //检查文件长度 if(p_filePDA.file_length > 4*1024*1024) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[18] = FILE_ERR_SIZE; cmd_len = 19; break; } // 分配内存 p_filePDA.file_buf = rt_malloc(p_filePDA.file_length); if((p_filePDA.file_buf) == NULL) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[18] = FILE_ERR_MEM; cmd_len = 19; break; } printf_filePDA(); // 所有检查通过,应答ACK cmd_buf[1] |= PDA_FILE_ACK; cmd_len = 18; // 修改状态 p_filePDA.state = FS_INFO_DOWN; break; case 0x04: // 上传文件信息 // 文件类型 file_index = (int)buf[1]; memcpy(cmd_buf+2,buf+2,16); // copy file name // 检查文件阶段 if((p_filePDA.state != FS_VERIFY_UP) && (p_filePDA.state != FS_INFO_UP)) { // 阶段不对 _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_PHASE; cmd_len = 3; break; } // 检查文件名称 p_filePDA.file_index = _PDA_file_check(cmd_buf+2,FILE_ATTR_UP); if(p_filePDA.file_index < 0 || p_filePDA.file_index != file_index) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_NAME; cmd_len = 3; break; } // 取得文件信息 if(_PDA_file_up_info(p_filePDA.file_index) != 0) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_NAME; cmd_len = 3; break; } printf_filePDA(); // 文件准备就绪,应答ACK memcpy(cmd_buf+2,p_file_item[file_index].file_name,16); // copy file name memcpy(cmd_buf+18,&p_filePDA.file_type,1); memcpy(cmd_buf+19,&p_filePDA.file_length,4); Swap_32(cmd_buf+19); Swap_16_memcpy(cmd_buf+23,(BYTE*)&p_filePDA.file_crc); // modify for am335x xxxxxx cmd_buf[1] |= PDA_FILE_ACK; cmd_len = 25; // 修改状态 p_filePDA.state = FS_INFO_UP; break; case 0x05: // 下载文件正文 NumOfData = (int)buf[1]; offset = ((DWORD)buf[2]<<24)+((DWORD)buf[3]<<16)+((DWORD)buf[4]<<8)+buf[5]; // 检查文件阶段 if((p_filePDA.state != FS_INFO_DOWN) && (p_filePDA.state != FS_DATA_DOWN)) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[6] = FILE_ERR_PHASE; cmd_len = 7; break; } // 检查文件buf if(p_filePDA.file_buf == NULL) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[6] = FILE_ERR_STATE; cmd_len = 7; break; } // 检查文件offset if(offset == p_filePDA.file_offset) { // 一切正常,获取数据 memcpy(p_filePDA.file_buf + offset,buf+6,NumOfData); p_filePDA.file_offset += NumOfData; } else { rt_printf("PDA_TransFile:offset\r\n"); } rt_printf("offset=%d\r\n",offset); // 发送ACK cmd_buf[1] |= PDA_FILE_ACK; memcpy(cmd_buf+3,&p_filePDA.file_offset,4); Swap_32(cmd_buf+3); cmd_buf[2] = (char)NumOfData; cmd_len = 7; // 修改状态 p_filePDA.state = FS_DATA_DOWN; break; case 0x06: // 上传文件正文 offset = ((DWORD)buf[2]<<24)+((DWORD)buf[3]<<16)+((DWORD)buf[4]<<8)+buf[5]; // 检查文件阶段 if((p_filePDA.state != FS_INFO_UP) && (p_filePDA.state != FS_DATA_UP)) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[6] = FILE_ERR_PHASE; cmd_len = 7; break; } // 检查文件file_buf if(p_filePDA.file_buf == NULL) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[6] = FILE_ERR_STATE; cmd_len = 7; break; } // 检查文件offset if(offset >= p_filePDA.file_length) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[6] = FILE_ERR_ADDR; cmd_len = 7; break; } // 发送ACK cmd_buf[1] |= PDA_FILE_ACK; if(p_filePDA.file_length - offset > 228) { cmd_len = 228; } else { cmd_len = p_filePDA.file_length - offset; } memcpy(cmd_buf+6,p_filePDA.file_buf + offset,cmd_len); offset += cmd_len; memcpy(cmd_buf+2,&offset,4); Swap_32(cmd_buf+2); cmd_len += 6; // 修改状态 p_filePDA.state = FS_DATA_UP; break; break; case 0x07: // 下载结果确认 // 检查文件阶段 if((p_filePDA.state != FS_DATA_DOWN) && (p_filePDA.state != FS_RESULT_DOWN)) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_PHASE; cmd_len = 3; break; } // 如果是重复报文,继续肯定应答。 if(p_filePDA.state == FS_RESULT_DOWN) { // 判断是否需要复位 if(buf[1] ==0x01) // 0:不复位;1:复位 { rt_irq_disable(); while(1) ; } cmd_buf[1] |= PDA_FILE_ACK; cmd_len = 2; break; } //检查文件长度 if(p_filePDA.file_offset != p_filePDA.file_length) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_SIZE; cmd_len = 3; break; } // 检查文件CRC if(p_filePDA.file_index < 2 ||( p_filePDA.file_index >6 && p_filePDA.file_index < 10 )) { if( CrcStr(p_filePDA.file_buf,(p_filePDA.file_length-2)) != p_filePDA.file_crc) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_CRC; cmd_len = 3; rt_printf("// CRC错误\r\n"); break; } } // 文件保存 rt_printf("// 文件保存\r\n"); if(p_file_item[p_filePDA.file_index].file_func(p_filePDA.file_index) != 0) { printf_filePDA(); _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_SAVE; cmd_len = 3; break; } if(_PDA_file_check_info(p_filePDA.file_index) == 0) { char log_buf[128]={0}; sprintf(to_file_name,"%s%s",p_file_item[p_filePDA.file_index].file_dir,p_file_item[p_filePDA.file_index].file_name); sprintf(from_file_name,"%s%s","/tmp/",p_file_item[p_filePDA.file_index].file_name); rt_file_mv(from_file_name,to_file_name); sprintf(name,"%s%s%s","文件更新",p_file_item[p_filePDA.file_index].file_dir,p_file_item[p_filePDA.file_index].file_name); log_str_time(LOG_OPERATE,name,0,1); sprintf(log_buf,"%s updated",p_file_item[p_filePDA.file_index].file_name); load_hs_log_rcd(TYPE_SW_UPDATE,true,NULL,log_buf,1); rt_printf("// yes\r\n"); } else { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_CRC; cmd_len = 3; rt_printf("// check错误\r\n"); break; } // 一切正常,肯定应答 cmd_buf[1] |= PDA_FILE_ACK; cmd_len = 2; // 复位全部状态后,设置状态为FS_RESULT_DOWN,继续应答重发确认帧。 _PDA_file_state_reset(); p_filePDA.state = FS_RESULT_DOWN; break; case 0x08: // 上传结果确认 // 检查文件阶段 if((p_filePDA.state != FS_DATA_UP) && (p_filePDA.state != FS_RESULT_UP)) { _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_PHASE; cmd_len = 3; break; } // 如果是重复报文,继续肯定应答。 if(p_filePDA.state == FS_RESULT_UP) { cmd_buf[1] |= PDA_FILE_ACK; cmd_len = 2; break; } // 一切正常,肯定应答 cmd_buf[1] |= PDA_FILE_ACK; cmd_len = 2; // 复位全部状态后,设置状态为FS_RESULT_UP,继续应答重发确认帧。 _PDA_file_state_reset(); p_filePDA.state = FS_RESULT_UP; break; break; default: rt_printf("PDA_TransFile:不支持的命令(%d)\r\n",buf[0]); _PDA_file_state_reset(); cmd_buf[1] |= PDA_FILE_NAK; cmd_buf[2] = FILE_ERR_OTHER; cmd_len = 3; break; } pda_data_echo(0xE7,cmd_len,cmd_buf); return 0; } static int _PDA_file_check(s8 * name,u32 attr) { int i; for(i=0; i< PDAFILE_ITEM_NUM; i++) { if(strcmp(name,p_file_item[i].file_name) == 0) { if(attr & p_file_item[i].file_attr) { return i; } } } return -1; } static void _PDA_file_state_reset(void) { p_filePDA.state = FS_IDLE; if(p_filePDA.file_buf) { rt_free(p_filePDA.file_buf); p_filePDA.file_buf = 0; } } static int _PDA_file_up_info(int index) { char file_name[64]; struct file * pfile; loff_t pos; sprintf(file_name,"%s%s",p_file_item[index].file_dir,p_file_item[index].file_name); // 打开文件 pfile = rt_file_open(file_name,O_RDONLY ,0); if(IS_ERR(pfile)) { return -1; } // 得到文件长度 p_filePDA.file_length = rt_file_getfile_size(pfile); if(p_filePDA.file_length <= 0) { rt_file_close(pfile,0); return -11; } // 分配内存 p_filePDA.file_buf = rt_malloc(p_filePDA.file_length); if((p_filePDA.file_buf) == NULL) { rt_file_close(pfile,0); return -2; } // 读出内容 pos = 0; if(rt_file_read(pfile,p_filePDA.file_buf,p_filePDA.file_length,&pos) != p_filePDA.file_length) { rt_file_close(pfile,0); rt_free(p_filePDA.file_buf); p_filePDA.file_buf = 0; return -3; } // 关闭文件 rt_file_close(pfile,0); // 计算CRC p_filePDA.file_crc = CrcStr(p_filePDA.file_buf,p_filePDA.file_length); // offset p_filePDA.file_offset = 0; // 文件类型 p_filePDA.file_type = (char)index; return 0; } static int _PDA_file_save_set(int index) { int ret; ret = set_save_data_file(index);//p_filePDA.file_buf,p_filePDA.file_length); return ret; } static int _PDA_file_save_app(int index) { char file_name[64]; struct file * pfile; loff_t pos; if(p_filePDA.file_index == 0) { //sprintf(file_name,"%s%s.new",p_file_item[index].file_dir,p_file_item[index].file_name); sprintf(file_name,"%s%s","/tmp/",p_file_item[index].file_name); } else if(p_filePDA.file_index == 10) { if(p_filePDA.file_name == NULL) { sprintf(file_name,"%s%s","/tmp/",p_file_item[index].file_name); } else { sprintf(file_name,"%s%s","/tmp/",p_filePDA.file_name); } } else { sprintf(file_name,"%s%s","/tmp/",p_file_item[index].file_name); } // 创建并打开文件 pfile = rt_file_open(file_name,O_CREAT|O_RDWR|O_TRUNC|O_SYNC,0); if(IS_ERR(pfile)) { return -1; } // 写文件 pos = 0; if(rt_file_write(pfile,p_filePDA.file_buf,p_filePDA.file_length,&pos) != p_filePDA.file_length) { rt_file_close(pfile,0); return -2; } // 关闭文件 rt_file_close(pfile,0); sprintf(file_name,"%s%s",p_file_item[index].file_dir,p_file_item[index].file_name); rt_printf("close%s\r\n",file_name); if(p_filePDA.file_index == 1) { //RmtInf_Init(); } return 0; } int _PDA_file_check_info(int index) { char file_name[64]; u32 len; u16 crc; u8 *buf; struct file * pfile; loff_t pos; sprintf(file_name,"%s%s","/tmp/",p_file_item[index].file_name); // 打开文件 pfile = rt_file_open(file_name,O_RDONLY ,0); if(IS_ERR(pfile)) { rt_printf("-1\r\n"); return -1; } // 得到文件长度 len = rt_file_getfile_size(pfile); if(len <= 0) { rt_file_close(pfile,0); return -11; } // 分配内存 buf = rt_malloc(len); if((buf) == NULL) { rt_file_close(pfile,0); rt_printf("-2\r\n"); return -2; } // 读出内容 pos = 0; if(rt_file_read(pfile,buf,len,&pos) != len) { rt_file_close(pfile,0); rt_free(buf); rt_printf("-3\r\n"); return -3; } // 关闭文件 rt_file_close(pfile,0); // 检查CRC crc = CrcStr(buf,len-2); if(crc != *(u16*)(buf+len-2)) { rt_free(buf); rt_printf("-4\r\n"); return -4; } rt_free(buf); // sunxi 20180719 added return 0; } int printf_filePDA(void) { rt_printf("p_filePDA:\t%p\r\n",&p_filePDA); rt_printf("state:\t\t%d\r\n",p_filePDA.state); rt_printf("file_name:\t%s\r\n",p_file_item[p_filePDA.file_index].file_name); rt_printf("file_index:\t%d\r\n",p_filePDA.file_index); rt_printf("file_type:\t%d\r\n",p_filePDA.file_type); rt_printf("file_crc:\t0x%04x\r\n",p_filePDA.file_crc); rt_printf("file_length:\t%d\r\n",p_filePDA.file_length); rt_printf("file_offset:\t%d\r\n",p_filePDA.file_offset); rt_printf("file_buf:\t%p\r\n",p_filePDA.file_buf); return 0; }