/******************************************************************************
版权所有：	
文件名称：	Maintain.c
文件版本：	01.01
创建作者：	xxxxxx
创建日期：	2013-03-05
功能说明：	装置维护管理
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include    "head.h"  

/*------------------------------- 宏定义 --------------------------------------
*/
#define MAINTAIN_TYPE 			138
#define MAINTAIN_ACK			0X80
#define MAINTAIN_NAK			0X40

#define MAINTAIN_ERR_OK			0x00
#define MAINTAIN_ERR_NAME		0x01
#define MAINTAIN_ERR_TYPE		0x02
#define MAINTAIN_ERR_BUSY		0x03
#define MAINTAIN_ERR_ADDR		0x04
#define MAINTAIN_ERR_SIZE		0x05
#define MAINTAIN_ERR_CRC		0x06
#define MAINTAIN_ERR_SAVE		0x07
#define MAINTAIN_ERR_PHASE		0x08
#define MAINTAIN_ERR_MEM		0x09
#define MAINTAIN_ERR_STATE		0x0a
#define MAINTAIN_ERR_OCODE		0X0B
#define MAINTAIN_ERR_NCODE		0X0C
#define MAINTAIN_ERR_NSLOT		0X0D
#define MAINTAIN_ERR_TIME		0X0E
#define MAINTAIN_ERR_SETNULL	0X0F
#define MAINTAIN_ERR_SETERR		0X10
#define MAINTAIN_ERR_DATAL		0X11	//输入校正值太小
#define MAINTAIN_ERR_CHXS		0X12	//通道系数超范围
#define MAINTAIN_ERR_ANGLEL		0X13	//输入角度值太小
#define MAINTAIN_ERR_ANGLEH		0X14	//输入角度值太大
#define MAINTAIN_ERR_ANGLEXS	0X15	//角度系数超范围
#define MAINTAIN_ERR_XSSAVE		0X16	//系数保存错误
#define MAINTAIN_ERR_CODE		0X17
#define MAINTAIN_ERR_CMD		0X18	// 不支持的命令
#define MAINTAIN_ERR_FORMAT		0X19	// 格式错误
#define MAINTAIN_ERR_OTHER		0xff

#define MAINTAIN_ATTR_UP		0X01
#define MAINTAIN_ATTR_DOWN		0X02

#define BOARD_NUMBER		12		//最大支持板卡个数

/*------------------------------ 类型结构 -------------------------------------
*/
enum mState
{
	MS_IDLE = 0,			// 空闲状态
	MS_REQUEST,				// 维护请求
	MS_END,					// 维护结束
	MS_UPDATE,				// 文件更新命令
	MS_EQUINF,				// 查看装置信息
	
	MS_BOARDINF,			// 查看板卡信息
	MS_TEST_DO,				// 开出测试
	MS_TEST_DI,				// 开入值刷新
	MS_TEST_LED,			// LED测试
	MS_SAMPLE,				// 零漂值刷新
	
	MS_ADJUST,				// 采样校准 
	MS_TEST_REMOTE,			// 远动测试
	MS_RECORD,				// 手动启动录波
	MS_MEASURE,				// 测量值刷新
	MS_TIME_DIS,			// 时间刷新
	
	MS_TIME_SET,			// 对时
	MS_FLAG_DIS,			// 标志刷新
	MS_BAT_MANAGE,			// 电池管理
	MS_CLEAR_SOE,			// 清除SOE
	MS_SET_CODE,			// 修改密码
	
	MS_KEEP_ALIVE,			// 心跳命令
	MS_BOARD_VERSION,		// 主板版本
	MS_DIDO_AUTO_TEST,		// 开入开出自动测试
	MS_BOARD_DI,			// 板卡遥信
	MS_RESOURCE_THAN,		// 资源表文件比对
	
	MS_BOARD_MEASURE,       // 板卡测量值刷新
	MS_BOARD_CALIBRATION,   // 板卡校准系数上传
	MS_DEFAULT_CALIBRATION, // 恢复默认校准系数
	MS_SAMPLE_CALIBRATION,  // 整机采样校准
	MS_DEFAULT,             // 恢复出厂设置

	MS_UZTEMP_MEASURE,		// 直流、温度刷新
	MS_ADJUST_UZL,			// 直流校准
	MS_SAMPLE_TEST,			// 采样通道测试
	MS_KRKC_TEST,			// 开入开出测试
	MS_LCD_TEST,			// LCD测试
	
	MS_RESET_TEST,			// 装置复位
	MS_CFGINF,				// 配置信息查看
	MS_ERRINF,				// 故障信息查看
	MS_GETIP,				// 获取网口及对应IP
	MS_GET_GPRS_INFO,		// 得到GPRS信息
	MS_FZXS_UD,				// 辐值系数上传下载
	MS_AC_CFG,				// 采样板单板通道配置
	MS_DC_FACTOR,			// 直流校准系数
	MS_WAVE_OK,				// 录波完成
	MS_FILE_ISUPDATE,		// 文件是否更新
	MS_COMM_TEST,			// 串口测试
	MS_PASSWORD,			// 密码及权限确认
	MS_INSTU,				// 内部状态查看
	MS_RCD_NAME,			// 录波文件名称获取
	MS_RMT_PAIR,			// 遥控器配对
	MS_BOARDINF2,			// 查看板卡信息
	MS_SET_MTPWD,			// 设置维护工具密码
	MS_MT_PWD,				// 维护工具密码及权限确认
	MS_CLOSE_PORT,			// 关闭维护端口服务
	MS_AUTH,				// 装置授权管理
	MS_YD_REFRESH,			// 远动遥信遥测刷新
	MS_FACTORY_SETUP,		//出厂设置
#if defined(CPU_AM335X) 
	MS_APP_BAK_START,		//启动app分区备份 58
	MS_APP_BAK_RESULT,		//查询app分区备份结果	59
#endif	
};

struct maintain
{
	enum mState state;
	s32 file_index;
	u16	file_type;
};


//板卡类型
enum
{
	BOARD_MASTER=0,		//主板
	BOARD_AUX,			//辅助功能板
	BOARD_DI_30,		//DI板:30个
	BOARD_DI_72,		//DI板:72个
	BOARD_DO,			//DO板
	BOARD_AI_UI,		//AI板:电压3个，电流9个
	BOARD_AI_I,			//AI板:电流12个
	BOARD_POWER,		//电源板
	BOARD_DISP,			//显示板
};


//采样板类型
enum
{
	AC_4U12I=1,
	AC_4U9I,
	AC_1U12I,
	AC_6U4I,
	AC_4U4I,
	ACTYPE_NUM,
};


//板卡信息格式
struct board_inf
{
	BYTE	bytype;			//板卡类型
	BYTE	bystatus;		//板卡状态
	BYTE	byCRC[2];		//程序CRC校验
	BYTE	byVer[4];		//程序版本	
};

struct ac_test_type
{
	char * 	name;
	u16		normal_data;
	short	normal_angle;
};

struct ac_test_board
{
	int type;
	int num;
	const struct ac_test_type
 *data;
};

#define FILELIST_FILE_VERSION	0X01010101	//文件列表版本
#define MTPWD_FILE_VERSION	0X01010101	//文件版本

/*------------------------------ 全局变量 -------------------------------------
*/

// 维护接入方式，是串口还是网络，如果是串口，不能打开网络端口
bool g_mt_rs232;

struct maintain g_maintain = {0};
struct maintain_def g_mtbuf;
struct prog_up g_prog_up;

static const char * mt_init_pwd = "gh123456@";           	// 维护工具默认密码
static char mt_pwd[17];

extern struct timespec g_sys_time;

u8 dido_buf[128];

uint32_t alive_us0 = 0,alive_us1 = 0;

uint32_t rmttest_us0 = 0,rmttest_us1 = 0;

const struct ac_test_type g_dtu_ac4u12i_desc[17] = 
{
	{"Ua",		100, 	0},
	{"Ub",		100, 	-120},
	{"Uc",		100, 	120},
	{"US",		100, 	120},
	
	{"Ia1",		5, 		0},
	{"Ib1",		5, 		-120},
	{"Ic1",		5, 		120},
	
	{"Ia2",		5, 		0},
	{"Ib2",		5, 		-120},
	{"Ic2",		5, 		120},
	
	{"Ia3",		5, 		0},
	{"Ib3",		5, 		-120},	
	{"Ic3",		5, 		120},
	
	{"Ia4",		5, 		0},
	{"Ib4",		5, 		-120},	
	{"Ic4",		5, 		120},
	
	{"F",		50, 	0},
};
#define AC_DTU_4U12I_NUM (sizeof(g_dtu_ac4u12i_desc)/sizeof(g_dtu_ac4u12i_desc[0]))

const struct ac_test_type g_dtu_ac4u9i_desc[17] = 
{
	{"Ua",		100, 	0},
	{"Ub",		100, 	-120},
	{"Uc",		100, 	120},
	{"US",		100, 	120},
	
	{"Ia1",		5, 		0},
	{"Ib1",		5, 		-120},
	{"Ic1",		5, 		120},
	
	{"Ia2",		5, 		0},
	{"Ib2",		5, 		-120},
	{"Ic2",		5, 		120},
	
	{"Ia3",		5, 		0},
	{"Ib3",		5, 		-120},	
	{"Ic3",		5, 		120},
	
	{"+12V",	12, 	0},
	{"-12V",	-12, 	0},
	{"+05V",	5, 		0},
	
	{"F",		50, 	0},
};
#define AC_DTU_4U9I_NUM (sizeof(g_dtu_ac4u9i_desc)/sizeof(g_dtu_ac4u9i_desc[0]))


const struct ac_test_type g_dtu_ac1u12i_desc[17] = 
{
	{"US1",		100, 	0},
	
	{"Ia1",		5, 		0},
	{"Ib1",		5, 		-120},
	{"Ic1",		5, 		120},
	
	{"Ia2",		5, 		0},
	{"Ib2",		5, 		-120},
	{"Ic2",		5, 		120},
	
	{"Ia3",		5, 		0},
	{"Ib3",		5, 		-120},	
	{"Ic3",		5, 		120},
	
	{"Ia4",		5, 		0},
	{"Ib4",		5, 		-120},	
	{"Ic4",		5, 		120},

	{"+12V",	12, 	0},
	{"-12V",	-12, 	0},
	{"+05V",	5, 		0},
	
	{"F",		50, 	0},
};
#define AC_DTU_1U12I_NUM (sizeof(g_dtu_ac1u12i_desc)/sizeof(g_dtu_ac1u12i_desc[0]))

const struct ac_test_type g_ftu_4u4i_desc[9] = 
{
	{"UA",		100, 	0},
	{"UB",		100, 	-120},	
	{"UC",		100, 	120},
	{"U0",		100, 	120},
	
	{"IA",		5, 		0},	
	{"IB",		5, 		-120},
	{"IC",		5, 		120},
	{"I0",		5, 		120},
	
	{"F",		50, 	0},
};
#define AC_FTU_4U4I_NUM (sizeof(g_ftu_4u4i_desc)/sizeof(g_ftu_4u4i_desc[0]))

struct ac_test_board g_ac_test_board[] = 
{
	{AC_4U12I,AC_DTU_4U9I_NUM,g_dtu_ac4u12i_desc},
	{AC_4U9I,AC_DTU_4U9I_NUM,g_dtu_ac4u9i_desc},
	{AC_1U12I,AC_DTU_1U12I_NUM,g_dtu_ac1u12i_desc},
	{AC_4U4I,AC_FTU_4U4I_NUM,g_ftu_4u4i_desc},
};
#define AC_TEST_BOARD_NUM (sizeof(g_ac_test_board)/sizeof(g_ac_test_board[0]))

/*------------------------------ 函数声明 -------------------------------------
*/
static void _maintain_state_reset(void);
static void _maintain_echo(struct maintain_def *pt,u8 * cmd_buf,u8 cmd_len);
static void _maintain_recv_rst(struct maintain_def *pt);
static void _maintain_send(void);
static int _maintain_comm(struct maintain_def *pt,unsigned char *buf,int len);
static int _trans_file_comm(struct maintain_def *pt,u8 *buf,int len);
static int _maintain_pwd_createfile(u8 *pwd);
static int _maintain_pwd_readfile(void);
extern BYTE g_LedNo;

extern struct down_program_comm g_down_program; //面板升级
int IEC101_TransFile(IEC101_DEF *pt,unsigned char *buf,int len);


/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/

/**************************************************************************
函数名称：MainTain_Init
函数版本：1.00 
作者：   
创建日期：2013.03.28     
函数功能说明：维护命令初始化
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/

void MainTain_Init(void)
{
	int i;
	memset(&g_mtbuf,0,sizeof(struct maintain_def));
	alive_us0= ustimer_get_origin();
	alive_us1= ustimer_get_origin();
	i = _maintain_pwd_readfile();
	if (i != 0)
	{
		u8 j, tmp_pwd[16];
		memset (&mt_pwd, ' ', 16);	
		memcpy (&mt_pwd, mt_init_pwd, strlen(mt_init_pwd));	
		for (j=0; j<16; j++)
		{
			tmp_pwd[j] = ~mt_pwd[j];
		}
		_maintain_pwd_createfile(tmp_pwd);
		rt_printf("维护工具密码文件错误: %d\r\n", i);
	}
}

/**************************************************************************
函数名称：Maintain_Applay
函数版本：1.00 
作者：   
创建日期：2013.03.28     
函数功能说明：维护命令链路数据处理
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
void Maintain_Applay(void)
{
	struct maintain_def *pt=&g_mtbuf;
	BYTE *pd;
	u8 AddByte=0;

	// 如果有僵死的维护线程，回收。
	net_maintain_zombie();

	if(bMaintain)	
	{
		alive_us1 = ustimer_get_origin();

#if defined (CPU_AM335X) || (defined CPU_FUXI)	
		//noted by sunxi: 目前维护工具为每30秒发1条心跳，如果漏1条，就已经是60秒了。
		//这样很容易出问题，应该是发3条心跳，1条都没有收到才被认为有问题才合理。100秒可有3条心跳了。
		//需要这里加了宏CPU_AM335X，但是所有平台都应该改为100秒。
		if(alive_us1 - alive_us0 > 100*USTIMER_SEC) //   100秒循环检查
#else		
		if(alive_us1 - alive_us0 > 60*USTIMER_SEC)
#endif
		{			
			bMaintain=false;
		}
	}
	
	if(g_run_stu.bToolRmtTest)
	{
		rmttest_us1 = ustimer_get_origin();
		if(rmttest_us1 - rmttest_us0> 600UL*USTIMER_SEC) //   10分钟自动退出远动测试模式
		{			
			g_run_stu.bToolRmtTest=false;
		}
	}	
	if(pt->bData)				//有接收到的数据
	{
		if (!g_mtbuf.hmi_mode)
		{
			g_file_save = 0;
		}

		pt->bData=false;
		if(pt->recvbuf[0]==0x10)  pd=&pt->recvbuf[1];//短帧
		else if(pt->recvbuf[0]==0x68)  pd=&pt->recvbuf[4];//长帧
		else 	return;		
		// rt_printf("Maintain_Recv buf= %x %x %x %x %x %x %x %x %x %x %x %x\r\n", pd[0],pd[1],pd[2],pd[3],pd[4],pd[5],pd[6],pd[7],pd[8],pd[9],pd[10],pd[11]);
		pt->dValidTime=dTCounter;                
		switch((pd[0]&0x0f))
		{
			case 3:				//请求/确认
			case 4:				//请求/无应答			
				switch(pd[2])		//类型标识判断
				{
					case 138://维护命令管理模块
						_maintain_comm(pt,&pd[2+AddByte],pt->recvbuf[1]-(2+AddByte));
					break;

					case 137: // 下载上传文件
						_trans_file_comm(pt,&pd[2+AddByte],pt->recvbuf[1]-(2+AddByte));
					break;
				}
			break;
		}	//类型判断结束

		_maintain_send();
	}
	else			//无有效数据接收，平衡式101处理自动发送数据
	{
		if(pt->bSend)return;  //正在发送数据，不处理

		if(dTCounter-pt->dValidTime>T_1s*10)   // 6秒后，未收到应答报文
		{
			
			pt->dValidTime=dTCounter;	
			if(++pt->byRetryTimes>2)  //重发三次后,重新初始化
			{
				pt->bSend=false;
			}
			else
			{
				//需重新组织发送
				_maintain_send();			
			}
		}
		return;	// 发送，未收到数据，返回		
	}	

}

/**************************************************************************
函数名称：Maintain_Manage
函数版本：1.00 
作者：   
创建日期：2013.03.28     
函数功能说明：维护命令处理
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
int Maintain_Manage(u8 *buf, u32 len, u8 *cmd_buf)
{
	u8 cmd_len=0;
	u16 i;
	char name[256];

#if defined(CPU_AM335X) 
		u32 llen;
		u8 *lbuf;
		u8 result = 0;
		struct file * pfile;
		loff_t pos;
		char *cmd_ls[] = {"/usr/sbin/app_backup.sh",NULL, NULL, NULL};
#endif
	
	cmd_buf[0] = MAINTAIN_TYPE;
	cmd_buf[1] = buf[1];
	alive_us0= ustimer_get_origin();

	switch(buf[1])
	{
		case MS_REQUEST:
	 		// 维护请求
			_maintain_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
			for (i=0; i<19; i++)	//检查版本号
			{
				if (buf[2+i] != szTool[i])
				{
					cmd_buf[1] |= MAINTAIN_NAK;
					break;
				}
			}	
#endif
			bMaintain = true;
			cmd_buf[1] |= MAINTAIN_ACK;
			
			g_maintain.state = MS_REQUEST;
		break;
			
		case MS_END:
			// 维护结束
			bMaintain = false;
			if(g_run_stu.bToolRmtTest)
			{
				g_run_stu.bToolRmtTest = false;
			}
			// 如果是重复报文，继续肯定应答。
			if(g_maintain.state == MS_END)
			{
				cmd_buf[1] |= MAINTAIN_ACK;
				cmd_len = 2;
				break;
			}

			// 判断是否需要复位
			if(buf[2] == 1) // 0：不复位；1：复位
			{
			}			

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

			// 复位全部状态后，设置状态为MS_END，继续应答重发确认帧。
			_maintain_state_reset();
			g_maintain.state = MS_END;
		break;

		case MS_UPDATE:
		{
			u16 file_type;
			char from_file_name[64];
			char to_file_name[64];
			memcpy(cmd_buf+2,buf+2,25); 
			
			// 检查阶段
			if((g_maintain.state != MS_REQUEST) || (!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[25] = MAINTAIN_ERR_PHASE;
				cmd_len = 26;
				break;
			}	

			//检查文件名
			g_maintain.file_index = file_check(buf+3,ATTR_DOWN);
			if(g_maintain.file_index < 0)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[25] = MAINTAIN_ERR_NAME;
				cmd_len = 26;	
				break;
			}	
			
			if (buf[25])
			{
				//子板升级
				if(g_maintain.file_type == FILETYPE_CHILDPRO)
				{
#if defined(BSP_CAN_ENABLE)
					extern struct program_comm g_program;
					if ((g_program.comm == 0)&&(g_prog_up.bit_echo == 0))
					{
						cmd_buf[1] |= MAINTAIN_NAK;
						cmd_buf[25] = MAINTAIN_ERR_OTHER;
						cmd_len = 26;	
						break;
					}
					else
					{
						cmd_buf[26] = g_prog_up.framesum;
						cmd_buf[27] = g_prog_up.framesum>>8;					
				
						cmd_buf[28] = g_prog_up.frameno;
						cmd_buf[29] = g_prog_up.frameno>>8;
						
						cmd_buf[30] = g_prog_up.bit_prog;
						cmd_buf[31] = g_prog_up.bit_prog>>8;

						cmd_buf[32] = g_prog_up.bit_echo;
						cmd_buf[33] = g_prog_up.bit_echo>>8;
						
						cmd_buf[1] |= MAINTAIN_ACK;
						cmd_len = 34;
					}
#endif
				
				}
				else if(g_maintain.file_type == FILETYPE_F308_HMI)
				{
					if ((g_down_program.comm == 0)&&(g_down_program.bit_echo == 0))
					{
						cmd_buf[1] |= MAINTAIN_NAK;
						cmd_buf[25] = MAINTAIN_ERR_OTHER;
						cmd_len = 26;	
						break;
					}
					else
					{
						cmd_buf[26] = g_down_program.framenum;
						cmd_buf[27] = g_down_program.framenum>>8;					
					
						cmd_buf[28] = g_down_program.frameno;
						cmd_buf[29] = g_down_program.frameno>>8;
						
						cmd_buf[30] = g_down_program.bit_prog;
						cmd_buf[31] = g_down_program.bit_prog>>8;

						cmd_buf[32] = g_down_program.bit_echo;
						cmd_buf[33] = g_down_program.bit_echo>>8;
						
						cmd_buf[1] |= MAINTAIN_ACK;
						//rt_printf("[frameno=%d, %d]\n", g_down_program.frameno,g_down_program.framenum);
						cmd_len = 34;
					}						
				}
				break;
			}
			
			memcpy(&g_maintain.file_type,buf+23,2);
		#ifndef MODE_LITTLE_ENDIAN	
			swap16(&g_maintain.file_type);
		#endif	
			file_type = file_check_type(buf+3,ATTR_DOWN);

			//文件校验，并进行移动、删除动作.注意GPRS相关文件作特殊处理
			if (g_file_save)
			{
				g_file_save = 0;
			}
			else if (g_maintain.file_type == file_type)
			{
				if (file_check_info(g_maintain.file_index) == 0)
				{
					char log_buf[128]={0};
					uint32_t us0 = ustimer_get_origin();
					watchdog_feed_mainloop_50s();					
					sprintf(to_file_name,"%s%s",g_file_item[g_maintain.file_index].file_dir,g_file_item[g_maintain.file_index].file_name);
					sprintf(from_file_name,"%s%s","/tmp/",g_file_item[g_maintain.file_index].file_name);
					rt_file_mv(from_file_name,to_file_name);
					rt_printf("rt_file_mv:us=%d.\r\n",ustimer_get_duration(us0)/USTIMER_US);

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

					sprintf(log_buf,"%s updated",g_file_item[g_maintain.file_index].file_name);
					load_hs_log_rcd(TYPE_SW_UPDATE,true,NULL,log_buf,1);
				}
				else
				{
					sprintf(from_file_name,"%s%s","/tmp/",g_file_item[g_maintain.file_index].file_name);
					rt_file_del(from_file_name);

					if (g_maintain.file_type == FILETYPE_SET)
					{
						set_create_data_file();
					}
					
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[25] = MAINTAIN_ERR_CRC;
					cmd_len = 26;
					break;
				}
			}
			
			if (g_maintain.file_type == FILETYPE_SET)
			{
				int ret=0;
				ret = set_save_data_file(g_maintain.file_index);
				if (ret != 0)
				{
					cmd_buf[1] |= MAINTAIN_NAK;
					if (ret < 0)
					{
						cmd_buf[25] = MAINTAIN_ERR_CRC;
					}
					else if (ret & 0x07)
					{
						cmd_buf[25] = MAINTAIN_ERR_SETNULL;
					}
					else if (ret & 0x70)
					{
						cmd_buf[25] = MAINTAIN_ERR_SETERR;
					}					
					cmd_len = 26;
					break;
				}
			} 
		#ifdef FUN_GPRS	// modfiy for xxxxxx 20220706 GPRS没有使用。	
			else if(g_maintain.file_type == FILETYPE_INNERGPRS)
			{
				//extern void gprs_net_update_gprsini(void);
				//gprs_net_update_gprsini();	
				//不作任何处理.GPRS模块自己会复位.
				extern int g_update_gprs_driver;

				if(strcmp(g_file_item[g_maintain.file_index].file_name,FILE_NAME_GPRSDRIVER) == 0)
				{
					g_update_gprs_driver = 1;//置更新标志
				}
			} 
		#endif	
			else if(g_maintain.file_type == FILETYPE_CHILDPRO)
			{
#if defined(BSP_CAN_ENABLE)
				if (init_file_program(buf[2], g_maintain.file_index) != 0)	//文件读取校验有误
				{
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[25] = MAINTAIN_ERR_CRC;
					cmd_len = 26;
					rt_file_del("/tmp/DTU-DIDO.elf.bin");
					break;
				}
				else
				{
					cmd_buf[25] = 1;	
				}	
#endif
			}
			else if(g_maintain.file_type == FILETYPE_F308_HMI)
			{
			
				if (init_down_program( g_maintain.file_index) != 0)	//文件读取校验有误
				{
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[25] = MAINTAIN_ERR_CRC;
					cmd_len = 26;
					rt_file_del("/tmp/F308_HMI.bin");
					break;
				}
				else
				{
					cmd_buf[25] = 1;	
				}						
			}
			
			cmd_buf[1] |= MAINTAIN_ACK;

			if (cmd_buf[25])
			{
				//子板升级
				if(g_maintain.file_type == FILETYPE_CHILDPRO)
				{
					cmd_buf[26] = g_prog_up.framesum;
					cmd_buf[27] = g_prog_up.framesum>>8;					
			
					cmd_buf[28] = g_prog_up.frameno;
					cmd_buf[29] = g_prog_up.frameno>>8;
					
					cmd_buf[30] = g_prog_up.bit_prog;
					cmd_buf[31] = g_prog_up.bit_prog>>8;

					cmd_buf[32] = g_prog_up.bit_echo;
					cmd_buf[33] = g_prog_up.bit_echo>>8;

					cmd_len = 34;				
				}
				else if(g_maintain.file_type == FILETYPE_F308_HMI)
				{
					cmd_buf[26] = g_down_program.framenum;
					cmd_buf[27] = g_down_program.framenum>>8;					
			
					cmd_buf[28] = g_down_program.frameno;
					cmd_buf[29] = g_down_program.frameno>>8;
					
					cmd_buf[30] = g_down_program.bit_prog;
					cmd_buf[31] = g_down_program.bit_prog>>8;

					cmd_buf[32] = g_down_program.bit_echo;
					cmd_buf[33] = g_down_program.bit_echo>>8;

					cmd_len = 34;							
				}

				break;
			}
			else
			{
				cmd_len = 26;
			}
		}

		break;
		
		case MS_EQUINF:
			// 查看装置信息		
			cmd_len = set_get_fixed_args_sz(buf[2],cmd_buf+2,240);
			cmd_len += 2;
			cmd_buf[1] |= MAINTAIN_ACK;
		break;
		
		case MS_BOARDINF:
		case MS_BOARDINF2:
		{
			// 查看板卡信息
			#define BOARD_INF_MAX_SLOT  11
			int slot_num=0,slot_begin=0;
			int b_info_size;

			if(buf[1] == MS_BOARDINF)
			{
				slot_num = g_equ_config->equ_slot_num > BOARD_INF_MAX_SLOT ? BOARD_INF_MAX_SLOT : g_equ_config->equ_slot_num;
				slot_begin = 0;
			}
			else if(g_equ_config->equ_slot_num > BOARD_INF_MAX_SLOT)
			{
				slot_num = g_equ_config->equ_slot_num -BOARD_INF_MAX_SLOT;
				slot_begin = BOARD_INF_MAX_SLOT;
			}
			else
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_OTHER;
				cmd_len = 3;
				break;
			}
			
			cmd_len = 2;
			b_info_size = 21;
			for(i=0; i<slot_num; i++)
			{
				cmd_buf[2+i*b_info_size] = g_board_info[slot_begin + i].type;
				cmd_buf[3+i*b_info_size] = g_board_info[slot_begin + i].status;
				cmd_buf[4+i*b_info_size] = g_board_info[slot_begin + i].errcode;
				cmd_buf[5+i*b_info_size] = g_board_info[slot_begin + i].crc;
				cmd_buf[6+i*b_info_size] = g_board_info[slot_begin + i].crc>>8;
				cmd_buf[7+i*b_info_size] = g_board_info[slot_begin + i].version;
				cmd_buf[8+i*b_info_size] = g_board_info[slot_begin + i].version>>8;
				cmd_buf[9+i*b_info_size] = g_board_info[slot_begin + i].version>>16;
				cmd_buf[10+i*b_info_size] = g_board_info[slot_begin + i].version>>24;
				cmd_buf[11+i*b_info_size] = g_board_info[slot_begin + i].update_time.tv_sec;
				cmd_buf[12+i*b_info_size] = g_board_info[slot_begin + i].update_time.tv_sec>>8;
				cmd_buf[13+i*b_info_size] = g_board_info[slot_begin + i].update_time.tv_sec>>16;
				cmd_buf[14+i*b_info_size] = g_board_info[slot_begin + i].update_time.tv_sec>>24;
				cmd_buf[15+i*b_info_size] = g_board_info[slot_begin + i].update_time.tv_nsec;
				cmd_buf[16+i*b_info_size] = g_board_info[slot_begin + i].update_time.tv_nsec>>8;
				cmd_buf[17+i*b_info_size] = g_board_info[slot_begin + i].update_time.tv_nsec>>16;
				cmd_buf[18+i*b_info_size] = g_board_info[slot_begin + i].update_time.tv_nsec>>24;
				cmd_buf[19+i*b_info_size] = g_board_info[slot_begin + i].can_bus;
				cmd_buf[20+i*b_info_size] = g_board_info[slot_begin + i].can_bus>>8;
				cmd_buf[21+i*b_info_size] = g_board_info[slot_begin + i].is_check;
				cmd_buf[22+i*b_info_size] = g_board_info[slot_begin + i].is_check>>8;

				cmd_len += b_info_size;
			}
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;	
		
		case MS_TEST_DO:
			// 开出测试

			// 检查阶段
			if((g_maintain.state != MS_REQUEST) ||(!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}
			bMaintain_test = true;
			dido_single_test(buf[2],buf[3]);
			bMaintain_test = false;

			cmd_buf[2] = buf[2];
			cmd_buf[3] = buf[3];
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 4;
		break;

		case MS_TEST_DI:
		{				
			// 开入值刷新
			int sw;

			sw = buf[2];
			cmd_buf[2] = sw;
			
			if(sw == 0)
			{
				int i;
				long flag=0;
				long value=0;
				long flag2=0;
				long value2=0;
				
				for(i=0;i<PUB_DI_NUM;i++)
				{
					if((short)g_sw_pub.di_cfg_index[i]!=INDEX_INVALLID)  //此遥信有配置
					{

						struct equ_config_di *ecd=&g_equ_config_di[g_sw_pub.di_cfg_index[i]];

						
						if(i<32)
						{
							if(dido_di_is_on(ecd->slot,ecd->index))
							{
								value |= (1<<i);
							}
							
							flag |= (1<<i);
						}
						else
						{
							if(dido_di_is_on(ecd->slot,ecd->index))
							{
								value2 |= (1<<(i-32));
							}
							
							flag2 |= (1<<(i-32));
						}
					}
				}
				
				cmd_buf[3] = flag;
				cmd_buf[4] = (flag >> 8);
				cmd_buf[5] = (flag >> 16);
				cmd_buf[6] = (flag >> 24);
				cmd_buf[7] =  value;
				cmd_buf[8] = (value >> 8);
				cmd_buf[9] = (value >> 16);
				cmd_buf[10] = (value >> 24); 				
				cmd_len = 11;
				if(PUB_DI_NUM>32)
				{
					cmd_buf[11] = flag2;
					cmd_buf[12] = (flag2 >> 8);
					cmd_buf[13] = (flag2>> 16);
					cmd_buf[14] = (flag2 >> 24);
					cmd_buf[15] =  value2;
					cmd_buf[16] = (value2 >> 8);
					cmd_buf[17] = (value2 >> 16);
					cmd_buf[18] =(value2 >> 24); 		
					cmd_len = 19;
				} 				
			}
			else if(sw <= SWITCH_NUM_MAX)
			{
				int i;
				long flag=0;
				long value=0;
				long flag2=0;
				long value2=0;
				
				sw --;
				
				for(i=0;i<SW_DI_NUM;i++)
				{
					if((short)g_sw[sw].di_cfg_index[i]!=INDEX_INVALLID)  //此遥信有配置
					{
						struct equ_config_di *ecd=&g_equ_config_di[g_sw[sw].di_cfg_index[i]];

						if(i<32)
						{
							if(dido_di_is_on(ecd->slot,ecd->index))
							{
								value |= (1<<i);
							}
							flag |= (1<<i);
						}
						else
						{
							if(dido_di_is_on(ecd->slot,ecd->index))
							{
								value2 |= (1<<(i-32));
							}
							flag2 |= (1<<(i-32));
						}
					}
				}
				cmd_buf[3] = flag;
				cmd_buf[4] = (flag >> 8);
				cmd_buf[5] = (flag>> 16);
				cmd_buf[6] = (flag >> 24);
				cmd_buf[7] =  value;
				cmd_buf[8] = (value >> 8);
				cmd_buf[9] = (value >> 16);
				cmd_buf[10] =(value >> 24); 				
				cmd_len = 11;				
				if(SW_DI_NUM>32)
				{

					cmd_buf[11] = flag2;
					cmd_buf[12] = (flag2 >> 8);
					cmd_buf[13] = (flag2>> 16);
					cmd_buf[14] = (flag2 >> 24);
					cmd_buf[15] =  value2;
					cmd_buf[16] = (value2 >> 8);
					cmd_buf[17] = (value2 >> 16);
					cmd_buf[18] =(value2 >> 24); 
					cmd_len = 19;
				}

			}
			else 
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_NSLOT;
				cmd_len = 3;
				break;
			}

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;

		case MS_TEST_LED:
		{	// LED测试

			// 检查阶段
			if((g_maintain.state != MS_REQUEST) ||(!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}

			// 显示面板LED测试
			if(buf[2] == 0)
			{
				add_led_test(TEST_LED);
			}
			// 辅助板LED测试
			else if(buf[2] == 1)
			{
				g_led_aux_test_st= 1;
			}
			// 状态板LED测试
			else if(buf[2] == 2)
			{
				g_led_aux_test_st= 1;
			}

			cmd_buf[2] = buf[2];
		
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 3;
		}
		break;

		case MS_SAMPLE:
		{	// 零漂值刷新
			u8 slot, i;
			short data;
		#ifdef CPU_FUXI
			int samcnt=((g_adc_dots_data_count/ADC_REC_SAMPLE_RATE)&CFG_ADC_DOTS_MASK);
		#else			
			int samcnt=((g_adc_dots_count-1)&CFG_ADC_DOTS_MASK);
		#endif
			cmd_buf[2] = buf[2] ;
			slot = buf[2];
			
			if((slot>=16)
				|| !(g_board_info[slot].type== BOARD_TYPE_FTUKZ1
					||(g_board_info[slot].type >= BOARD_TYPE_DFTU_KC00&&g_board_info[slot].type<BOARD_TYPE_DFTU_KC00+BOARD_TYPE_KZ_NUM)
					|| g_board_info[slot].type == BOARD_TYPE_AC)  //只有7到10板有零漂
				|| (g_board_info[slot].type== BOARD_TYPE_FBDTU_MAIN)
				|| (g_board_info[slot].type== BOARD_TYPE_FBDTU_MAIN1)

			)  
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_NSLOT;
				cmd_len = 3;
				break;
			}			
			
			for(i=0; i<EQU_SLOT_AC_CHN; i++)
			{
				data = g_adc_dots[equ_get_ac_channel(slot,i)][samcnt];
				cmd_buf[i*2+3]=(data);
				cmd_buf[i*2+4]=(data)>>8;
			}

			cmd_len = EQU_SLOT_AC_CHN*2;
			
			// 发送ACK 
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len += 3;
		}
		break;

		case MS_ADJUST:
		{
			// 采样校准
			// 检查阶段
			int ret;
			if((g_maintain.state != MS_REQUEST) || (!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}
			ret = sw_auto_adjust(-1);
			switch(ret)
			{
				case 0:
					cmd_buf[1] |= MAINTAIN_ACK;
					cmd_len = 2;
				break;
				
				case -1:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_DATAL;
					cmd_len = 3;
				break;
				
				case -2:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_CHXS;
					cmd_len = 3;
				break;
				
				case -3:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_ANGLEL;
					cmd_len = 3;
				break;
				
				case -4:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_ANGLEH;
					cmd_len = 3;
				break;
				
				case -5:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_ANGLEXS;
					cmd_len = 3;
				break;
				
				case -6:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_XSSAVE;
					cmd_len = 3;
				break;
			}

			if (ret == 0)
			{
				log_str_time(LOG_OPERATE,"工具交流校准成功",0,0);
			}
			else
			{
				log_str_time(LOG_OPERATE,"工具交流校准失败",0,0);
			}
		}
		break;

		case MS_TEST_REMOTE:
		{	// 远动测试
		
			// 检查阶段
			if(g_maintain.state != MS_REQUEST)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}

			cmd_buf[2] = buf[2];
			
			if(buf[2] == 0x01)
			{
				send_rmt_yc(buf);	// 遥测
			}
			else if(buf[2] == 0x06)		// 电度
			{
				send_rmt_dd(buf);	// 遥测
			}
			else if (buf[2] == 0x05)
			{
				int ret;
				char *szErr;
				ret = send_rmt_yk(buf);	// 遥控
				if(ret != 0)
				{
					szErr = RmtCtrl_Err(ret);
					// 发送ACK
					cmd_buf[1] |= MAINTAIN_NAK;
					strcpy(&cmd_buf[3],szErr);
					cmd_len = 3 + strlen(szErr) + 1;
					break;
				}
			}
			else if(buf[2] == 0x02||buf[2] == 0x04)		//xj 2019-10-18	解决远动测试发送遥测时，遥信也突发上送 			
			{
				send_rmt_yx(buf);	// 遥信
			}
			rmttest_us0 = ustimer_get_origin();
			g_run_stu.bToolRmtTest = true;			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 3;
		}
		break;

		case MS_RECORD:
		{	// 手动启动录波
			int waves;
			struct rtc_time_t tm;
			struct timespec ts;
			
			memcpy(cmd_buf+2,buf+2,4);

			waves = (int)buf[2] | (int)buf[3]<<8 | (int)buf[4]<<16 | (int)buf[5]<<24;	// zwg 此处有BUG，维护工具未发时间

			// 得到当前时刻。
			clk_time_get(&ts);
			timespec_to_rtc(ts,&tm,0);
			rt_printf("当前时间: %04d-%02d-%02d %02d:%02d:%02d:%09d!\r\n",
				tm.year + 2000,
				tm.month,
				tm.day,
				tm.hour,
				tm.min,
				tm.ms/1000,
				ts.tv_nsec
				);
			rcd_start(SWITCH_NUM_MAX,RECORD_TYPE_SD, waves);
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 6;
		}
		break;

		case MS_MEASURE:
		{
			// 测量值刷新
			#define YC_NUM_PER_FRAME   (250/9)
			int sw,frame,cnt;

			sw = buf[2]&0x1f;
			frame = (buf[2]>>5)&0x07;
			cnt = 0;

			if (sw == 0)
			{
				long val,ang;
				int pCal=0;
				
				for(i=frame*YC_NUM_PER_FRAME;i<PUB_AC_NUM_ALL;i++)
				{
					val=g_sw_pub.ac_in[i];
					if(i<PUB_AC_NUM)
					{
						ang=g_ui[i].p;
						if(g_ui[i].chn_index!=CFG_ADC_CHANNEL_ZERO)
						{
							pCal = 0x1;
						}
						else if(g_ui[i].ui_base_make!=-1)
						{
							pCal = 0x2;
						}
						else
						{
							pCal = 0x4;
						}
					}	
					else
					{
						ang=ANGEL_INVALID;
						pCal=0x2;
					}
					
					if(g_unit[g_pub_ac_desc[i].unit].zero>0&&_AbsL(val)<g_unit[g_pub_ac_desc[i].unit].zero && pRunSet->bTT_RET_ZERO)
					{
						val=0;
						ang=ANGEL_INVALID;
					}					
		
					cmd_buf[3+cnt*9] = pCal;
					cmd_buf[3+cnt*9+1] = val;
					cmd_buf[3+cnt*9+2] = (val >> 8);
					cmd_buf[3+cnt*9+3] = (val >> 16);
					cmd_buf[3+cnt*9+4] = (val >> 24);
					cmd_buf[3+cnt*9+5] =  ang;
					cmd_buf[3+cnt*9+6] = (ang >> 8);
					cmd_buf[3+cnt*9+7] = (ang >> 16);
					cmd_buf[3+cnt*9+8] = (ang >> 24);

					cnt++;
					if(cnt== YC_NUM_PER_FRAME)
					{
						frame++;
						break;
					}
				}
			}
			else if (sw <= EQU_SLOT_NUM_MAX)
			{
				int index_begin;				
				index_begin = UI_SW_INDEX_BEGIN(sw-1);

				for(i=frame*YC_NUM_PER_FRAME;i<SW_AC_NUM_ALL;i++)
				{
					long val,ang;
					int pCal=0; 
					
					val=g_sw[sw-1].ac_in[i];
					if(i<SW_AC_NUM)
					{
						ang=g_ui[index_begin+i].p;
						if(g_ui[index_begin+i].chn_index!=CFG_ADC_CHANNEL_ZERO)
						{
							pCal = 0x1;
						}
						else if(g_ui[index_begin+i].ui_base_make!=-1)
						{
							pCal = 0x2;
						}
						else
						{
							pCal = 0x4;
						}

					}
					else
					{
						pCal=0x2;
						ang=ANGEL_INVALID;
					}
						
					if(g_unit[g_sw_ac_desc[i].unit].zero>0&&_AbsL(val)<g_unit[g_sw_ac_desc[i].unit].zero && pRunSet->bTT_RET_ZERO)
					{
						val=0;
						ang=ANGEL_INVALID;
					}
					if(g_sw_ac_desc[i].unit==UNIT_GE)val*=65536;
					
					cmd_buf[3+cnt*9] = pCal;
					cmd_buf[3+cnt*9+1] = val;
					cmd_buf[3+cnt*9+2] = (val >> 8);
					cmd_buf[3+cnt*9+3] = (val >> 16);
					cmd_buf[3+cnt*9+4] = (val >> 24);
					cmd_buf[3+cnt*9+5] =  ang;
					cmd_buf[3+cnt*9+6] = (ang >> 8);
					cmd_buf[3+cnt*9+7] = (ang >> 16);
					cmd_buf[3+cnt*9+8] = (ang >> 24); 

					cnt++;
					if(cnt== YC_NUM_PER_FRAME)
					{
						frame++;
						break;
					}
				}
			}
			
			cmd_len = cnt*9;
			cmd_len += 3;

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_buf[2] = sw;// | frame;	
		}
		break;

		case MS_TIME_DIS:
		{
			// 时间刷新
			struct rtc_time_t t_rtc;	
			struct timespec ts;
		#ifndef MODE_LITTLE_ENDIAN	
			u8 tmp=0;
		#endif
			// 得到系统时间		
			clk_time_get(&ts);
			timespec_to_rtc(ts,&t_rtc,1);
			memcpy(cmd_buf+2, &t_rtc, 8);		

		#ifndef MODE_LITTLE_ENDIAN
			tmp = cmd_buf[2];
			cmd_buf[2]=cmd_buf[3];
			cmd_buf[3]=tmp;

			tmp = cmd_buf[8];
			cmd_buf[8]=cmd_buf[9];
			cmd_buf[9]=tmp;
		#endif

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 10;
		}
		break;


		case MS_TIME_SET:
		{
			// 时间设置
			struct rtc_time_t t_rtc;
		#ifndef MODE_LITTLE_ENDIAN	
			u8 tmp=0;
		#endif
			
			memcpy(cmd_buf+2, buf+2, 8);

		#ifndef MODE_LITTLE_ENDIAN
			tmp = buf[2];
			buf[2]=buf[3];
			buf[3]=tmp;

			tmp = buf[8];
			buf[8]=buf[9];
			buf[9]=tmp;
		#endif

			memcpy(&t_rtc, buf+2, 8);
			
			// 设置系统时间
			if(sys_time_set(&t_rtc)!= 0)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_TIME;
				cmd_len = 3;
				break;
			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 10;
			log_str_time(LOG_OPERATE,"工具设置时间",0,0);
		}
		break;

		case MS_FLAG_DIS:
			// 标志刷新
			
			// 得到所需上传标志
			cmd_buf[2] = 1;
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len =  2;

		break;

		case MS_BAT_MANAGE:
			// 电源管理

			if(buf[2] == 1)
			{
				bat_active(1);
			}
			if(buf[3] == 1)
			{
				bat_act_off(1);
			}
			
			memcpy(cmd_buf+2,buf+2,2);

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 4;

		break;

		case MS_CLEAR_SOE:
			// 清除事件
			
			if (buf[2])	//清除操作记录
			{
				soe_clear_opt();
				soe_record_opt(EV_CLEAR_OPE,0);
			}
			if (buf[3])	//清除事件记录
			{
				soe_clear_ev();
				soe_record_opt(EV_CLEAR_SOE,0);
			}
			
			memcpy(cmd_buf+2,buf+2,2);		
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 4;
		break;

		case MS_SET_CODE:
		{
			// 设置密码
			u16 old_password,new_password;
			
			old_password = buf[2] | (buf[3]<<8);
			new_password = buf[4] | (buf[5]<<8);
			
			if((old_password!=tRunPara.wPassword) && (old_password!=PASS_WORD))
			{
				old_password=0;
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_OCODE;	//旧密码错误
				cmd_len = 3;
				break;
			}
			if(new_password == INTER_PASSWORD)
			{
				new_password=0;
				old_password=0;
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_NCODE;	//新密码无效
				cmd_len = 3;
				break;
			}
			//SavePassword(new_password);
			tRunPara.wPassword = ReadPassword();	
			log_str_time(LOG_OPERATE,"工具设置用户密码",0,0);
		
			memcpy(cmd_buf+2,buf+2,4);		
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 6;
		}
		break;

		case MS_KEEP_ALIVE:
		{
			alive_us0= ustimer_get_origin();
			cmd_len = 2;
		}
		break;
		case MS_BOARD_VERSION:
		{	// 主板版本
			
			int flag,no=0;
			struct board_info *bi;
			bi = g_board_info;

			flag = buf[2];
			
			cmd_buf[2] =flag;

				
				
			switch(flag)
			{
				case 0:
					no = ENV_U_BOOT;
					break;
				case 1:
					no = ENV_KERNEL;
					break;
				case 2:
					no = ENV_ROOT_FS;
					break;
				case 3:
					sprintf(cmd_buf+3,"APP    VERSION:SV%02d.%03d %s",
						VER_NUM/1000,VER_NUM%1000,VER_TIME);
					cmd_len = strlen(cmd_buf+3) + 3;
					break;
#ifdef CPU_FUXI
				//fuxi 增加裸核版本信息
				case 4:
					sprintf(cmd_buf+3,"LuoHe  VERSION:V%d.%02d %s CRC=%X",
						LuoHe_version.ver/100,LuoHe_version.ver%100,LuoHe_version.time,LuoHe_version.v_crc);
					cmd_len = strlen(cmd_buf+3) + 3;
					break;
#endif					
				default:
					cmd_len = 3;
					break;
			}

			if(flag < 3)
			{
				sprintf(cmd_buf+3,"%s",env_get_info(no));
				
				cmd_len = strlen(env_get_info(no)) + 3;
			}

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			
		}
		break;

		case MS_DIDO_AUTO_TEST:
		{	// 开入开出自动测试			
			char tmpbuf[16];
			
			// 检查阶段
			if((g_maintain.state != MS_REQUEST) || (!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}

			bMaintain_test = true;
			switch(buf[2]) 
			{
			case 0:	//自动检测板卡测试
#if defined(BSP_CAN_ENABLE)
				tmpbuf[0] = 1;
				tmpbuf[1] = 3;
				tmpbuf[2] = 1;
				tmpbuf[3] = 4;
				tmpbuf[4] = 2;
				tmpbuf[5] = 5;
				tmpbuf[6] = 2;
				tmpbuf[7] = 6;
				dido_auto_test(tmpbuf,3);
				cmd_buf[6] = 3;
#else
				tmpbuf[0] = 1;	// DO板卡
				tmpbuf[1] = 1;	// DI板卡
				dido_auto_test(tmpbuf,1);
				cmd_buf[6] = 1;
#endif
				break;
			case 1:	//开出板卡测试
			case 2:	//开入板卡测试
				tmpbuf[0] = 1;
				tmpbuf[1] = 3;
				dido_auto_test(tmpbuf,1);
				cmd_buf[6] = 1;
				break;
			case 3: // 辅助板测试
				tmpbuf[0] = 5;
				tmpbuf[1] = 5;
				dido_auto_test(tmpbuf,1);
				cmd_buf[6] = 1;
				break;
			case 4: // 综合板测试
				tmpbuf[0] = 4;
				tmpbuf[1] = 6;
				
				dido_auto_test(tmpbuf,1);
				cmd_buf[6] = 1;
				break;
			case 5:	//开入60板测试
				tmpbuf[0] = 1;
				tmpbuf[1] = 3;
				tmpbuf[2] = 2;
				tmpbuf[3] = 3;
				dido_auto_test(tmpbuf,2);
				cmd_buf[6] = 2;
				break;
			default:
				break;
			}
			bMaintain_test = false;
			
			cmd_buf[2] = 0;
			
#if defined(BSP_CAN_ENABLE)
			{
			extern struct rt_stat 	g_stat_do_delay;
			extern struct rt_stat 	g_stat_di_delay;


			if (g_stat_do_delay.max > 1000000)
			{
				cmd_buf[2] |= 0x01;
			}

			if (g_stat_di_delay.max > (20000000+20000000))
			{
				cmd_buf[2] |= 0x02;
			}
			}
#endif
			cmd_buf[3] = 0;
			cmd_buf[4] = 0;
			cmd_buf[5] = 0;

			memcpy(cmd_buf+7,dido_buf,cmd_buf[6]*14);

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = cmd_buf[6]*14 + 4 + 3;
		}
		break;

		case MS_BOARD_DI:
		{	// 板卡遥信
			
			int slot;

			slot = buf[2];
			cmd_buf[2] = slot;
			
			{
				int i;
				long flag1=0;
				long value1=0;		
				long flag2=0;
				long value2=0;		
				int di_num;

				di_num = equ_get_di_num(slot);	
	
				for(i=0;i<di_num;i++)
				{
					if (i<32)
						flag1 |= (1<<i); 
					else
						flag2 |= (1<<(i-32)); 
					if(dido_di_is_on(slot,i))
					{
						if (i<32)
							value1 |= (1<<i);
						else
							value2 |= (1<<(i-32));
					}
					else
					{
						if (i<32)
							value1 &= ~(1<<i);
						else
							value2 &= ~(1<<(i-32));
					}
				}


				cmd_buf[3] = flag1;
				cmd_buf[4] = (flag1 >> 8);
				cmd_buf[5] = (flag1 >> 16);
				cmd_buf[6] = (flag1 >> 24);
				cmd_buf[7] = (flag2 >> 0);
				cmd_buf[8] = (flag2 >> 8);
				cmd_buf[9] = (flag2 >> 16);
				cmd_buf[10] = (flag2 >> 24);
				cmd_buf[11] =  value1;
				cmd_buf[12] = (value1 >> 8);
				cmd_buf[13] = (value1 >> 16);
				cmd_buf[14] = (value1 >> 24); 
				cmd_buf[15] = (value2 >> 0);
				cmd_buf[16] = (value2 >> 8);
				cmd_buf[17] = (value2 >> 16);
				cmd_buf[18] = (value2 >> 24); 

			}
			

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 19;
		}
		break;

		case MS_RESOURCE_THAN:
		{			
			memcpy(cmd_buf+2,buf+2,22); 

			// 定值描述文件
			if(strcmp(buf+2,FILE_NAME_SET_DESC) == 0)
			{
				cmd_buf[22] = setdesc_contrast.version;
				cmd_buf[23] = (setdesc_contrast.version >> 8);
				cmd_buf[24] = (setdesc_contrast.version >> 16);
				cmd_buf[25] = (setdesc_contrast.version >> 24);
				cmd_buf[26] =  setdesc_contrast.signature;
				cmd_buf[27] = (setdesc_contrast.signature >> 8);
				cmd_buf[28] = (setdesc_contrast.signature >> 16);
				cmd_buf[29] = (setdesc_contrast.signature >> 24); 
				cmd_buf[30] =  setdesc_contrast.length;
				cmd_buf[31] = (setdesc_contrast.length >> 8);
				cmd_buf[32] = (setdesc_contrast.length >> 16);
				cmd_buf[33] = (setdesc_contrast.length >> 24); 
				cmd_buf[34] =  setdesc_contrast.crc;
				cmd_buf[35] = (setdesc_contrast.crc>> 8);
			}
			// 资源描述文件
			else if(strcmp(buf+2,FILE_NAME_RSC) == 0)
			{
				cmd_buf[22] = rsc_contrast.version;
				cmd_buf[23] = (rsc_contrast.version >> 8);
				cmd_buf[24] = (rsc_contrast.version >> 16);
				cmd_buf[25] = (rsc_contrast.version >> 24);
				cmd_buf[26] =  rsc_contrast.signature;
				cmd_buf[27] = (rsc_contrast.signature >> 8);
				cmd_buf[28] = (rsc_contrast.signature >> 16);
				cmd_buf[29] = (rsc_contrast.signature >> 24); 
				cmd_buf[30] =  rsc_contrast.length;
				cmd_buf[31] = (rsc_contrast.length >> 8);
				cmd_buf[32] = (rsc_contrast.length >> 16);
				cmd_buf[33] = (rsc_contrast.length >> 24); 
				cmd_buf[34] =  rsc_contrast.crc;
				cmd_buf[35] = (rsc_contrast.crc>> 8);
			}
			// 通道配置文件
			else if(strcmp(buf+2,FILE_NAME_EQU_CFG) == 0)
			{
				cmd_buf[22] = g_equ_contrast.version;
				cmd_buf[23] = (g_equ_contrast.version >> 8);
				cmd_buf[24] = (g_equ_contrast.version >> 16);
				cmd_buf[25] = (g_equ_contrast.version >> 24);
				cmd_buf[26] =  g_equ_contrast.signature;
				cmd_buf[27] = (g_equ_contrast.signature >> 8);
				cmd_buf[28] = (g_equ_contrast.signature >> 16);
				cmd_buf[29] = (g_equ_contrast.signature >> 24); 
				cmd_buf[30] =  g_equ_contrast.length;
				cmd_buf[31] = (g_equ_contrast.length >> 8);
				cmd_buf[32] = (g_equ_contrast.length >> 16);
				cmd_buf[33] = (g_equ_contrast.length >> 24); 
				cmd_buf[34] =  g_equ_contrast.crc;
				cmd_buf[35] = (g_equ_contrast.crc>> 8);
			}
			else
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[22] = MAINTAIN_ERR_PHASE;
				cmd_len = 23;	
				break;
			}

			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 36;
		}
		break;
		case MS_BOARD_MEASURE:
		{	// 板卡测量值刷新			
			int slot,chn;

			slot = buf[2];
			cmd_buf[2] = slot;	

			if((slot>=16)
				|| !(g_board_info[slot].type== BOARD_TYPE_FTUKZ1
					||(g_board_info[slot].type >= BOARD_TYPE_DFTU_KC00&&g_board_info[slot].type<BOARD_TYPE_DFTU_KC00+BOARD_TYPE_KZ_NUM)
					|| g_board_info[slot].type == BOARD_TYPE_AC)  //只有7到10板有零漂
				|| (g_board_info[slot].type== BOARD_TYPE_FBDTU_MAIN)
				|| (g_board_info[slot].type== BOARD_TYPE_FBDTU_MAIN1)

			)  
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_NSLOT;
				cmd_len = 3;
				break;
			}

			chn = g_board_res[g_board_info[slot].type].ac_num;
			for(i=0;i<chn;i++)
			{
				long val,ang;
				int chn_index,j;

				chn_index = equ_get_ac_channel(slot,i);
				for(j=0;j<UI_NUM;j++)
				{
					if(g_ui[j].chn_index == chn_index)
					{
						break;
					}
				}

				if(chn_index >=0 && j != UI_NUM)
				{
					val=g_ui[j].e;
					ang=g_ui[j].p;
				}
				else
				{
					val=0;
					ang=0;
				}

				cmd_buf[3+i*8] = val;
				cmd_buf[3+i*8+1] = (val >> 8);
				cmd_buf[3+i*8+2] = (val >> 16);
				cmd_buf[3+i*8+3] = (val >> 24);
				cmd_buf[3+i*8+4] =  ang;
				cmd_buf[3+i*8+5] = (ang >> 8);
				cmd_buf[3+i*8+6] = (ang >> 16);
				cmd_buf[3+i*8+7] = (ang >> 24); 
			}
			
			{
				long val=0;
				val = g_sw_pub.ac_in[PUB_AC_IN_F1];
				cmd_buf[3+i*8+0] = val;
				cmd_buf[3+i*8+1] = (val >> 8);
				cmd_buf[3+i*8+2] = (val >> 16);
				cmd_buf[3+i*8+3] = (val >> 24);
			}	
			
			cmd_len = 8*(chn+1);
			cmd_len += 3;

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;
		case MS_BOARD_CALIBRATION:
		{	// 板卡校准系数上传
			
			int board;
			s32 factor;
			struct ac_slot_factor asf;

			board = buf[2];
			cmd_buf[2] = board;	

			if((board>=16)
					|| !(g_board_info[board].type== BOARD_TYPE_FTUKZ1
						||(g_board_info[board].type >= BOARD_TYPE_DFTU_KC00&&g_board_info[board].type<BOARD_TYPE_DFTU_KC00+BOARD_TYPE_KZ_NUM)
						|| g_board_info[board].type == BOARD_TYPE_AC)  //只有7到10板有零漂
					|| (g_board_info[board].type== BOARD_TYPE_FBDTU_MAIN)
					|| (g_board_info[board].type== BOARD_TYPE_FBDTU_MAIN1)			
			)  					
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_NSLOT;
				cmd_len = 3;
				break;
			}

			if (factor_read(board,&asf) != 0)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_OTHER;
				cmd_len = 3;
				break;
			}
			
			for(i=0;i<EQU_SLOT_AC_CHN;i++)
			{				
				factor = (s32)rt_round(asf.factor_e_c[i]*Q16_BASE);                      // 幅值系数
				cmd_buf[3+i*8+0] = factor; 
				cmd_buf[3+i*8+1] = (factor>>8);
				cmd_buf[3+i*8+2] = (factor>>16);
				cmd_buf[3+i*8+3] = (factor>>24);

				factor = (s32)rt_round(asf.factor_p_c[i]*Q16_BASE);                       // 角度系数
				cmd_buf[3+i*8+4] = factor; 
				cmd_buf[3+i*8+5] = (factor>>8);
				cmd_buf[3+i*8+6] = (factor>>16);
				cmd_buf[3+i*8+7] = (factor>>24);
			}

			cmd_len = 8*EQU_SLOT_AC_CHN;
			cmd_len += 3;
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;
		case MS_DEFAULT_CALIBRATION:
		{	// 恢复默认校准系数
			
			// 检查阶段
			if((g_maintain.state != MS_REQUEST) || (!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}

			factor_restore_default();

			log_str_time(LOG_OPERATE,"工具恢复默认校准系数",0,0);
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 2;
		}
		break;
		case MS_SAMPLE_CALIBRATION:
		{	// 整机采样校准		
			int ret;
			// 检查阶段
			if((g_maintain.state != MS_REQUEST) ||(!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}
			
			ret = sw_auto_adjust(-1);
			switch(ret)
			{
				case 0:
					cmd_buf[1] |= MAINTAIN_ACK;
					cmd_len = 2;
				break;
				
				case -1:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_DATAL;
					cmd_len = 3;
				break;
				
				case -2:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_CHXS;
					cmd_len = 3;
				break;
				
				case -3:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_ANGLEL;
					cmd_len = 3;
				break;
				
				case -4:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_ANGLEH;
					cmd_len = 3;
				break;
				
				case -5:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_ANGLEXS;
					cmd_len = 3;
				break;
				
				case -6:
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_XSSAVE;
					cmd_len = 3;
				break;
			}

			if (ret == 0)
			{
				log_str_time(LOG_OPERATE,"工具交流校准成功",0,0);
			}
			else
			{
				log_str_time(LOG_OPERATE,"工具交流校准失败",0,0);
			}
		}
		break;
		case MS_DEFAULT:
		{	// 恢复出厂设置			

			// 检查阶段
			if((g_maintain.state != MS_REQUEST) || ((!bMaintain)))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}

			init_default_equip_set(1);
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 2;
			log_str_time(LOG_OPERATE,"工具恢复出厂设置",0,0);
		}
		break;
		
		case MS_UZTEMP_MEASURE:
		{	// 直流电压温度刷新
			long val;
			
			for(i=PUB_AC_IN_UZ1;i<PUB_AC_NUM_ALL;i++)
			{
				val=g_sw_pub.ac_in[i];
				
				if(_AbsL(val)<g_unit[g_pub_ac_desc[i].unit].zero && pRunSet->bTT_RET_ZERO)
				{
					val=0;
				}					

				cmd_buf[2+(i-PUB_AC_IN_UZ1)*4] = val;
				cmd_buf[2+(i-PUB_AC_IN_UZ1)*4+1] = (val >> 8);
				cmd_buf[2+(i-PUB_AC_IN_UZ1)*4+2] = (val >> 16);
				cmd_buf[2+(i-PUB_AC_IN_UZ1)*4+3] = (val >> 24);
			}
			cmd_len = 4*3;
			cmd_len += 3;

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;

		case MS_ADJUST_UZL:
		{	// 直流校准			

			// 检查阶段
			if((g_maintain.state != MS_REQUEST) ||(!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}

			cmd_buf[2] = buf[2];
			if (cmd_buf[2] == 0x01)
			{
				sw_adjust_dc_0();
			}
			else if(cmd_buf[2] == 0x02)
			{
				sw_adjust_dc_1();
			}
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 2;

			log_str_time(LOG_OPERATE,"工具直流校准",0,0);
		}
		break;

		case MS_SAMPLE_TEST:
		{
			float val=0,base_v=-1.0,base_i=-1.0;
			u32 check_result[2]={0,0};
			float accuracy[6] = {0.1, -0.1, 0.2, -0.2, 0.01, -0.01};
			u8 sw;

			// 检查电压
			for(i=0;i<PUB_AC_NUM;i++)
			{	
				if(g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO)
				{
					continue;

				}

				// 确定基准
				if(base_v < 0)
				{
					val = ((float)g_ui[i].e/65536-100.0) / 100.0*100;
					if ((val < accuracy[0]) && (val > accuracy[1]))
					{
						base_v = 100.0;
					}
					else
					{
						val = ((float)g_ui[i].e/65536-57.735) / 57.735*100;
						if ((val < accuracy[0]) && (val > accuracy[1]))
						{
							base_v = 57.735;
						}
					}
				}

				// 检查精度
				val = ((float)g_ui[i].e/65536-base_v) / base_v*100;
				if ((val > accuracy[0]) || (val < accuracy[1]))
				{
					check_result[0] |= 0x01;	//电压超精度
				}
			}

			// 检查频率
			val = g_sw_pub.ac_in[PUB_AC_IN_F1];
			val = ((float)val/65536-50.0) / 100.0*100;
			if ((val > accuracy[4]) || (val < accuracy[5]))
			{
				check_result[0] |= 0x02;	//频率超精度
			}
			
			for (sw=0; sw<g_sw_num; sw++)
			{
				float dat=0;
				int cnt;
				
				// 检查电流
				cnt = 0;
				for(i=0;i<SW_AC_NUM;i++)
				{				
					if(g_ui[UI_SW_INDEX(sw,i)].chn_index == CFG_ADC_CHANNEL_ZERO)
					{
						cnt++;
						continue;
					}

					// 确定基准
					if(base_i < 0)
					{
					val = ((float)g_ui[UI_SW_INDEX(sw,i)].e/65536-5.0) / 5.0*100;
						if ((val < accuracy[0]) && (val > accuracy[1]))
						{
							base_i = 5.0;
						}
						else
						{
							val = ((float)g_ui[UI_SW_INDEX(sw,i)].e/65536-3.0) / 3.0*100;
							if ((val < accuracy[0]) && (val > accuracy[1]))
							{
								base_i = 3.0;
							}
						}

						rt_printf("base_i=%f.\r\n",base_i);
					}
				
					val = ((float)g_ui[UI_SW_INDEX(sw,i)].e/65536-base_i) / base_i*100;
					if ((val > accuracy[0]) || (val < accuracy[1]))
					{
						// 0x01，开关电流超精度
						check_result[1] |= 0x01<<(sw*2);
						break;
					}
				}

				// 整个开关没有配置，置0x03标志
				if(cnt == SW_AC_NUM)
				{
					check_result[1] |= 0x03<<(sw*2);
					continue;
				}
				
				// 如果精度有问题，不再检测P、Q.
				if(i != SW_AC_NUM)
				{
					continue;
				}

				// 开始检查功率
				dat = base_v*base_i*3;
				if(g_ui[PUB_AC_UA1].chn_index == CFG_ADC_CHANNEL_ZERO)
				{
					// 二表法
					dat /= 1.732;
				}
				// 检查P
				val = ((float)g_sw[sw].ac_in[SW_AC_IN_P]/65536-dat) / dat*100;
				if ((val > accuracy[2]) || (val < accuracy[3]))
				{
					// 0x02，开关功率超精度
					check_result[1] |= 0x02<<(sw*2);	
				}

				// 检查Q
				val = ((float)g_sw[sw].ac_in[SW_AC_IN_Q]/65536-0.0) / dat*100;
				if ((val > accuracy[2]) || (val < accuracy[3]))
				{
					// 0x02，开关功率超精度
					check_result[1] |= 0x02<<(sw*2);	
				}
			}
			
			cmd_buf[2+0] = check_result[0];
			cmd_buf[2+1] = (check_result[0] >> 8);
			cmd_buf[2+2] = (check_result[0] >> 16);
			cmd_buf[2+3] = (check_result[0] >> 24);

			cmd_buf[2+4] = check_result[1];
			cmd_buf[2+5] = (check_result[1] >> 8);
			cmd_buf[2+6] = (check_result[1] >> 16);
			cmd_buf[2+7] = (check_result[1] >> 24);

			cmd_len = 10;

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;

		case MS_KRKC_TEST:
		{	// 开入开出自动测试			
			extern struct rt_stat 	g_stat_do_delay;
			extern struct rt_stat 	g_stat_di_delay;

			u8 buf_test[24];

			// 检查阶段
			if((g_maintain.state != MS_REQUEST) || (!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}

			memset(buf_test,0,sizeof(buf_test));
			memcpy(buf_test,buf+3,buf[2]*2);
			dido_auto_test(buf_test,buf[2]);

			cmd_buf[2] = 0;
			if (g_stat_do_delay.max > 1000000)
			{
				cmd_buf[2] |= 0x01;
			}

			if (g_stat_di_delay.max > (5000000+20000000))
			{
				cmd_buf[2] |= 0x02;
			}
			
			cmd_buf[3] = 0;
			cmd_buf[4] = 0;
			cmd_buf[5] = 0;
			cmd_buf[6] = buf[2];

			memcpy(cmd_buf+7,dido_buf,42);

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = buf[2]*14 + 4 + 3;
		}
		break;
		
		case MS_LCD_TEST:
		{	// LCD测试			

			// 检查阶段
			if((g_maintain.state != MS_REQUEST) ||(!bMaintain))
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_PHASE;
				cmd_len = 3;
				break;
			}

			add_led_test(TEST_LED);
			add_led_test(TEST_LCD);
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 2;
		}
		break;

		case MS_RESET_TEST:
		{
			//复位
			cmd_buf[2] = buf[2];
			switch (cmd_buf[2])
			{
				case 0x1:
					rt_printf("装置复位\r\n");
					watchdog_reset_cpu(2);	//装置复位
				break;

				case 0x2:
					rt_printf("子板复位\r\n");
				break;

				case 0x4:
					rt_printf("应用复位\r\n");
					//env_restart();		//主板复位
					watchdog_reset_cpu(2);	//装置复位
				break;
			}
				
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 2;
		}
		break;

		case MS_CFGINF:
		{
			// 配置信息查看
			cmd_buf[2] = 6;
			sprintf(cmd_buf+3+24*0,"装置资源文件:%04XH",g_crc_rsc);
			sprintf(cmd_buf+3+24*1,"板卡资源文件:%04XH",g_crc_brd_res);
			sprintf(cmd_buf+3+24*2,"通道配置文件:%04XH",g_crc_equ_cfg);
			sprintf(cmd_buf+3+24*3,"转发点表文件:%04XH",g_crc_rectable);
			sprintf(cmd_buf+3+24*4,"定值描述文件:%04XH",g_crc_set_desc);
			sprintf(cmd_buf+3+24*5,"定值数据文件:%04XH",g_crc_set_data);

			cmd_len = 3 + 24*6;			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;	

		case MS_ERRINF:
		{
			// 故障信息查看
			u8 num=0;
			if(rt_err_count())
			{
				cmd_buf[2] = rt_err_count();
				for (i=0; i<ERR_CODE_NUM; i++)
				{
					if (rt_err_test(i))
					{
						num++;
						if (num > 9)
						{
							break;
						}
						sprintf(cmd_buf+3+(num-1)*20,rt_err_msg(i));						
					}
				}							
			}
			else
			{
				cmd_buf[2] = 0;
			}
			cmd_len = 3 + 20*10;
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;	

		case MS_GETIP:
		{
			// 获取网口及对应IP
			int net;
			char ipbuf[32];

			cmd_buf[2] = 0;
			for(net=0; net<g_net_num; net++)
			{
				// 如果接口不正常，不初始化
				if(rt_if_ip_get(net,ipbuf) != 0)
				{
					cmd_buf[3+net*5] = 0;
					continue;

				}
			
				cmd_buf[2] = net+1;
				cmd_buf[3+net*5] = 1;
				Swap_32(ipbuf);
				memcpy(cmd_buf+4+net*5,ipbuf, 4);	
			}

			cmd_len = 3 + 5*IEC104_TOTAL_SOCKETS;
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;
		
		case MS_GET_GPRS_INFO:
		{
			int i,num;
			
			cmd_buf[2] = buf[2];
			if(cmd_buf[2] == 1)
			{
				// 发送查询子命令
				IEC101_PH_GprsInfo();
				cmd_buf[1] |= MAINTAIN_ACK;
				cmd_len = 3;
			}
			else if(cmd_buf[2] == 2)
			{
				// 接收查询子命令1
				gprs_get_info();

				num = g_gprs_info_num<10 ?  g_gprs_info_num : 10;
				cmd_buf[3] = num;
				for(i=0; i<num; i++)
				{
					strcpy(cmd_buf+ 4 + i*20,strGprsInf[i]);
				}

				cmd_buf[1] |= MAINTAIN_ACK;
				cmd_len = 4 + num*20;
			}
			else if(cmd_buf[2] == 3)
			{
				//接收查询子命令2
				num = g_gprs_info_num<10 ?  0 : (g_gprs_info_num -10);
				cmd_buf[3] = num;
				for(i=0; i<num; i++)
				{
					strcpy(cmd_buf+ 4 + i*20,strGprsInf[i+10]);
				}

				cmd_buf[1] |= MAINTAIN_ACK;
				cmd_len = 4 + num*20;
			}
			else
			{
				// 不支持的子命令
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[3] = MAINTAIN_ERR_OTHER;
				cmd_len = 4;
			}
		}
		break;

		case MS_FZXS_UD:
		{
			int board;
			s32 factor;
			
			struct ac_slot_factor asf;

			cmd_buf[2] = buf[2];
			board = buf[3];
			cmd_buf[3] = board;
			if((board>=16)
					|| !(g_board_info[board].type== BOARD_TYPE_FTUKZ1
						||(g_board_info[board].type >= BOARD_TYPE_DFTU_KC00&&g_board_info[board].type<BOARD_TYPE_DFTU_KC00+BOARD_TYPE_KZ_NUM)
						|| g_board_info[board].type == BOARD_TYPE_AC)  //只有7到10板有零漂
					|| (g_board_info[board].type== BOARD_TYPE_FBDTU_MAIN)
					|| (g_board_info[board].type== BOARD_TYPE_FBDTU_MAIN1)			
			)  
					
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[4] = MAINTAIN_ERR_NSLOT;
				cmd_len = 5;
				break;
			}			

			if (factor_read(board,&asf) != 0)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[4] = MAINTAIN_ERR_OTHER;
				cmd_len = 5;
				break;
			}

			if(cmd_buf[2] == 1)		//上传
			{				
				for(i=0;i<EQU_SLOT_AC_CHN;i++)
				{					
					factor = (s32)rt_round(asf.factor_e_c[i]*Q16_BASE);                      // 幅值系数
					cmd_buf[4+i*8+0] = factor; 
					cmd_buf[4+i*8+1] = (factor>>8);
					cmd_buf[4+i*8+2] = (factor>>16);
					cmd_buf[4+i*8+3] = (factor>>24);

					factor = (s32)rt_round(asf.factor_p_c[i]*Q16_BASE);                      // 角度系数
					cmd_buf[4+i*8+4] = factor; 
					cmd_buf[4+i*8+5] = (factor>>8);
					cmd_buf[4+i*8+6] = (factor>>16);
					cmd_buf[4+i*8+7] = (factor>>24);
				}

				cmd_len = 8*EQU_SLOT_AC_CHN;
				cmd_len += 4;	
			}
			else if(cmd_buf[2] == 2)//下载
			{
				union

				{
					float ff;
					u8 bb[4];					
				}ff;
				for(i=0;i<EQU_SLOT_AC_CHN;i++)
				{				
					CopySwap(ff.bb,&buf[4+i*8+0],4,false);
					asf.factor_e_c[i] = ff.ff / Q16_BASE;
					
					CopySwap(ff.bb,&buf[4+i*8+4],4,false);
					asf.factor_p_c[i] = ff.ff / Q16_BASE;
				}
				if (factor_write_board(board, &asf) != 0)
				{
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[4] = MAINTAIN_ERR_OTHER;
					cmd_len = 5;
					break;				
				}
				cmd_len = 4;	

			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;

		case MS_AC_CFG:
		{
			int i,j;
			cmd_buf[2] = buf[2];

			for(i=0; i<AC_TEST_BOARD_NUM; i++)
			{
				if(g_ac_test_board[i].type == cmd_buf[2])
				{
					break;
				}
			}

			if (i == AC_TEST_BOARD_NUM)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[4] = MAINTAIN_ERR_NSLOT;
				cmd_len = 5;
				break;
			}
			else
			{
				char name[10]; 
				for (j=0; j<g_ac_test_board[i].num; j++)
				{
					strncpy(name,g_ac_test_board[i].data[j].name,4);
					memcpy(&cmd_buf[3+8*j+0], name, 4);
					cmd_buf[3+8*j+4] = g_ac_test_board[i].data[j].normal_data;
					cmd_buf[3+8*j+5] = g_ac_test_board[i].data[j].normal_data>>8;
					cmd_buf[3+8*j+6] = g_ac_test_board[i].data[j].normal_angle;
					cmd_buf[3+8*j+7] = g_ac_test_board[i].data[j].normal_angle>>8;					
				}
			}
			cmd_len = 8*g_ac_test_board[i].num;
			cmd_len += 4;
		}
		break;

		case MS_DC_FACTOR:
		{
			s32 factor;
			u8 *p;
			
			cmd_buf[2] = buf[2];
			cmd_len = 3;
			
			if(cmd_buf[2] == 1)		//上传
			{
				
				for(i=0; i<DC_NUM; i++)
				{					
					factor = (s32)rt_round(g_dcfactor_save[i].dc_h * Q16_BASE);     // 直流H系数
					cmd_buf[3+i*8+0] = factor; 
					cmd_buf[3+i*8+1] = (factor>>8);
					cmd_buf[3+i*8+2] = (factor>>16);
					cmd_buf[3+i*8+3] = (factor>>24);

					factor = (s32)rt_round(g_dcfactor_save[i].dc_l * Q16_BASE); 	// 直流L系数
					cmd_buf[3+i*8+4] = factor; 
					cmd_buf[3+i*8+5] = (factor>>8);
					cmd_buf[3+i*8+6] = (factor>>16);
					cmd_buf[3+i*8+7] = (factor>>24);
				}

				cmd_buf[3+DC_NUM*8+0] = g_dcfactor_save[0].adjust_set;
				cmd_buf[3+DC_NUM*8+1] = g_dcfactor_save[1].adjust_set;

				memcpy (&cmd_buf[3+DC_NUM*8+2], g_auth_id, 8);		//装置flash_id
				memcpy (&cmd_buf[3+DC_NUM*8+2+8], g_dcfactor_id, 8);	//存储flash_id

				// 上传校准温度
				p = (u8*)&g_dc_temp;
				cmd_buf[3+DC_NUM*8+2+16] = p[3]; 
				cmd_buf[3+DC_NUM*8+2+17] = p[2];
				cmd_buf[3+DC_NUM*8+2+18] = p[1];
				cmd_buf[3+DC_NUM*8+2+19] = p[0];
				
				cmd_len = 8*2 + 2 + 8*2 + 4;
				cmd_len += 3;
				cmd_buf[1] |= MAINTAIN_ACK;
				break;
			}
			else if(cmd_buf[2] == 2)//下载
			{
				union
				{
					float ff;
					u8 bb[4];					
				}ff;
				float dc_h, dc_l;
				u8 id[8];
				struct dc_factor_save factor[2];

				memcpy(factor, g_dcfactor_save, sizeof(g_dcfactor_save));
				for(i=0; i<DC_NUM; i++)
				{					
					CopySwap(ff.bb,&buf[3+i*8+0],4,false);
					dc_h = ff.ff / Q16_BASE;

					CopySwap(ff.bb,&buf[3+i*8+4],4,false);
					dc_l = ff.ff / Q16_BASE;

					if (factor[i].dc_h != dc_h)
					{
						factor[i].dc_h = dc_h;
						factor[i].adjust_set = DC_SETDATA;
					}
					if (factor[i].dc_l!= dc_l)
					{
						factor[i].dc_l = dc_l;
						factor[i].adjust_set = DC_SETDATA;
					}
				}
				memcpy(id, g_auth_id, 8);
				if(dcfactor_createfile(&id[0], (u8 *)&factor) != 0)
				{
					rt_printf("直流系数文件保存失败.\r\n");
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[3] = MAINTAIN_ERR_OTHER;
					cmd_len = 4;
					break;
				}
				
				log_str_time(LOG_OPERATE,"工具直流系数修改",0,0);
				
				cmd_len = 3;
				cmd_buf[1] |= MAINTAIN_ACK;
				break;
				
			}
			else if(cmd_buf[2] == 3) // 恢复默认值
			{
				
				if(dcfactor_restore_default() != 0)
				{

					rt_printf("直流系数恢复默认值失败.\r\n");
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[3] = MAINTAIN_ERR_OTHER;
					cmd_len = 4;
					break;
				}
				cmd_len = 3;
				cmd_buf[1] |= MAINTAIN_ACK;
				break;
			}
			
			// 不支持的直流系数命令
			rt_printf("不支持的直流系数命令:cmd_buf[2]=%d.\r\n",cmd_buf[2]);
			cmd_buf[1] |= MAINTAIN_NAK;
			cmd_buf[3] = MAINTAIN_ERR_OTHER;
			break;
		}
		break;
		case MS_WAVE_OK:
		{	
			if (rcd_check_ok(SWITCH_NUM_MAX) != 1)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_OTHER;
				cmd_len = 3;
				break;
			}
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 2;
		}
		break;

		case MS_FILE_ISUPDATE:
		{
			int file_index=0; 
			u32 file_time=0;
			u16 file_type=0;

			// 复制文件名
			memcpy(cmd_buf+2,buf+2,20); 

			// 检查文件名
			file_index = file_check(buf+2, ATTR_UP);
			
			if(file_index < 0)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[22] = MAINTAIN_ERR_NAME;
				cmd_len = 23;	
				break;
			}

			// 获取文件当前时间
			file_time = file_change_time(file_index);
			if ((short)file_time == -1)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[22] = MAINTAIN_ERR_NAME;
				cmd_len = 23;	
				break;
			}			

			// 如果是首次上传,暂存文件时间
			if (buf[22])
			{		
				g_file_time[file_index].st_mtime = file_time;
				if (file_type == FILETYPE_LOG_APP)
				{
					file_index = log_file_check(buf+2);
					g_logfile_update[file_index] = 0;
				}
				cmd_buf[22] = 0;
			}
			else
			{	
				// 非首次上传，比对文件时间，并上传文件是否修改状态
				cmd_buf[22] = 0;
				if(g_file_time[file_index].st_mtime != file_time)
				{
					cmd_buf[22] = 1;
				}
				else if (file_type == FILETYPE_LOG_APP)
				{
					file_index = log_file_check(buf+2);
					if(g_logfile_update[file_index])
					{
						cmd_buf[22] = 1;
					}
				}				
			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 23;
		}
		break;

		case MS_COMM_TEST:
		{	
			u8 j;
			
			// 启动测试
			uart_test_begin = 1;

			// 串口测试
			uart_232_485_test(&buf[2]);

			// 停止测试
			uart_test_begin = 0;

			memset(&cmd_buf[2], 0, 6);

			// RS232_1, RS232_2
			cmd_buf[2] = 0x7;
			for (j=0; j<2; j++)
			{
				if (uart_test_flag[j][0])
				{
					cmd_buf[3] |= 0x1<<j;
				}
				if (uart_test_flag[j][1])
				{
					cmd_buf[4] |= 0x1<<j;
				}
			}			
			cmd_buf[3] |= 0x1<<2;  // 串口3 自动满足
			cmd_buf[4] |= 0x1<<2;

			// RS485_1,RS485_2,RS485_3
			cmd_buf[5] = 0x7;			
			for (j=0; j<3; j++)
			{
				if (uart_test_flag[j+3][0])
				{
					cmd_buf[6] |= 0x1<<j;
				}
				if (uart_test_flag[j+3][1])
				{
					cmd_buf[7] |= 0x1<<j;
				}
			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 8;
		}
		break;

		case MS_INSTU:
		{		
			int i;
			u32 data;

			cmd_buf[2] = INSTU_NUM;
			for(i=0; i<INSTU_NUM; i++)
			{						
				data = *g_instu_desc[i].fstdata;
				cmd_buf[3+i*4] =  data;
				cmd_buf[4+i*4] = (data >> 8);
				cmd_buf[5+i*4] = (data >> 16);
				cmd_buf[6+i*4] = (data >> 24); 
			}

			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = INSTU_NUM*4 + 3;
		}
		break;

		case MS_RCD_NAME:
		{		
			static char name[9*64];
			int i=0, j;
			struct stat s;	
			static int sum=0, num=0, cur=0;
			// 首次查询
			if (buf[2] == 0)
			{
				memset (name, 0, 9*64);
				
				//检查文件是否存在
				if(sys_newstat("/tmp/rec_wave.dat",&s)==0)
				{
					memcpy(name, "/tmp/rec_wave.dat", strlen("/tmp/rec_wave.dat"));
					i=1;
				}
				num = rcd_get_list_name();
				if(num > 8)
				{
				 	num = 8;
				}

				for (j=0; j<num; j++)
				{
					memcpy(&name[(i+j)*64], "/app/data/rec_wave/", strlen("/app/data/rec_wave/"));
					memcpy(&name[(i+j)*64+strlen("/app/data/rec_wave/")], wave_name[j],35);
				}

				if (num)
				{
					num += i;
					sum = num;
				}
				else
				{
					num = 0;
					sum = i;
				}
				cur=0;
			}
			else
			{
				cur+=3;
			}

			// 总条数
			cmd_buf[2] = sum;

			if (num > 3)
			{
				cmd_buf[3] = 1;
				memcpy(cmd_buf+4, &name[cur*64], 3*64);
				num -= 3;
				cmd_len += 3*64;
			}
			else
			{
				cmd_buf[3] = 0;
				memcpy(cmd_buf+4, &name[cur*64], (sum-cur)*64);
				cmd_len += (sum-cur)*64;
			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len += 4;
		}
		break;


		case MS_RMT_PAIR:
		{	// 遥控器配对	
		
			memcpy(cmd_buf+2,buf+2,2); 
			
			if (cmd_buf[2])
			{
				add_rmt_pair(RMT_PAIR);
				log_str_time(LOG_OPERATE,"工具遥控器配对",0,0);
			}
			if (cmd_buf[3])
			{
				add_rmt_pair(RMT_CLRPAIR);
				log_str_time(LOG_OPERATE,"工具遥控器配对清除",0,0);
			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 4;
		}
		break;
		case MS_SET_MTPWD:
		{
			// 设置密码
			u8 pwd[16];
			int i, check=0, str=0, data=0;

			// 此处需将密码解密
			for (i=0; i<16; i++)
			{
				pwd[i] = ~buf[2+i];
			}

			// 校验旧密码
			check = memcmp(pwd, mt_pwd,16);
			if (check != 0)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_OCODE;	
				cmd_len = 3;
				// break;
			}

			// 此处需将密码解密
			for (i=0; i<16; i++)
			{
				pwd[i] = ~buf[18+i];
			}

			// 校验新密码是否符合规则
			for (i=0; i<16; i++)
			{
				// 密码中有数字
				if ((pwd[i] >= 0x30) && (pwd[i] < 0x3A))
				{
					data = 1;
				}
				else
				{
					str = 1;
				}
			}

			if (!data || !str)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_NCODE;	//新密码无效
				cmd_len = 3;
				break;			
			}

			// 更新密码
			memcpy (&mt_pwd, pwd, 16);	

			// 保存加密后的新密码
			_maintain_pwd_createfile(&buf[18]);
			
			log_str_time(LOG_OPERATE,"工具设置维护工具密码",0,0);
		
			memcpy(cmd_buf+2,buf+2,32);		
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 34;
		}
		break;

		case MS_PASSWORD:
			// 不支持旧密码认证，直接否定确认
			cmd_buf[1] |= MAINTAIN_NAK;
			cmd_buf[2] = MAINTAIN_ERR_CODE;	
			cmd_len = 3;
		break;
		
		case MS_MT_PWD:
		{
			int i, check=0;
			u8 pwd[16];

			// 此处需将密码解密
			for (i=0; i<16; i++)
			{
				pwd[i] = ~buf[2+i];
			}

			check = memcmp(pwd,mt_pwd,16);
			if (check != 0)
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_CODE;	
				cmd_len = 3;
				//print_mem("pwd0:",mt_pwd,16);
				//print_mem("pwd1:",pwd,16);
				break;
			}

			// 密码校验通过，打开相关的维护端口
			{
				char log[128];
				sprintf(log,"%s登录!", &buf[2+16]);
				log_str_time(LOG_OPERATE,log,0,0);
				rt_printf("%s\r\n",log);
			}

			if(g_mt_rs232 == 0)
			{
				net_debug_init();
				open_inet_port();
			}
			
			memcpy(cmd_buf+2,buf+2,16);		
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 18;
		}
		break;

		case MS_CLOSE_PORT:
		{
			// 关闭端口服务，仅保留6008维护端口	
			net_debug_exit();
			close_inet_port();

			rt_printf("网络维护端口关闭.\r\n");
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 2;
		}
		break;
	
		case MS_AUTH:
		{
			cmd_buf[2] = buf[2];
			
			// 上传ID
			if(cmd_buf[2] == 1) 
			{
				auth_get_encrypt_id(&cmd_buf[3],32);	
				print_mem("     id:",&cmd_buf[3],24);
				cmd_len = 3 + 32;
			}
			// 下载license
			else if(cmd_buf[2] == 2)
			{
				auth_save(&buf[3],AUTH_LICENSE_LEN);
				cmd_len = 3;
			}
			// 从授权机获取授权
			else if(cmd_buf[2] == 3)
			{
				int ret;
				ret = auth_license(&buf[3],(struct rtc_time_t *)&buf[3+32],&cmd_buf[3]);
				if(ret != 0)
				{	
					rt_printf("auth_license error:ret=%d.\r\n",ret);
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_OTHER;	
					cmd_len = 3;
					break;
				}
				cmd_len = 3 + AUTH_LICENSE_LEN;
			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;
		
		case MS_YD_REFRESH:
		{
			u16 begin,num;

			// 将子命令和开始值复制到返回命令中
			memcpy(&cmd_buf[2],&buf[2],3);

			// 得到开始值和个数
			Swap_16_memcpy((BYTE*)&begin,&buf[3]);	// modify for am335x  xxxxxx 
			Swap_16_memcpy((BYTE*)&num,&buf[5]);		// modify for am335x  xxxxxx 
			// 遥信
			if(cmd_buf[2] == 1) 
			{
				num = tbl_yd_yx(begin,num,cmd_buf+7);
				if(num > 0)
				{
					Swap_16_memcpy(&cmd_buf[5],(BYTE*)&num);	// modify for am335x  xxxxxx 
					cmd_len = 3 + 4 + (num+3)/4;
				}
				else
				{
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_OTHER;	
					cmd_len = 3;
					break;
				}	
			}
			// 遥测
			else if(cmd_buf[2] == 2)
			{
				num = tbl_yd_yc(begin,num,cmd_buf+7);
				if(num > 0)
				{
					Swap_16_memcpy(&cmd_buf[5],(BYTE*)&num);	// modify for am335x  xxxxxx 
					cmd_len = 3 + 4 + num*9;
				}
				else
				{
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_OTHER;	
					cmd_len = 3;
					break;
				}	
			}
			// 电度
			else if(cmd_buf[2] == 3)
			{
				num = tbl_yd_dd(begin,num,cmd_buf+7);
				if(num > 0)
				{
					Swap_16_memcpy(&cmd_buf[5],(BYTE*)&num);	// modify for am335x  xxxxxx 
					cmd_len = 3 + 4 + num*9;
				}
				else
				{
					cmd_buf[1] |= MAINTAIN_NAK;
					cmd_buf[2] = MAINTAIN_ERR_OTHER;	
					cmd_len = 3;
					break;
				}	
			}
			else
			{
				cmd_buf[1] |= MAINTAIN_NAK;
				cmd_buf[2] = MAINTAIN_ERR_OTHER;	
				cmd_len = 3;
				break;
			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;
		
		case MS_FACTORY_SETUP:
		{
			u8 mac[6];
			
			cmd_buf[2] = buf[2];
			
			// 装置ID码
			if(buf[2] == 1) 
			{
				if(strlen(&buf[3]) == 24) 
				{
					env_setenv("pid", &buf[3]); 
					rt_printf("pid=%s\r\n",&buf[3]);
					cmd_len = 3;
				}
				else
				{
					cmd_buf[3] = MAINTAIN_ERR_FORMAT;
					cmd_len = 4;
					cmd_buf[1] |= MAINTAIN_NAK;
					break;
				}
			}
			// 网络1MAC
			else if(buf[2] == 2)
			{
				if(rt_if_sz2mac(&buf[3],mac) == 0)
				{
					env_setenv("net1mac", &buf[3]); 
					rt_printf("net1mac=%s\r\n",&buf[3]);
					cmd_len = 3;
				}
				else
				{
					cmd_buf[3] = MAINTAIN_ERR_FORMAT;
					cmd_len = 4;
					cmd_buf[1] |= MAINTAIN_NAK;
					break;
				}
			}
			// 网络2MAC
			else if(buf[2] == 3)
			{
				if(rt_if_sz2mac(&buf[3],mac) == 0)
				{
					env_setenv("net2mac", &buf[3]); 
					rt_printf("net2mac=%s\r\n",&buf[3]);
					cmd_len = 3;
				}
				else
				{
					cmd_buf[3] = MAINTAIN_ERR_FORMAT;
					cmd_len = 4;
					cmd_buf[1] |= MAINTAIN_NAK;
					break;
				}
			}
			
			// 发送ACK
			cmd_buf[1] |= MAINTAIN_ACK;
		}
		break;

#if defined(CPU_AM335X) 
		case MS_APP_BAK_START:

			rt_printf("maintain: 启动app分区备份.\r\n");

			//下面备份工作需要大约5秒，耗时有点长，先喂狗
			watchdog_feed_mainloop();

			//1. 删除临时文件/tmp/backup_flag
			rt_file_del("/tmp/backup_flag");

			//2. 调用启动备份脚本（函数）	
			call_usermodehelper("/usr/sbin/app_backup.sh",  cmd_ls,  NULL,  UMH_WAIT_PROC);	

			watchdog_feed_mainloop();

			//3. 回复
			cmd_buf[1] |= MAINTAIN_ACK;
			cmd_len = 2;
		break;

		case MS_APP_BAK_RESULT:

			//1. 检测临时文件/tmp/backup_flag是否存在？
			// 打开文件
			pfile = rt_file_open("/tmp/backup_flag",O_RDONLY ,0);
			if(IS_ERR(pfile))
			{
				rt_printf("maintain: 临时文件/tmp/backup_flag不存在.\r\n");
				
				//1.1 不存在
				cmd_buf[1] |= MAINTAIN_ACK;
				cmd_buf[2] = 2;//备份中
				cmd_len = 3;

				break;

			}
			
			// 得到文件长度
			rt_file_llseek(pfile,0,SEEK_END);
			llen = pfile->f_pos;
			rt_file_llseek(pfile,0,SEEK_SET);
			
			// 分配内存
			lbuf = rt_malloc(llen);
			if((lbuf) == NULL)
			{
				rt_file_close(pfile,0);
				break;	
			}
			
			// 读出内容
			pos = 0;
			if(rt_file_read(pfile,lbuf,llen,&pos) != llen)
			{
				rt_file_close(pfile,0);
				rt_free(lbuf);
				break;
			}
			
			// 关闭文件
			rt_file_close(pfile,0);
			
			result = lbuf[0];
			rt_free(lbuf);

				//1.2 存在
			if(result == '1')
			{
				rt_printf("maintain: app分区备份成功.\r\n");
				
				//2 读取文件/tmp/backup_flag内容，成功值是1，备份失败值是 0
				//成功
				cmd_buf[1] |= MAINTAIN_ACK;
				cmd_buf[2] = 1;//成功
				cmd_len = 3;
			}
			else
			{
				rt_printf("maintain: app分区备份失败.\r\n");
				
				//失败
				cmd_buf[1] |= MAINTAIN_ACK;
				cmd_buf[2] = 0;//失败
				cmd_len = 3;
			}
		break;
#endif	
	
		default:
			rt_printf("Maintain_Manage:不支持的命令(%d)\r\n",buf[1]);
			_maintain_state_reset();
			cmd_buf[1] |= MAINTAIN_NAK;
			cmd_buf[2] = MAINTAIN_ERR_CMD;
			cmd_len = 3;
		break;
	}
	return cmd_len;
}

void Maintain_uart_send(void)
{
	struct maintain_def *pt = &g_mtbuf;
	int len;
	u8 buf_tx[256];	

	memset(buf_tx,0,sizeof(buf_tx));
	pt->bData = false;
	len = pt->recvbuf[1] + 6;  //68 L L 68 + data + crc + END
	
	memcpy(buf_tx,pt->recvbuf,len-1);
	
	buf_tx[len] = 0x80;
	buf_tx[len] |= (PDA_BOARD<<3);
	buf_tx[len] |= MAIN_BOARD;
	
	Add_Uart_Frame(PDA_BOARD,len,buf_tx);
}

void Maintain_Board_Recv(int len,BYTE *para)	
{
	struct maintain_def *pt = &g_mtbuf;
	if(pt->bData)
	{
		_maintain_recv_rst(pt);
		return;
	}
	pt->nRecvLenth = len;
	memcpy(pt->recvbuf,para,len);
	pt->bData=true;
	pt->hmi_mode=true;
	//print_mem("PCRX:",g_mtbuf.recvbuf,len);
	mainloop_wakeup();
	
}

/**************************************************************************
函数名称：_maintain_recv
函数版本：1.00 
作者：   
创建日期：2013.03.29     
函数功能说明：6008端口数据接受判断，只判断是否满足报文格式
输入参数：
输出参数：有完整帧接受，返回1，否则返回 0
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
void Maintain_Recv(u8 byRevData) 
{
	struct maintain_def *pt = &g_mtbuf;
	pt->recvbuf[pt->nRecvCounter++]=byRevData;
//	pt->dTRecvPiece=dTCounter;   //接收字符时的时刻，在大循环中判断，是否需要复归
	switch(pt->nTypeCounter)
	{
		case 0:
			if(byRevData==0x68)
			{
				pt->nTypeCounter=1;
			}
			else if(byRevData==0x10)
			{
				pt->nTypeCounter=4;
				pt->nRecvLenth=2;
			}			
			else
			{
				_maintain_recv_rst(pt);
			}
		break;
		
		case 1:
			pt->nTypeCounter=2;
			pt->nRecvLenth=byRevData;			//长帧长度
			if(pt->nRecvLenth>IEC101_RECVBUF_MAX)
			{
				_maintain_recv_rst(pt);
			}
		break;
		
		case 2:
			if(pt->nRecvLenth==byRevData)
			{
				pt->nTypeCounter=3;
			}
			else
			{
				_maintain_recv_rst(pt);
			}
		break;
		
		case 3:
			if(byRevData==0x68)
			{
				pt->nTypeCounter=4;
			}
			else
			{
				_maintain_recv_rst(pt);
			}
		break;
		
		case 4:  //控制域
			pt->sum=byRevData;
			pt->nTypeCounter=5;
		break;
		
		case 5: //目标地址
			pt->sum+=byRevData;
			pt->nRecvCnt=0;
			pt->nTypeCounter=6;
			if(pt->nRecvLenth==2)//短帧 
				pt->nTypeCounter=7;
		break;
		
		case 6:	 //有效数据			//有效数据
			if(++pt->nRecvCnt>=pt->nRecvLenth-2)
			{
				pt->nTypeCounter=7;
			}
			pt->sum+=byRevData;
		break;
		
		case 7:		 //校验和	
			pt->recvsum=byRevData;
			pt->nTypeCounter=8;				
		break;
		
		case 8:  //结束符
			_maintain_recv_rst(pt);
			if(byRevData==0x16)	//校验结束字符,报文接收完毕，
			{
				if(pt->sum!=pt->recvsum)
				{
					return;
				}				
				else
				{
					pt->bData=true;
					// 唤醒主循环
					mainloop_wakeup();
				}
				return ;
			}
		break;
		
		default:   
			_maintain_recv_rst(pt);
		break;
	}	//类型校验结束			

	return ;	
}

/******************************************************************************
函数名称：	filelist_getlen
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-2-13
函数说明：	获取文件列表长度
参数说明：	
						fname:文件列表名
返回值：  	文件列表长度
修改记录：	
*/
static unsigned int filelist_getlen(struct file_item *file_list)
{
	int len = 0;
	int i = 0;
	int fd = 0;
	char file_name[64];	
 
 	//遍历文件列表
	for(i=0;i<FILE_LIST_NUM;i++)
	{
		memset(file_name, 0, 64);
		// 组合文件路径和文件名
		sprintf(file_name,"%s%s",file_list[i].file_dir,file_list[i].file_name);
		
		//打开文件
		fd = sys_open(file_name, O_RDONLY, 0);
		//打不开表示文件不存在
		if(fd < 0) continue;
		//计算长度
		len += strlen(file_name) + 2;	
		//关闭文件
		sys_close(fd);	
	}

	return len;	
		
}

/******************************************************************************
函数名称：	filelist_memcpy
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-2-13
函数说明：	拷贝文件列表内容到目的地址
参数说明：	
						dst: 目的地址
						fname:文件列表名
返回值：  	文件列表长度
修改记录：	
*/
static void filelist_memcpy(char *dst, struct file_item *file_list)
{
	int len = 0;
	int i = 0;
	int fd = 0;
	char file_name[64];	

	//遍历文件列表
	for(i=0; i<FILE_LIST_NUM; i++)
	{
		memset(file_name, 0, 64);
		// 组合文件路径和文件名
		sprintf(file_name,"%s%s",file_list[i].file_dir,file_list[i].file_name);
		
		// 在系统中打开对应文件
		fd = sys_open(file_name, O_RDONLY, 0);
		// 打不开表示文件不存在
		if(fd < 0) continue;

		// 如果文件不需要放入文件列表，关闭文件并退出
		if ((file_list[i].file_attr & ATTR_UP) == 0)
		{
			sys_close(fd);	
			continue;
		}

		if((strcmp(file_name, file_list[i].file_dir)==0)
			&& (strlen(file_name) == strlen(file_list[i].file_dir)))
		{
			continue;
		}
		
		// 文件名拷贝，并添加回车
		len = strlen(file_name);
		memcpy(dst, file_name, len);
		dst = dst + len;	
		memcpy(dst, "\r\n", 2);			
		dst = dst + 2;

		// 关闭文件
		sys_close(fd);	
	}				
}

/******************************************************************************
函数名称：	filelist_createfile
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	创建文件列表
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int filelist_createfile(void)
{
	unsigned int addr,file_length;
	u16 crc;
	char *p;
	loff_t pos;
	struct file * pfile;
	struct cfg_file_head	filelist_file;
		
	// 写文件头
	memset(&filelist_file,0,sizeof(filelist_file));
	filelist_file.signature = SIG_FILELIST_FILE;
	filelist_file.version = FILELIST_FILE_VERSION;

	addr = FILE_ADDR_ALGIN(sizeof(filelist_file));
	
	// 得到文件长度
	file_length = addr + filelist_getlen(g_file_item);
	file_length = FILE_ADDR_ALGIN(file_length);

	// 分配并初始化空间
	p = rt_malloc(file_length + 2); 
	if(!p)
	{
		return -1;
	}
	memset(p, 0, file_length + 2);
	
	// 写入文件头
	memcpy(p, (char *)&filelist_file, sizeof(filelist_file));
	
	// 写文件列表
	filelist_memcpy(p+addr, g_file_item);

	// 计算CRC
	crc = CrcStr(p, file_length);
	memcpy(p+file_length, &crc, 2);

	// 创建数据文件
	pfile = rt_file_open("/tmp/file_list.bin",O_CREAT|O_RDWR,0);
	if(IS_ERR(pfile))
	{
		rt_free(p);
		return -2;
	}
	
	pos = 0;
	rt_file_write(pfile, p, file_length+2, &pos);

	rt_file_close(pfile,0);
	
	rt_free(p);
	
	return 0;
}
/*------------------------------ 内部函数 -------------------------------------
内部函数以下划线‘_’开头，不需要检查参数的合法性.
*/

static void _maintain_state_reset(void)
{
	g_maintain.state = MS_IDLE;
}

static void _maintain_echo(struct maintain_def *pt,u8 * cmd_buf,u8 cmd_len)			//确认帧
{	
	u8 cnt,checksum ,len;
	u8 *p;
	
	p=pt->sendbuf;

	// 101规约len域的值 +4=控制域、地址 、类型标识 、	文件命令
	len = cmd_len+2;
	
	// 报文帧长度 +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] = 0x01;	//链路地址

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

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

	// 帧尾
	if (pt->hmi_mode)
	{
		*p++ = 0x80 | (MAIN_BOARD << 3) | MAINTAIN_BOARD; 
	}
	else
	{	
		*p++ = 0x16;		 
	}
}	

/**************************************************************************
函数名称：IEC101_Recv_Rst
函数版本：1.00 
作者：   
创建日期：2008.9.1     
函数功能说明：复归数据的接受
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
static void _maintain_recv_rst(struct maintain_def *pt)
{
	pt->nTypeCounter=0;
	pt->nRecvLenth=0;
	pt->nRecvCounter=0;
}

static int _maintain_comm(struct maintain_def *pt,u8 *buf,int len)
{
	static u8 cmd_buf[256];
	u8 cmd_len;

	g_mt_rs232 = 0;

	memset(cmd_buf,0,sizeof(cmd_buf));
	cmd_len = Maintain_Manage(buf, len, &cmd_buf[0]);
	
	// 按内部101格式组帧
	_maintain_echo(pt, &cmd_buf[0], cmd_len);
	
	g_mtbuf.bSend = true;
	return 0;
}

static int _trans_file_comm(struct maintain_def *pt,u8 *buf,int len)
{
	static u8 cmd_buf[256] = {0};
	u8 cmd_len;
	
	cmd_len = com_trans_file(buf, len, &cmd_buf[0]);
	
	// 按内部101格式组帧
	_maintain_echo(pt, &cmd_buf[0], cmd_len);
	
	g_mtbuf.bSend = true;
	return 0;
}
 
/**************************************************************************
函数名称：_maintain_Send
函数版本：1.00 
作者：   
创建日期：2013.03.28    
函数功能说明：启动数据发送
输入参数：
输出参数：无
返回值： 
函数扇入清单：
***************************************************************************/

static void _maintain_send(void) 
{
	u8 length;
	length = g_mtbuf.sendbuf[0];
	if(g_mtbuf.bSend)
	{
		//print_mem("PCTX:",&g_mtbuf.sendbuf[1],length);
		if (!g_mtbuf.hmi_mode)
		{
			if (net_maintain_send(&g_mtbuf.sendbuf[1],length))
			{
				g_mtbuf.bSend = FALSE;
			}
		}
		else
		{
			Add_Uart_Frame(PDA_BOARD, (int)g_mtbuf.sendbuf[0], &g_mtbuf.sendbuf[1]);
			g_mtbuf.bSend = FALSE;
		}
	}
}

/******************************************************************************
函数名称：	_maintain_pwd_createfile
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	创建直流系数文件
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
static int _maintain_pwd_createfile(u8 *pwd)
{
	unsigned int addr,file_length;
	u16 crc;
	char *p;
	loff_t pos;
	struct file * pfile;
	struct mtpwd_file_head_data	mtpwd_file;
		
	// 写文件头
	memset(&mtpwd_file,0,sizeof(mtpwd_file));
	mtpwd_file.cfh.signature = SIG_MTPWD_FILE;
	mtpwd_file.cfh.version = MTPWD_FILE_VERSION;
	
	memcpy (&mtpwd_file.pwd, pwd, 16);
	
	// 得到文件长度
	addr = FILE_ADDR_ALGIN(sizeof(mtpwd_file));
	file_length = FILE_ADDR_ALGIN(addr);

	// 分配并初始化空间
	p = rt_malloc(file_length + 2); 
	if(!p)
	{
		return -1;
	}
	memset(p, 0, file_length + 2);
	
	// 写入文件头
	memcpy(p, (char *)&mtpwd_file, sizeof(mtpwd_file));
	
	// 计算CRC
	crc = CrcStr(p, file_length);
	memcpy(p+file_length, &crc, 2);

	// 创建数据文件
	pfile = rt_file_open("/app/data/mt_pwd.bin",O_CREAT|O_RDWR,0);
	if(IS_ERR(pfile))
	{
		rt_free(p);
		return -2;
	}
	
	pos = 0;
	rt_file_write(pfile, p, file_length+2, &pos);

	rt_file_close(pfile,0);
	
	rt_free(p);
	
	return 0;
}

/******************************************************************************
函数名称：	_maintain_pwd_readfile
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	读取直流系数文件
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
static int _maintain_pwd_readfile(void)
{
	u32 len;
	u16 crc;
	u8 *buf;
	loff_t pos;
	struct file * pfile;
	u8 i,pwd[16];

	struct mtpwd_file_head_data *brh;
	
	// 创建并打开文件
	pfile = rt_file_open("/app/data/mt_pwd.bin",O_RDWR,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(crc != *(u16*)(buf+len-2))
	{
		rt_free(buf);
		return -4;
	}

	// 检查文件签名
	brh = (struct mtpwd_file_head_data*)buf;
	if(brh->cfh.signature != SIG_MTPWD_FILE)
	{
		rt_free(buf);
		return -5;
	}

	// 检查文件长度
	if(len < sizeof(*brh) + 2)
	{
		rt_free(buf);
		return -7; 	
	}

	//取出文件中存储内容
	memcpy (&pwd, brh->pwd, 16);

	// 此处需将密码解密
	for (i=0; i<16; i++)
	{
		mt_pwd[i] = ~pwd[i];
	}

	rt_free(buf);
	return 0;
}
/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/
int printf_maintian(void)
{
	return 0;
}



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


