/******************************************************************************
版权所有：	
文件名称：	IEC101_FILE.c
文件版本：	01.01
创建作者:	   sunxi
创建日期：	2012-10-10
功能说明：	101规约文件传输扩展
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include    "head.h"  
/*------------------------------- 宏定义 --------------------------------------
*/
#define IEC101_TYPE_FILE 	137
#define IEC101_FILE_ACK		0X80
#define IEC101_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



/*------------------------------ 类型结构 -------------------------------------
*/
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 file101
{
	enum fState state;
	s32	file_index;
	u16	file_type;
	u16 file_crc;
	u32	file_length;
	u32	file_offset;
	u8* file_buf;
};


/*------------------------------ 全局变量 -------------------------------------
*/
struct file101 g_file101= {0};


// 通过串口下载的文件，不需要在maintain中再检查文件
u8 g_file_save=0;
/*------------------------------ 函数声明 -------------------------------------
*/
static int _file_up_info(int index);
static int _file_save_app(int index);
//static int _file_check(s8 * name,u32 attr);
int printf_file101(void);

struct file_item g_file_item[] = 
{
	{"equ_cfg.bin", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_CFG, 		_file_save_app},
	{"set_data.bin",	"/tmp/",		ATTR_UP|ATTR_DOWN,	FILETYPE_SET, 		_file_save_app},
	{"iectable.bin", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_TABLE, 	_file_save_app},
	{"equ_res.bin",		"/app/data/",	ATTR_UP|ATTR_DOWN,	FILETYPE_BRD, 		_file_save_app},	
	{"f306.ko",			"/app/",		ATTR_UP|ATTR_DOWN,	FILETYPE_MAINAPP,	_file_save_app},
	{"f308.ko",			"/app/",		ATTR_UP|ATTR_DOWN,	FILETYPE_MAINAPP,	_file_save_app},	
	{KO_FILE_NAME_1,	"/app/",		ATTR_UP|ATTR_DOWN,	FILETYPE_MAINAPP,	_file_save_app},
	{FILE_NAME_RSC,		"/tmp/", 		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER,		_file_save_app},
	{FILE_NAME_PPL_RSC,	"/tmp/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{FILE_NAME_PPL_CFG,	"/app/data/",	ATTR_UP|ATTR_DOWN,	FILETYPE_PPL, 		_file_save_app},
	{FILE_NAME_SET_DESC,"/tmp/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER,		_file_save_app},
	{"u-boot.bin",		"/tmp/",		ATTR_DOWN,			FILETYPE_SYS,		_file_save_app},//引导程序
	{"uImage",			"/tmp/",		ATTR_DOWN,			FILETYPE_SYS,		_file_save_app},//内核程序
	{"app.jffs2",		"/tmp/",		ATTR_DOWN,			FILETYPE_SYS,		_file_save_app},//应用系统
	{"rootfs.jffs2",	"/tmp/",		ATTR_DOWN,			FILETYPE_SYS,		_file_save_app},//内核系统
	{"image_flash.bin",	"/tmp/",		ATTR_DOWN,			FILETYPE_SYS,		_file_save_app},//烧录系统
	{"innergprs.ini",	"/app/data/",	ATTR_UP|ATTR_DOWN,	FILETYPE_INNERGPRS,	_file_save_app},
	{FILE_NAME_GPRSDRIVER,	"/app/",	ATTR_UP|ATTR_DOWN,	FILETYPE_GPRSDRIVER,_file_save_app},
	{"gprs_app",		"/app/",		ATTR_UP|ATTR_DOWN,	FILETYPE_GPRSAPP,	_file_save_app},	
	{"e2prom.bin", 		"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER,		_file_save_app},
	{"brd_res.bin", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"log_err.txt", 	"/app/data/",	ATTR_UP,			FILETYPE_LOG_APP, 	_file_save_app},
	{"log_operate.txt", "/app/data/",	ATTR_UP,			FILETYPE_LOG_APP, 	_file_save_app},
	{"log_soe.txt", 	"/app/data/",	ATTR_UP,			FILETYPE_LOG_APP,	_file_save_app},
	{"log_yx.txt", 		"/app/data/",	ATTR_UP,			FILETYPE_LOG_APP, 	_file_save_app},	
	{"log_gprs.txt", 	"/app/data/",	ATTR_UP,			FILETYPE_LOG_GPRS,	_file_save_app},	
	{"rec_wave.dat", 	"/tmp/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"F308_HMI.bin",	"/tmp/", 		ATTR_UP|ATTR_DOWN,	FILETYPE_F308_HMI, 	_file_save_app},
	{"DTU-DIDO.elf.bin",	"/tmp/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_CHILDPRO, 	_file_save_app},	
	{"changelog.txt", 	"/app/", 		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
#ifdef CPU_AM335X
	{"335x_m", 			"/app/", 		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
#else
	{"m", 				"/app/", 		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
#endif
//	{"acfactor.bin", 	"/app/data/", 	ATTR_UP,			FILETYPE_OTHER, 	_file_save_app},
//	{"dcfactor.bin", 	"/app/data/", 	ATTR_UP,			FILETYPE_OTHER, 	_file_save_app},
	{"hzk.bin", 		"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"vol_status.bin", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"sm2key0.bin", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"sm2key1.bin", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"sm2key2.bin", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"sm2key3.bin", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"userid.bin", 		"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"x509_time0", 		"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"x509_time1", 		"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"x509_time2", 		"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"x509_time3", 		"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"sysm2_0.cer", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"sysm2_1.cer", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"sysm2_2.cer", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"sysm2_3.cer", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"fixset.csv", 		"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app}, // 固定参数文件
	{"pcolcfg.ini", 	"/app/data/", 	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app}, // 级联规约文件
	{"env.dat", 		"/tmp/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"instu.bin", 		"/tmp/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"file_list.bin", 	"/tmp/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"master_slave_equ_sync", 	"/app/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"factor_modify", 	"/app/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"mainImage.lcd", 	"/app/data/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"logcfg.xml", 	"/app/IEC61850/cfg/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"osicfg.xml", 		"/app/IEC61850/cfg/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"lcd_menu.csv", 		"/app/data/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{"vir_mix_table.csv",		"/app/data/",		ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	
	{wave_name[0], 		"/app/data/rec_wave/",	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{wave_name[1], 		"/app/data/rec_wave/",	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{wave_name[2], 		"/app/data/rec_wave/",	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{wave_name[3], 		"/app/data/rec_wave/",	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{wave_name[4], 		"/app/data/rec_wave/",	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{wave_name[5], 		"/app/data/rec_wave/",	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{wave_name[6], 		"/app/data/rec_wave/",	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
	{wave_name[7], 		"/app/data/rec_wave/",	ATTR_UP|ATTR_DOWN,	FILETYPE_OTHER, 	_file_save_app},
};
const int FILE_LIST_NUM = (sizeof(g_file_item)/sizeof(struct file_item));
#define FILE_ITEM_NUM (sizeof(g_file_item)/sizeof(struct file_item))

struct stat g_file_time[FILE_ITEM_NUM];	//文件最新修改时间

/*------------------------------ 函数声明 -------------------------------------
*/
int file_check(s8 * name,u32 attr);
static void _file_state_reset(void);
static void _file_echo(IEC101_DEF *pt,u8 * cmd_buf,u8 cmd_len);


/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/
int IEC101_TransFile(IEC101_DEF *pt,unsigned char *buf,int len)
{
	u8 cmd_len;
	u8 cmd_buf[256];

	cmd_len = com_trans_file(buf, len, cmd_buf);

	// 按101格式组帧
	_file_echo(pt, cmd_buf, cmd_len);
	
	return 0;
}

extern bool g_mt_rs232;
int IEC101_Maintain(IEC101_DEF *pt,unsigned char *buf,int len)
{
	u8 cmd_buf[256];
	u8 cmd_len;

	g_mt_rs232 = 1;

	memset(cmd_buf,0,sizeof(cmd_buf));
	cmd_len = Maintain_Manage(buf, len, cmd_buf);
	
	// 按101格式组帧
	_file_echo(pt,&cmd_buf[0],cmd_len);

	return 0;
}

int com_trans_file(u8 *buf, u32 len, u8 *cmd_buf)
{
	u8 cmd_len=0;
	u32 offset;
	
	cmd_buf[0] = IEC101_TYPE_FILE;
	cmd_buf[1] = buf[1];

	switch(buf[1])
	{
	case 0x01:
		// 下载请求验证
		// 复位状态机
		_file_state_reset();

		sprintf(cmd_buf+2,szTool);			
		sprintf(cmd_buf+21,VER_TIME "CRC:%04XH",m_CodeCrc);
		cmd_len = strlen(cmd_buf+2)+1+2;

#if 0		
		if(memcmp(buf+2,szTool,19) != 0) // 具体版本号暂时不检查(匹配V1.XX.XX)
		{
			cmd_buf[1] |= IEC101_FILE_NAK;
			break;
		}
#endif

		cmd_buf[1] |= IEC101_FILE_ACK;
		
		g_file101.state = FS_VERIFY_DOWN;
		break;
		
	case 0x02:
		// 上传请求验证
		// 复位状态机
		_file_state_reset();
		

		sprintf(cmd_buf+2,szTool);			
		sprintf(cmd_buf+21,VER_TIME "CRC:%04XH",m_CodeCrc);
		cmd_len = strlen(cmd_buf+2)+1+2;

#if 0		
		if(memcmp(buf+2,szTool,19) != 0) // 具体版本号暂时不检查(匹配V1.XX.XX)
		{
			cmd_buf[1] |= IEC101_FILE_NAK;
			break;
		}
#endif

		cmd_buf[1] |= IEC101_FILE_ACK;
		
		g_file101.state = FS_VERIFY_UP;
		break;
	
	case 0x03:
		// 下载文件信息
		memcpy(cmd_buf+2,buf+2,64); // copy file name
		cmd_buf[65] = 0;
		memcpy(&g_file101.file_type,buf+66,2);
		swap16(&g_file101.file_type);
		memcpy(&g_file101.file_length,buf+68,4);
		swap32(&g_file101.file_length);
		memcpy(&g_file101.file_crc,buf+72,2);
		swap16(&g_file101.file_crc);
		g_file101.file_offset = 0;

		// 检查文件阶段
		if((g_file101.state != FS_VERIFY_DOWN) && (g_file101.state != FS_INFO_DOWN))
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[22] = FILE_ERR_PHASE;
			cmd_len = 23;

			break;
		}
		
		//检查文件名
		g_file101.file_index = file_check(cmd_buf+2,ATTR_DOWN);
		if(g_file101.file_index < 0)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[66] = FILE_ERR_NAME;
			cmd_len = 67;	

			break;
		}
		
		//检查文件长度
		if(g_file101.file_length > 4*1024*1024)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[66] = FILE_ERR_SIZE;
			cmd_len = 67;	
			break;
		}
		
		// 分配内存
		g_file101.file_buf = rt_malloc(g_file101.file_length);
		if((g_file101.file_buf) == NULL)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[66] = FILE_ERR_MEM;
			cmd_len = 67;	

			break;
		}
		
		// 所有检查通过，应答ACK
		cmd_buf[1] |= IEC101_FILE_ACK;
		cmd_len = 66;

//		printf_file101();

		// 修改状态
		g_file101.state = FS_INFO_DOWN;
		break;
	
	case 0x04:
		// 上传文件信息
		memcpy(cmd_buf+2,buf+2,64); // copy file name
		cmd_buf[65] = 0;

		// 检查文件阶段
		if((g_file101.state != FS_VERIFY_UP) && (g_file101.state != FS_INFO_UP))
		{
			// 阶段不对
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[66] = FILE_ERR_PHASE;
			cmd_len = 67;

			break;
		}

		// 检查文件名称
		g_file101.file_index = file_check(cmd_buf+2,ATTR_UP);
		if(g_file101.file_index < 0)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[66] = FILE_ERR_NAME;
			cmd_len = 67;

			break;
		}
		
		// 取得文件信息
		if(_file_up_info(g_file101.file_index) != 0)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[66] = FILE_ERR_NAME;
			cmd_len = 67;

			break;
		}

//		printf_file101();

		// 文件准备就绪，应答ACK
		memcpy(cmd_buf+66,&g_file101.file_type,2);
		swap16(cmd_buf+66);
		memcpy(cmd_buf+68,&g_file101.file_length,4);
		swap32(cmd_buf+68);
		memcpy(cmd_buf+72,&g_file101.file_crc,2);
		swap16(cmd_buf+72);
		
		cmd_buf[1] |= IEC101_FILE_ACK;
		cmd_len = 74;

		// 修改状态
		g_file101.state = FS_INFO_UP;
		break;
	
	case 0x05:
		
		// 下载文件正文
		memcpy(cmd_buf+2,buf+2,4);
		memcpy(&offset,buf+2,4);
		swap32(&offset);

		// 检查文件阶段
		if((g_file101.state != FS_INFO_DOWN) && (g_file101.state != FS_DATA_DOWN))
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[6] = FILE_ERR_PHASE;
			cmd_len = 7;

			break;

		}

		//  检查文件buf
		if(g_file101.file_buf == NULL)
		{
			rt_printf("IEC101_TransFilefile_buf==NULL\r\n");
			
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[6] = FILE_ERR_STATE;
			cmd_len = 7;

			break;
		}

		// 检查文件offset
		if(offset == g_file101.file_offset)
		{
			// 一切正常，获取数据
			len -= 2 + 4;
			memcpy(g_file101.file_buf + offset,buf+6,len);
			g_file101.file_offset += len;
		}
		else
		{
			rt_printf("IEC101_TransFile:offset\r\n");
		}

		// 发送ACK
		cmd_buf[1] |= IEC101_FILE_ACK;
		memcpy(cmd_buf+2,&g_file101.file_offset,4);
		swap32(cmd_buf+2);
		cmd_len = 6;

		// 修改状态
		g_file101.state = FS_DATA_DOWN;
		break;
	
	case 0x06:
		// 上传文件正文
		memcpy(cmd_buf+2,buf+2,4);
		memcpy(&offset,buf+2,4);
		swap32(&offset);
		
		// 检查文件阶段
		if((g_file101.state != FS_INFO_UP) && (g_file101.state != FS_DATA_UP))
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[6] = FILE_ERR_PHASE;
			cmd_len = 7;

			break;

		}

		// 检查文件file_buf
		if(g_file101.file_buf == NULL)
		{
			rt_printf("IEC101_TransFilefile_buf==NULL\r\n");
			
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[6] = FILE_ERR_STATE;
			cmd_len = 7;

			break;
		}
		
		// 检查文件offset
		if(offset >= g_file101.file_length)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[6] = FILE_ERR_ADDR;
			cmd_len = 7;

			break;
		}

		// 发送ACK
		cmd_buf[1] |= IEC101_FILE_ACK;
		if(g_file101.file_length - offset > 200)
		{
			cmd_len = 200;
		}
		else
		{
			cmd_len = g_file101.file_length - offset;
		}
		memcpy(cmd_buf+6,g_file101.file_buf + offset,cmd_len);
		cmd_len += 6;

		// 修改状态
		g_file101.state = FS_DATA_UP;
		break;
		break;
	
	case 0x07:
		// 下载结果确认
		// 检查文件阶段
		if((g_file101.state != FS_DATA_DOWN) && (g_file101.state != FS_RESULT_DOWN))
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[2] = FILE_ERR_PHASE;
			cmd_len = 3;

			break;
		}

		// 如果是重复报文，继续肯定应答。
		if(g_file101.state == FS_RESULT_DOWN)
		{
			// 判断是否需要复位
			if(buf[2] == 1) // 0：不复位；1：复位
			{
				watchdog_reset_cpu(1);
			}
			cmd_buf[1] |= IEC101_FILE_ACK;
			cmd_len = 2;

			break;
		}

		//检查文件长度
		if(g_file101.file_offset != g_file101.file_length)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[2] = FILE_ERR_SIZE;
			cmd_len = 3;

			break;
		}

		// 检查文件CRC
		if(CrcStr(g_file101.file_buf,g_file101.file_length) != g_file101.file_crc)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[2] = FILE_ERR_CRC;
			cmd_len = 3;

			break;
		}

		// 文件保存
		if(g_file_item[g_file101.file_index].file_func(g_file101.file_index) != 0)
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[2] = FILE_ERR_SAVE;
			cmd_len = 3;

			break;
		}
		
		// 一切正常，肯定应答
		cmd_buf[1] |= IEC101_FILE_ACK;
		cmd_len = 2;

		// 复位全部状态后，设置状态为FS_RESULT_DOWN，继续应答重发确认帧。
		_file_state_reset();
		g_file101.state = FS_RESULT_DOWN;
		
		break;
	
	case 0x08:
		// 上传结果确认
		// 检查文件阶段
		if((g_file101.state != FS_DATA_UP) && (g_file101.state != FS_RESULT_UP))
		{
			_file_state_reset();
			cmd_buf[1] |= IEC101_FILE_NAK;
			cmd_buf[2] = FILE_ERR_PHASE;
			cmd_len = 3;

			break;
		}

		// 如果是重复报文，继续肯定应答。
		if(g_file101.state == FS_RESULT_UP)
		{
			cmd_buf[1] |= IEC101_FILE_ACK;
			cmd_len = 2;

			break;
		}

		
		// 一切正常，肯定应答
		cmd_buf[1] |= IEC101_FILE_ACK;
		cmd_len = 2;

		// 复位全部状态后，设置状态为FS_RESULT_UP，继续应答重发确认帧。
		_file_state_reset();
		g_file101.state = FS_RESULT_UP;
		break;
		break;
	
	
	default:
		rt_printf("IEC101_TransFile:不支持的命令(%d)\r\n",buf[0]);
		_file_state_reset();
		cmd_buf[1] |= IEC101_FILE_NAK;
		cmd_buf[2] = FILE_ERR_OTHER;
		cmd_len = 3;
		break;
	}
	return cmd_len;
}

int file_check(s8 * name,u32 attr)
{
	int i;

	for(i=0; i< FILE_ITEM_NUM; i++)
	{
		if(strcmp(name,g_file_item[i].file_name) == 0)
		{
			if(attr & g_file_item[i].file_attr)
			{
				return i;
			}
		}
	}
	return -1;
}

int file_check_type(s8 * name,u32 attr)
{
	int i;

	for(i=0; i< FILE_ITEM_NUM; i++)
	{
		if(strcmp(name,g_file_item[i].file_name) == 0)
		{
			return g_file_item[i].file_type;
		}
	}

	return -1;
}


int file_check_info(int index)
{
	char file_name[64];
	u32 len;
	u16 crc;
	u8 *buf;

	struct cfg_file_head *brh;
	unsigned int	signature;	//配置文件签名
	
	struct file * pfile;
	loff_t pos;

	if((g_file_item[index].file_type == FILETYPE_INNERGPRS)
		|| (g_file_item[index].file_type == FILETYPE_SYS))
	{ 
		return 0;
	}

	sprintf(file_name,"%s%s","/tmp/",g_file_item[index].file_name);

	// 打开文件
	pfile = rt_file_open(file_name,O_RDONLY ,0);
	if(IS_ERR(pfile))
	{
		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);
		return -2; 	
	}

	// 读出内容
	pos = 0;
	if(rt_file_read(pfile,buf,len,&pos) != len)
	{
		rt_file_close(pfile,0);
		rt_free(buf);
		return -3;
	}

	// 关闭文件
	rt_file_close(pfile,0);

	// 检查CRC
	crc = CrcStr(buf,len-2);
	if (g_file_item[index].file_type == FILETYPE_CHILDPRO)
	{
		crc = CrcStr(buf+64,len-2-64);
		//swap16(&crc);
	}

	if(g_file_item[index].file_type == FILETYPE_F308_HMI)
	{
		crc = CrcStr(buf + 64,len-2-64);
	
	}

	if ((g_file_item[index].file_type == FILETYPE_MAINAPP)
		|| (g_file_item[index].file_type == FILETYPE_CHILDPRO)
		|| (g_file_item[index].file_type == FILETYPE_F308_HMI))
	{
		//ko,或子板程序
		#ifdef MODE_LITTLE_ENDIAN
		swap16(&crc);
		#endif
	}

	if(crc != *(u16*)(buf+len-2))
	{
		rt_free(buf);
		return -4;
	}

	// 检查文件签名
	brh = (struct cfg_file_head*)buf;
	signature = 0;
	switch(g_file_item[index].file_type)
	{
		case FILETYPE_CFG: 	
			signature = SIG_EQU_CFG_FILE;
		break;

		case FILETYPE_SET: 	
			signature = SIG_SET_DATA_FILE;
		break;

		case FILETYPE_TABLE: 	
			signature = SIG_TABLE_FILE;
		break;

		case FILETYPE_BRD: 	
			signature = SIG_EQU_RES_FILE;
		break;

		case FILETYPE_MAINAPP: 	
		case FILETYPE_FPGA:
		case FILETYPE_CHILDPRO: 	
		case FILETYPE_OTHER:
		case FILETYPE_GPRSDRIVER:
		case FILETYPE_GPRSAPP:
		case FILETYPE_F308_HMI:	
		case FILETYPE_PPL: 
			rt_free(buf);		
			return 0;
		break;
	}
		
	if(brh->signature != signature)
	{
		rt_free(buf);
		return -5;
	}
	
	return 0;
}

u32 file_change_time(int index)
{
	struct stat s;
	char file_name[64];

	sprintf(file_name,"%s%s",g_file_item[index].file_dir,g_file_item[index].file_name);
	if(sys_newstat((char *)file_name,&s))
	{
		return -1;

	}
	
	return s.st_mtime;
}

/*------------------------------ 内部函数 -------------------------------------
内部函数以下划线‘_’开头，不需要检查参数的合法性.
*/

#if 0
static int _file_check(s8 * name,u32 attr)
{
	int i;
	char file_name[64];

	for(i=0; i< FILE_ITEM_NUM; i++)
	{
		sprintf(file_name,"%s%s",g_file_item[i].file_dir,g_file_item[i].file_name);
		if(strcmp(name,file_name) == 0)
		{
			if(attr & g_file_item[i].file_attr)
			{
				return i;
			}
		}
	}

	return -1;
}
#endif

static int _file_up_info(int index)
{
	char file_name[64];
	struct file * pfile;
	loff_t pos;

	sprintf(file_name,"%s%s",g_file_item[index].file_dir,g_file_item[index].file_name);

	// 打开文件
	pfile = rt_file_open(file_name,O_RDONLY ,0);
	if(IS_ERR(pfile))
	{
		return -1;
	}

	// 得到文件长度
	g_file101.file_length = rt_file_getfile_size(pfile);
	if(g_file101.file_length == 0)
	{
		rt_file_close(pfile,0);
		return -11;
	}

	// 分配内存
	g_file101.file_buf = rt_malloc(g_file101.file_length);
	if((g_file101.file_buf) == NULL)
	{
		rt_file_close(pfile,0);
		return -2; 	
	}

	// 读出内容
	pos = 0;
	if(rt_file_read(pfile,g_file101.file_buf,g_file101.file_length,&pos) != g_file101.file_length)
	{
		rt_file_close(pfile,0);
		rt_free(g_file101.file_buf);
		g_file101.file_buf = 0;
		return -3;
	}

	// 关闭文件
	rt_file_close(pfile,0);

	// 计算CRC
	g_file101.file_crc = CrcStr(g_file101.file_buf,g_file101.file_length-2);

	// offset
	g_file101.file_offset = 0;

	// 文件类型
	g_file101.file_type = 0;
	
	return 0;
}


static int _file_save_app(int index)
{
	char file_name[64];
	struct file * pfile;
	loff_t pos;
	char from_file_name[64];
	char to_file_name[64];

	g_file_save = 0;
	
	//sprintf(file_name,"%s%s.new",g_file_item[index].file_dir,g_file_item[index].file_name);
	sprintf(file_name,"%s%s","/tmp/",g_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,g_file101.file_buf,g_file101.file_length,&pos) != g_file101.file_length)
	{
		rt_file_close(pfile,0);
		return -2;
		
	}

	// 关闭文件
	rt_file_close(pfile,0);

	if (file_check_info(index) == 0)
	{
		sprintf(to_file_name,"%s%s",g_file_item[index].file_dir,g_file_item[index].file_name);
		sprintf(from_file_name,"%s%s","/tmp/",g_file_item[index].file_name);
		rt_file_mv(from_file_name,to_file_name);

		sprintf(file_name,"%s%s%s","文件更新",g_file_item[index].file_dir,g_file_item[index].file_name);
		log_str_time(LOG_OPERATE,file_name,0,0);
		

		g_file_save = 1;
	}
	else
	{
		sprintf(from_file_name,"%s%s","/tmp/",g_file_item[index].file_name);
		rt_file_del(from_file_name);
	}
	
	return 0;
}

static void _file_state_reset(void)
{
	g_file101.state = FS_IDLE;
	if(g_file101.file_buf)
	{
		rt_free(g_file101.file_buf);
		g_file101.file_buf = 0;
	}
}



static void _file_echo(IEC101_DEF *pt,u8 * cmd_buf,u8 cmd_len)			//确认帧
{	
	BYTE cnt,checksum ,len;
	BYTE *p;
	BYTE AddByte=0;
	
	p=pt->tx_buf_s;

	if(tRunPara.b101Addr2Byte)
	{
		AddByte=1;	
		p[7]=(BYTE)(tRunPara.byAddr>>8);	//链路地址高地址
	}

	// 101规约len域的值 +4=控制域、地址 、类型标识 、	文件命令
	len = cmd_len+2+AddByte;
	
	// 报文帧长度 +6=报文头（4字节）校验和、结束符	
	p[0]=len + 6 ; 			

	// 帧头
	p[1]=0x68;  	//报文头
	p[2]=len;
	p[3]=len;
	p[4]=0x68;		
	p[5]=IEC101_ECHO_DATA;		//控制域
	p[6]=(BYTE)tRunPara.byAddr;	//链路地址

	// 命令
	p=&pt->tx_buf_s[7+AddByte]; // 调整位置
	memcpy(p,cmd_buf,cmd_len);

	// 计算检验和
	p=&pt->tx_buf_s[5];
	checksum=0;
	for(cnt=0; cnt<len; cnt++)
	{			
		checksum+=*p++;
	}
	*p++=checksum;

	// 帧尾
	*p++=0x16;		
	
}


/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/
int printf_file101(void)
{
	rt_printf("g_file101:\t%p\r\n",&g_file101);	
	
	rt_printf("state:\t\t%d\r\n",g_file101.state);	
	rt_printf("file_name:\t%s\r\n",g_file_item[g_file101.file_index].file_name);	
	rt_printf("file_index:\t%d\r\n",g_file101.file_index);	
	rt_printf("file_type:\t%d\r\n",g_file101.file_type);	
	rt_printf("file_crc:\t0x%04x\r\n",g_file101.file_crc);	
	rt_printf("file_length:\t%d\r\n",g_file101.file_length);	
	rt_printf("file_offset:\t%d\r\n",g_file101.file_offset);	
	rt_printf("file_buf:\t%p\r\n",g_file101.file_buf);	

	return 0;
}



/*------------------------------ 文件结束 -------------------------------------
*/


