/*
这是一个示例文件，各产品应当参考本文件，开发自己的APP_API.c
也可以根据自身项目情况将这些函数分散到不同的.c文件中，只保持APP_API.h不变即可
*/
#include "APP_API.h"
#include "MSCP_APP_API.h"
#include "2oo2InterfaceDataManage.h"
#include "2oo2DataTransferManage.h"
#include "commonQueryStruDef.h"
#include "SystemParameterManage.h"
#include "ConfigDataReadManage.h"
#include "ProtclParam.h"
#include "../Deployment/DeploymentExtern.h"


static CM_UINT32 gFollowDataLen = 0u; /*应用跟随数据长度*/
static CM_UINT8 gFollowData[MSCP_FOLLOW_BUFF_SIZE] = { 0 }; /*应用跟随数据*/

/* 内网安全通信配置参数，示例： */
/* 内网安全通信配置参数，示例： */
/*ATP、ATO、MMI间通信时,SFP协议使用的数据库数组:
*两端ATP分别当作ZC1和ZC2,ZC1为发起方;
*ATO为CI3,MMI为CI4,CCOV为CI5(CCOV仅为预留,暂无通信的需求).ZC与CI通信时ZC为发起方
*总结各子系统ID为:两端ATP分别为0x5501,0x5502;ATO为0x7103;MMI为0x7104;CCOV为0x7105*/
const CM_UINT8 g_SfpInnetParam[] =
{

	0,4,/*不同设备通信关系表记录个数*/
		/*记录的格式如下:*/
		/*                   发起方  发起方发送数据  发起方报文   发起方报文  发起方接收Ack          跟随方  跟随方发送数据  跟随方运行  跟随方报文  此通信关系中成功发送           */
		/*                   设备类型    通信类型    发送周期长度   最大延时   报文最大延时差       设备类型    通信类型      周期长度    最大延时   一包数据所需最小周期数                               */
		/*ZC->CI*/           0x22,       0x55,       0x01,0x1D,   0x01,0x1D,   0x01,0x1D,            0xff,   0x55,           0x00,0xC8,  0x00,0xC8,  0x02,
		/*AOM->TIAS*/        0x15,       0x55,       0x00,0xC8,   0x00,0xC8,   0x00,0xC8,            0x03,   0x55,           0x00,0xC8,  0x00,0xC8,  0x02,
		/*AOM->ATP*/         0x14,       0x55,       0x00,0xC8,   0x00,0xC8,   0x00,0xC8,            0x15,   0x55,           0x00,0xC8,  0x00,0xC8,  0x02,
		/*主机->维护机*/   0xD9,       0x55,       0x01,0x2c,   0x01,0x2C,   0x01,0x2C,            0xf8,   0x55,           0x00,0xc8,  0x00,0xc8,  0x02,
		0,2,/*相同设备通信关系表记录个数*/
			/*记录的格式如下:*/
			/*                   发起方  发起方      发起方发送数据  发起方报文  发起方报文 发起方接收Ack    跟随方  跟随方      跟随方发送数据  跟随方运行  跟随方报文  此通信关系中成功发送           */
			/*                   设备类型 设备ID         通信类型    发送周期长度  最大延时  报文最大延时差  设备类型 设备ID         通信类型      周期长度    最大延时   一包数据所需最小周期数     */
			/*AOM1->AOM2*/       0x22,   1,               0x55,      0x00,0xC8,  0x00,0xC8,   0x00,0xC8,       0x22,   2,             0x55,      0x00,0xC8,  0x00,0xC8,  0x02,
			/*ZC1->ZC2*/         0x55,   1,               0x55,      0x00,0xC8,  0x00,0xC8,   0x00,0xC8,       0x55,   2,             0x55,      0x00,0xC8,  0x00,0xC8,  0x02
};

/* 应用周期主逻辑2 */
ENUM_CM_RETURN APP_API_MainFunc2(void);
/* 应用周期主逻辑3 */
ENUM_CM_RETURN APP_API_MainFunc3(void);
/* 应用周期主逻辑4 */
ENUM_CM_RETURN APP_API_MainFunc4(void);
/* 应用周期主逻辑4 */
ENUM_CM_RETURN APP_API_MainFunc5(void);
/* 应用周期主逻辑4 */
ENUM_CM_RETURN APP_API_MainFunc6(void);

#if (kPLATFORM==kVXWORKS)
static ENUM_CM_RETURN AddOneAppCheckData(IN const UINT32 dwDataAddr, IN const UINT16 wDataLen);
static ENUM_CM_RETURN AddAppCheckData(UINT32* pConfigDataAdderBuf, UINT16* pConfigDataLenBuf, UINT16 wDataLen);
#endif


/**
* @brief 应用初始化
* @param VitalBuf 关键数据数组
* @param pVitalLen 关键数据长度
* @return ENUM_CM_RETURN 初始化结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败（平台立即宕机）
* @details
* 2oo2双机的关键数据内容不一致时，2oo2初始化将失败——平台宕机；
* 2x2双系的关键数据内容不一致时，非主系运行的设备将宕机；
* 关键数据应尽可能短（如几个版本号或MD5码）总长不得超过200字节。
*/
ENUM_CM_RETURN APP_API_Init(OUT CM_UINT8 VitalBuf[200], OUT CM_UINT16* pVitalLen)
{
	ENUM_CM_RETURN retVal = ENUM_CM_FALSE; /*返回值*/
	UINT8 initRtn = 0U; /*应用初始化结果*/
	UINT16* pTiocFsVersion = NULL;/* 数据版本号 */

#if (kPLATFORM==kVXWORKS)
	UINT16 wAppConfigDataLen = 0u;
	UINT32 szConfigDataAddr[200u] = { 0u };
	UINT16 szConfigDataLen[200u] = { 0u };
	SERIAL_ID_FUNC pIsSendExtendBoard = NULL;/* 扩展板相关 */
	SERIAL_OUT_ATS_VOBC pReserveOutVobc = NULL;
	SERIAL_IN_VOBC_ATS pReserveInAts = NULL;
#if 1
	UINT8 cSwtichFalg = FUNC_SWITCH_OFF; /* 预留 下版本支持 */
#endif
#endif

	if ((NULL != VitalBuf) && (NULL != pVitalLen) && (192u >= *pVitalLen))
	{
		initRtn = CiAppInitial();
		if (1u == initRtn)
		{
			retVal = ENUM_CM_TRUE;
		}
		else
		{
			; /*返回失败*/
		}
	}
	else
	{
		;/* 返回失败 */
	}
	printf("CiAppInitial ret:%x\n", retVal);
	if (ENUM_CM_TRUE == retVal)
	{
		/* 应用初始化成功 */

		/* 获取数据版本号 */
		pTiocFsVersion = GetTiocFsVersion();

		if (NULL != pTiocFsVersion)
		{
			/* 输出数据版本号 */
			ShortToChar(pTiocFsVersion[0], &VitalBuf[*pVitalLen]);
			*pVitalLen += 2u;
			ShortToChar(pTiocFsVersion[1], &VitalBuf[*pVitalLen]);
			*pVitalLen += 2u;
			ShortToChar(pTiocFsVersion[2], &VitalBuf[*pVitalLen]);
			*pVitalLen += 2u;
			ShortToChar(pTiocFsVersion[3], &VitalBuf[*pVitalLen]);
			*pVitalLen += 2u;
		}
		else
		{
			retVal = ENUM_CM_FALSE;
		}
	}
	else
	{
		;/* 无处理 */
	}
	printf("GetTiocFsVersion ret:%x\n", retVal);
#if (kPLATFORM==kVXWORKS)
	if (ENUM_CM_TRUE == retVal)
	{
		/* 获取自检内存 */
		wAppConfigDataLen = GetTiocDeviceConfigData(szConfigDataAddr, szConfigDataLen, 200u);

		/* 添加自检内存 */
		if ((0u != wAppConfigDataLen) && (200u >= wAppConfigDataLen))
		{
			retVal = AddAppCheckData(szConfigDataAddr, szConfigDataLen, wAppConfigDataLen);
			printf("AddAppCheckData1 ret:%x\n", retVal);
		}
		else
		{
			retVal = ENUM_CM_FALSE;
		}
	}
	else
	{
		;/* 无处理 */
	}
	printf("GetTiocDeviceConfigData ret:%x\n", retVal);
	if (ENUM_CM_TRUE == retVal)
	{
		/* 获取自检内存 */
		wAppConfigDataLen = GetTiocSystemParameterData(szConfigDataAddr, szConfigDataLen, 200u);

		/* 添加自检内存 */
		if ((0u != wAppConfigDataLen) && (200u >= wAppConfigDataLen))
		{
			retVal = AddAppCheckData(szConfigDataAddr, szConfigDataLen, wAppConfigDataLen);
			printf("AddAppCheckData2 ret:%x\n", retVal);
		}
		else
		{
			retVal = ENUM_CM_FALSE;
		}
	}
	else
	{
		;/* 无处理 */
	}
	printf("GetTiocSystemParameterData ret:%x\n", retVal);
	if (ENUM_CM_TRUE == retVal)
	{
		pIsSendExtendBoard = Is_Send_ExtendBoard;
		MSCP_SetSerial(pIsSendExtendBoard);
		pReserveOutVobc = SerialOutAtsVobcFunc;
		MSCP_SetOutAtsVobcFunc(pReserveOutVobc);
		pReserveInAts = SerialInVobcAtsFunc;
		MSCP_SetInVobcAtsFunc(pReserveInAts);
#if 1
		cSwtichFalg = GetCiFunctionSwitchConfig(FUNC_OC_200_INOUTNET);

		if (FUNC_SWITCH_ON == cSwtichFalg)
		{
			/*设置协议参数*/
			MSCP_ParamData(innetProtclParam, innetProtclParamLen);
		}
		else
		{
			/* 无处理 */
		}
#endif


		/*设置主应用任务*/
		MSCP_SetAppFunc(APP_API_MainFunc, APP_API_MainFunc2, APP_API_MainFunc3, APP_API_MainFunc4, APP_API_MainFunc5);
	}
#endif

	return retVal;
}

/*
* @brief 提供给平台的初始化函数
* @return无
* @details
* 给平台提供FS版本号，维护ID、内网参数，系统版本号
**/
void APP_API_Data_Init()
{
	UINT8 fsVersBuffer[4] = { 0u };
	UINT8 appVersBuffer[4] = { 0u };
	UINT8 ciToCimDataBuffer[4] = { 0u };
	UINT8 deviceSum = 0u; /*通信设备数*/
	UINT16* pTiocFsVersion = NULL;  /*FS版本号buff*/
	UINT16 ii = 0U;
	UINT8 szFSFILEVersionFS[DFS_VERSION_LENGTH] = { 0 };
	UINT8 funcRetVal = 0U;
	funcRetVal = dquGetFSVersion(DataPath, szFSFILEVersionFS);

#if (kPLATFORM==kVXWORKS)
	/*文件配置*/
	STRU_APP_CFG_T AppCfgInterface = {
			.FS_NAME = "RCI.FS",			/**< FS文件名称 */
			.APP_NAME = "RCOCI",			/**< 应用文件名称 */
			.CYC_TIME = 300,			/**< 系统周期 */
			.app_num = 1,				/**< app任务数 */
			.M_2oo2_Enable = 0x55,		/**< 2oo2功能开关 */
			.M_2x2_Enable = 0x55,		/**< 2x2功能开关*/
			.M_InnetSafe_Enable = 0x55,	/**< 内网安全通信功能开关 */
			.M_InnetRaw_Enable = 0xAA,	/**< 内网透传通信功能开关 */
			.M_OutnetSafe_Enable = 0x55,/**< 外网安全通信功能开关 */
			.M_OutnetRaw_Enable = 0xAA,	/**< 外网透传通信功能开关 */
			.M_CpuUsageGet_Enable = 0x55,/**< 获取cpu使用率功能开关 */
			.M_RemoteUpdate_Enable = 0x55,/**< 远程部署内网安全通信功能开关 */
			.ID_Maintenance = DEVICE_TYPE_AIM,
			.Start_Path = "/emmc1",	/**< 程序启动路径 */
			.reboot_replycount = 10,	/**< 重启确认报文回复次数 */
			.M_AutoReboot_Count = 3,	/**< 自动重启次数 */
			.M_AutoClear_Days = 1,		/**< 连续运行多久清空宕机次数的天数 */
			.CPU[0].IP_2oo2 = "192.168.0.11",     /**< 2oo2通信IP */
			.CPU[0].IP_2x2 = "192.168.1.62",       /**< 2x2通信IP */
			.CPU[0].IP_Out = "192.168.1.62",       /**< 外网通信IP */
			.CPU[0].IP_Maintain = "192.168.146.101",  /**< 维护通信IP */
			/*适用透传通道-选配*/
			.CPU[0].IP_Com = "192.168.1.62",       /**< 通用通信IP */
			.CPU[0].IP_Com_Extend = "192.168.1.62",/**< 通用通信扩展IP */
			.CPU[0].Logger_PortBase = 55011,   		 /**< 明文日志记录发送端口 */
			.CPU[0].Logger_PortCiphertext = 55002, 	 /**< 暗文日志记录发送端口 */

			.CPU[1].IP_2oo2 = "192.168.0.12",     /**< 2oo2通信IP */
			.CPU[1].IP_2x2 = "192.168.2.62",       /**< 2x2通信IP */
			.CPU[1].IP_Out = "192.168.2.62",       /**< 外网通信IP */
			.CPU[1].IP_Maintain = "192.168.18.102",  /**< 维护通信IP */
			/*适用透传通道-选配*/
			.CPU[1].IP_Com = "192.168.2.62",       /**< 通用通信IP */
			.CPU[1].IP_Com_Extend = "192.168.2.62",/**< 通用通信扩展IP */
			.CPU[1].Logger_PortBase = 55012,   		 /**< 明文日志记录发送端口 */
			.CPU[1].Logger_PortCiphertext = 55002, 	 /**< 暗文日志记录发送端口 */

			.CPU[2].IP_2oo2 = "192.168.0.21",     /**< 2oo2通信IP */
			.CPU[2].IP_2x2 = "192.168.1.64",       /**< 2x2通信IP */
			.CPU[2].IP_Out = "192.168.1.64",       /**< 外网通信IP */
			.CPU[2].IP_Maintain = "192.168.146.103",  /**< 维护通信IP */
			/*适用透传通道-选配*/
			.CPU[2].IP_Com = "192.168.1.64",       /**< 通用通信IP */
			.CPU[2].IP_Com_Extend = "192.168.1.64",/**< 通用通信扩展IP */
			.CPU[2].Logger_PortBase = 55021,   		 /**< 明文日志记录发送端口 */
			.CPU[2].Logger_PortCiphertext = 55002, 	 /**< 暗文日志记录发送端口 */

			.CPU[3].IP_2oo2 = "192.168.0.22",     /**< 2oo2通信IP */
			.CPU[3].IP_2x2 = "192.168.2.64",       /**< 2x2通信IP */
			.CPU[3].IP_Out = "192.168.2.64",       /**< 外网通信IP */
			.CPU[3].IP_Maintain = "192.168.18.104",  /**< 维护通信IP */
			/*适用透传通道-选配*/
			.CPU[3].IP_Com = "192.168.2.64",       /**< 通用通信IP */
			.CPU[3].IP_Com_Extend = "192.168.2.64",/**< 通用通信扩展IP */
			.CPU[3].Logger_PortBase = 55022,   		 /**< 明文日志记录发送端口 */
			.CPU[3].Logger_PortCiphertext = 55002, 	 /**< 暗文日志记录发送端口 */
			/*通用端口配置*/
			.Port_Outnet_Safe = 54001,   	 /**< 外网安全通信端口 */
			.Port_Innet_Safe = 53001,   	 /**< 内网安全通信端口 */
			.Port_Outnet_Raw = 54002,   	 /**< 外网透明传输端口 */
			.Port_Remote_Update = 50000,  	 /**< 远程部署通信端口 */
			/*透传配置-选配*/
			.Port_Innet_Raw_Num = 0, 	 /**< 内网透传端口数量 */
			.Port_Innet_Raw_Extend_Num = 0, /**< 内网透传扩展端口数量 */
			.Innet_Raw_Parameter[0].Port_Innet_Raw = 3956, 		     /**< 内网透明传输端口 */
			.Innet_Raw_Parameter[0].Port_Type_Enable = RAW_COM_UDP,  /**< 内网透明tcp传输模式 */
			.Innet_Raw_Parameter[0].Server_DevId = 0, 		         /**< 服务端设备类型和id */
			.Innet_Raw_Parameter[0].TIME_STAMP_ENABLE = 0XAA,	     /**< 2取2乘时间戳使能开关 */
			.Innet_Raw_Parameter[0].INNET_2oo2_RAW = 0X55,		     /**< 透传通道2取开关 */
			.Innet_Raw_Parameter[0].INNET_2x2_RAW = 0XAA,		     /**< 透传通道2乘开关 */
			.Innet_Raw_Parameter[0].IP_InnetRaw_maddr = "224.0.0.31",/**< 内网透传的组播IP */

			.Innet_Raw_Parameter[1].Port_Innet_Raw = 3956, 		     /**< 内网透明传输端口 */
			.Innet_Raw_Parameter[1].Port_Type_Enable = RAW_COM_UDP,  /**< 内网透明tcp传输模式 */
			.Innet_Raw_Parameter[1].Server_DevId = 0, 		         /**< 服务端设备类型和id */
			.Innet_Raw_Parameter[1].TIME_STAMP_ENABLE = 0XAA,	     /**< 2取2乘时间戳使能开关 */
			.Innet_Raw_Parameter[1].INNET_2oo2_RAW = 0X55,		     /**< 透传通道2取开关 */
			.Innet_Raw_Parameter[1].INNET_2x2_RAW = 0XAA,		     /**< 透传通道2乘开关 */
			.Innet_Raw_Parameter[1].IP_InnetRaw_maddr = "224.0.0.32",/**< 内网透传的组播IP */
			/*外网通信配置*/
			.OutNetRed.CC_G_IP = "192.168.1.60",  /**< 通控的内网IP */
			.OutNetRed.CC_P_IP = "192.168.2.60",  /**< 通控的内网IP */
			.OutNetRed.EXTEND_G_IP = "192.168.1.70",       	/**< 扩展板卡的内网IP */
			.OutNetRed.EXTEND_P_IP = "192.168.2.70",       	/**< 扩展板卡的内网IP */
			.OutNetRed.OutnetSafe_Port = 54001, 		/**< 外网安全通信端口 */
			.OutNetRed.OutnetRaw_Port = 54002, 		/**< 外网透传通信端口 */
			.OutNetRed.InnetRaw_Port = 53003,   		/**< 内网透传通信端口 */

			.OutNetBlue.CC_G_IP = "192.168.1.61",  /**< 通控的内网IP */
			.OutNetBlue.CC_P_IP = "192.168.2.61",  /**< 通控的内网IP */
			.OutNetBlue.EXTEND_G_IP = "192.168.1.71",       	/**< 扩展板卡的内网IP */
			.OutNetBlue.EXTEND_P_IP = "192.168.2.71",       	/**< 扩展板卡的内网IP */
			.OutNetBlue.OutnetSafe_Port = 54001, 		/**< 外网安全通信端口 */
			.OutNetBlue.OutnetRaw_Port = 54002, 		/**< 外网透传通信端口 */
			.OutNetBlue.InnetRaw_Port = 53003,   		/**< 内网透传通信端口 */
			/*日志记录目标设备IP配置*/
			.Logger_G_IP = "192.168.146.100",         /**< 绿网日志记录IP */
			.Logger_P_IP = "192.168.18.100",         /**< 紫网日志记录IP */
			/*内网通信设备注册最大支持0-255*/
			.INNET_COM_NUM = 1,     				/**< 内网通信设备数量 */
			.INNET_COM_CFG[0].InnetID = DEVICE_TYPE_AIM,     /**< 内网通信ID */
			.INNET_COM_CFG[0].IP_G = (CM_UINT32)inet_addr("192.168.146.100"),/**< 绿网IP */
			.INNET_COM_CFG[0].Port_Raw_G = 55004,   /**< 绿网透传端口 */
			.INNET_COM_CFG[0].Port_Safe_G = 55003,  /**< 绿网安全端口 */
			.INNET_COM_CFG[0].IP_P = (CM_UINT32)inet_addr("192.168.18.100"),/**< 紫网IP */
			.INNET_COM_CFG[0].Port_Raw_P = 55004,   /**< 紫网透传端口 */
			.INNET_COM_CFG[0].Port_Safe_P = 55003,  /**< 紫网安全端口 */
	};
	MSCP_Set_APP_ConfigData(&AppCfgInterface);
#endif

	/*组FS版本号*/
	ii = 0U;
	fsVersBuffer[ii++] = szFSFILEVersionFS[0];
	fsVersBuffer[ii++] = szFSFILEVersionFS[1];
	fsVersBuffer[ii++] = szFSFILEVersionFS[2];
	fsVersBuffer[ii++] = szFSFILEVersionFS[3];

	/*组软件版本号*/
	ii = 0U;
	appVersBuffer[ii++] = VER_INTE_PROJECT;
	appVersBuffer[ii++] = VER_INTE_PRODUCT >> 2U;
	appVersBuffer[ii++] = (VER_INTE_PRODUCT << 6U) + (VER_INTE_EXE & (UINT8)0x3F);
	appVersBuffer[ii++] = VER_INTE_TIME;
	/*设置平台调用获取外网信息函数*/
	MSCP_SetSrcId(SetOutNetPara);
	/*设置内网参数*/
	MSCP_SetSfpInnetPara(g_SfpInnetParam);
	MSCP_SetAppVersion(appVersBuffer);
	MSCP_SetFsVersion(fsVersBuffer);
}
/**
* @brief 应用周期主逻辑
* @return ENUM_CM_RETURN 函数执行结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败（平台立即宕机）
* @details
* 当本系热备状态为：ENUM_2x2_SHUTDOWN，时
* 本函数不执行；
* 当本系热备状态为：ENUM_2x2_OFFLINE，ENUM_2x2_PRE_MASTER，ENUM_2x2_SLAVE，时
* 本函数被周期执行，但 ENUM_MSG_OUTNET_SAFE 报文不会真实输出；
* 当本系热备状态为：ENUM_2x2_MASTER，时
* 本函数被周期执行，并且所有输出信息被真实输出。
*/
ENUM_CM_RETURN APP_API_MainFunc(void)
{
	ENUM_CM_RETURN retVal = ENUM_CM_NULL;
	CM_UINT64 startCycTick = 0u;
	CM_UINT64 endCycTick = 0u;

	startCycTick = MSCP_GetTick();
	debug_infor_printf("app proc start at %llu us\n", startCycTick);
	if (1 == MainProcess())
	{
		retVal = ENUM_CM_TRUE;
	}
	else
	{
		debug_infor_printf("app proc err\n");
	}

	endCycTick = MSCP_GetTick();
	debug_infor_printf("app proc end at %llu us,used %d us\n", endCycTick, (CM_INT32)((endCycTick - startCycTick) / 1000));

	gFollowDataLen = GetCiAppData(gFollowData);
	MSCP_SetFollowData(gFollowData, gFollowDataLen);

	return retVal;
}

/**
* @brief 应用周期主逻辑2
* @return ENUM_CM_RETURN 函数执行结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败（平台立即宕机）
* @details
* 当本系热备状态为：ENUM_2x2_SHUTDOWN，时
* 本函数不执行；
* 当本系热备状态为：ENUM_2x2_OFFLINE，ENUM_2x2_PRE_MASTER，ENUM_2x2_SLAVE，时
* 本函数被周期执行，但 ENUM_MSG_OUTNET_SAFE 报文不会真实输出；
* 当本系热备状态为：ENUM_2x2_MASTER，时
* 本函数被周期执行，并且所有输出信息被真实输出。
*/
ENUM_CM_RETURN APP_API_MainFunc2(void)
{
	/*MSCP_LogMsg("app2\n");*/
	/*CM_Sleep(50u);*/
	return ENUM_CM_TRUE;
}

/**
* @brief 应用周期主逻辑3
* @return ENUM_CM_RETURN 函数执行结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败（平台立即宕机）
* @details
* 当本系热备状态为：ENUM_2x2_SHUTDOWN，时
* 本函数不执行；
* 当本系热备状态为：ENUM_2x2_OFFLINE，ENUM_2x2_PRE_MASTER，ENUM_2x2_SLAVE，时
* 本函数被周期执行，但 ENUM_MSG_OUTNET_SAFE 报文不会真实输出；
* 当本系热备状态为：ENUM_2x2_MASTER，时
* 本函数被周期执行，并且所有输出信息被真实输出。
*/
ENUM_CM_RETURN APP_API_MainFunc3(void)
{
	/*MSCP_LogMsg("app3\n");*/
	/*CM_Sleep(50u);*/
	return ENUM_CM_TRUE;
}

ENUM_CM_RETURN APP_API_MainFunc4(void)
{
	/*MSCP_LogMsg("app3\n");*/
	/*CM_Sleep(50u);*/
	return ENUM_CM_TRUE;
}

/**
* @brief 应用周期主逻辑5
* @return ENUM_CM_RETURN 函数执行结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败（平台立即宕机）
* @details
* 当本系热备状态为：ENUM_2x2_SHUTDOWN，时
* 本函数不执行；
* 当本系热备状态为：ENUM_2x2_OFFLINE，ENUM_2x2_PRE_MASTER，ENUM_2x2_SLAVE，时
* 本函数被周期执行，但 ENUM_MSG_OUTNET_SAFE 报文不会真实输出；
* 当本系热备状态为：ENUM_2x2_MASTER，时
* 本函数被周期执行，并且所有输出信息被真实输出。
*/
ENUM_CM_RETURN APP_API_MainFunc5(void)
{
	/*MSCP_LogMsg("app3\n");*/
	/*CM_Sleep(50u);*/
	return ENUM_CM_TRUE;
}

ENUM_CM_RETURN APP_API_MainFunc6(void)
{
	/*MSCP_LogMsg("app3\n");*/
	/*CM_Sleep(50u);*/
	return ENUM_CM_TRUE;
}
/**
* @brief 应用输入处理逻辑
* @return ENUM_CM_RETURN 函数执行结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败（平台立即宕机）
* @note
* 本函数在平台线程的输入阶段被调用
* 注意平台线程在第N周期接收的输入数据，应用线程在第N+1周期才能读取到
*/
ENUM_CM_RETURN APP_API_InputFunc(void)
{
	return ENUM_CM_TRUE;
}

/**
* @brief 备系跟随接口
* @param Data   跟随数据数组
* @param Len    跟随数据长度
* @return ENUM_CM_RETURN 函数执行结果
* - ENUM_CM_TRUE 成功
* - ENUM_CM_FALSE 失败（平台立即宕机）
* @details
* 当本系热备状态为：ENUM_2x2_OFFLINE，ENUM_2x2_SLAVE，且收到了邻系正确的跟随数据时
* 本函数将在APP_API_MainFunc()之前执行；
* 否则，本函数不执行。
* 应用跟随数据的最大长度不得超过1024*1000字节
* @see :: MSCP_SetFollowData
*/
ENUM_CM_RETURN APP_API_FollowUp(IN const CM_UINT8 Data[MSCP_FOLLOW_BUFF_SIZE], IN CM_UINT32 Len)
{
	ENUM_CM_RETURN retVal = ENUM_CM_FALSE;
	UINT8 setRtn = 0u;

	setRtn = SetCiAppData(Data, Len);
	if (1u == setRtn)
	{
		retVal = ENUM_CM_TRUE;
	}

	return retVal;
}

ENUM_CM_RECCUSEB Is_Send_ExtendBoard(IN const CM_UINT16 dstDevTypeId)
{
	ENUM_CM_RECCUSEB retVal = ENUM_CM_CC; /*返回值*/
	CM_UINT8 devType = 0U; /*设备类型*/
	CM_UINT8 devId = 0U; /*设备ID*/
	CM_UINT16 wAtsGtWayDevTypeId = 0U;
	UINT8 chLocalCiType = 0U; /*本联锁属性*/
	UINT8 chDstCiType = 0U; /*本联锁属性*/
	UINT8 chCldScxCommMode = 0U;
	UINT8 chResult = CI_ERROR; /*联锁属性检查结果*/

	wAtsGtWayDevTypeId = GetTiocTrnsmtGtwyDevTypeId();
	/**使用通控板与ATS网关通信*/
	if (dstDevTypeId != wAtsGtWayDevTypeId)
	{
		devType = (CM_UINT8)((dstDevTypeId >> 8) & 0xFF);
		devId = (CM_UINT8)(dstDevTypeId & 0xFF);

		chLocalCiType = GetLocalCiType();
		chDstCiType = GetCiType(devId);
		chCldScxCommMode = GetCiFunctionSwitchConfig(SCX_CLD_INTERFACE_TYPE);

		if ((SCX_CLD_SERIAL_PORT_COMM == chCldScxCommMode) && (CI_SYSTEM_TYPE_CI == devType))
		{
			if (((CI_TYPE_CLD == chLocalCiType) && (CI_TYPE_SCX == chDstCiType)) || ((CI_TYPE_SCX == chLocalCiType) && (CI_TYPE_CLD == chDstCiType)))
			{
				/*串口通信要求双方一个为车辆段一个为试车线*/
				chResult = CI_SUCCESS;
			}
			else
			{
				; /*CI类型错误，返回失败*/
			}
		}
		else
		{
			; /*不为串口通信，此时不对本地CI类型及对方CI类型进行判断*/
		}

		if ((CI_SYSTEM_TYPE_XIANDI == devType) || (CI_SYSTEM_TYPE_ATS == devType) || (CI_SYSTEM_TYPE_LEU == devType)
			|| (CI_SUCCESS == chResult)
			|| (CI_SYSTEM_TYPE_VOBC_BACKUP == devType)) /*现地,ATS,LEU,使用串口的相邻CI*/
		{
			retVal = ENUM_CM_SEB;
		}
		else if (CI_SYSTEM_TYPE_ITE == devType)
		{
			retVal = ENUM_CM_CCSEB;
		}
		else
		{
			retVal = ENUM_CM_CC;
		}
	}
	else
	{
		retVal = ENUM_CM_CC;
	}

	return retVal;
}
/*
* @func： 外网输入ID 红蓝网类型及ID缓存
* @param： void
* @return  ：VOID
*/
void SetOutNetPara(UINT8* pRxBuf, UINT32 dwLen, ENUM_OUTNET_CHN_T chOutNetType, UINT16* pOutBuf, INOUT UINT16* pCurLen)
{
	UINT16 wSrcId = 0U;
	UINT32 dwTmpLen = 0U;
	UINT16 tmpAppLen = 0U;
	UINT16 objLen = 0U;
	UINT16 tempLen = 0U;
	UINT16 ii = 0U;
	UINT16 gTransmitObjTypeId[TRANSMIT_OBJECT_SUM_MAX * TRANSMIT_OBJECT_DEVICE_SUM_MAX] = { 0U };
	if ((NULL != pRxBuf) && (NULL != pOutBuf) && (NULL != pCurLen))
	{
		if ((ENUM_OUTNET_RED == chOutNetType) || (ENUM_OUTNET_EXTEND_RED == chOutNetType)
			|| (ENUM_OUTNET_BLUE == chOutNetType) || (ENUM_OUTNET_EXTEND_BLUE == chOutNetType))
		{
			while (dwTmpLen < dwLen)
			{
				tmpAppLen = ShortFromChar(&pRxBuf[dwTmpLen]);
				if ((tmpAppLen + 2) <= (dwLen - dwTmpLen))
				{
					wSrcId = ShortFromChar(&pRxBuf[dwTmpLen + 2]);
					dwTmpLen += (tmpAppLen + 2);

					/*去重*/
					for (ii = 0U; ii < objLen; ii++)
					{
						if (gTransmitObjTypeId[ii] == wSrcId)
						{
							break;
						}
					}
					if ((ii == objLen) && (TRANSMIT_OBJECT_SUM_MAX * TRANSMIT_OBJECT_DEVICE_SUM_MAX > objLen))
					{
						gTransmitObjTypeId[objLen++] = wSrcId;
					}

				}
				else
				{
					break;
				}
			}
			tempLen = *pCurLen;
			if ((TRANSMIT_OBJECT_SUM_MAX * TRANSMIT_OBJECT_DEVICE_SUM_MAX) > (tempLen + objLen))
			{
				CommonMemCpy((void*)&pOutBuf[tempLen], objLen * sizeof(UINT16), \
					(const void*)gTransmitObjTypeId, objLen * sizeof(UINT16));
				*pCurLen = tempLen + objLen;
				debug_infor_printf("outnet in type len :%d", chOutNetType, objLen);
				debug_out_array(0xAA, gTransmitObjTypeId, objLen * sizeof(UINT16));
			}
		}
		else
		{
			;
		}
	}
	else
	{
		printf("buf Null\n");
	}
}






#if (kPLATFORM==kVXWORKS)
/*
* 功能描述： 处理平台网络数据类型信息
* 参数说明： void
* 返回值  ： void
*/
void ProcessPlatformNetData(void)
{
	UINT16 ii = 0U;
	UINT16 wSrcId = 0U;
	UINT16 gRedTransmitObjTypeId[TRANSMIT_OBJECT_SUM_MAX * TRANSMIT_OBJECT_DEVICE_SUM_MAX] = { 0U };
	UINT16 gBlueTransmitObjTypeId[TRANSMIT_OBJECT_SUM_MAX * TRANSMIT_OBJECT_DEVICE_SUM_MAX] = { 0U };
	MSCP_GetRciTempBuf(gRedTransmitObjTypeId, gBlueTransmitObjTypeId);
	debug_infor_printf("\nRED type in cycle:%d", Get2oo2CurCycleNum());
	debug_out_array(0xAA, gRedTransmitObjTypeId, TRANSMIT_OBJECT_SUM_MAX * TRANSMIT_OBJECT_DEVICE_SUM_MAX * sizeof(UINT16));
	debug_infor_printf("\nBlue type in cycle:%d", Get2oo2CurCycleNum());
	debug_out_array(0xAA, gBlueTransmitObjTypeId, TRANSMIT_OBJECT_SUM_MAX * TRANSMIT_OBJECT_DEVICE_SUM_MAX * sizeof(UINT16));
	for (ii = 0; ii < TRANSMIT_OBJECT_SUM_MAX * TRANSMIT_OBJECT_DEVICE_SUM_MAX; ii++)
	{
		wSrcId = gRedTransmitObjTypeId[ii];
		SetCiTrnsmitCycNumByNetType((UINT8)(wSrcId >> 8U), (UINT8)(wSrcId & 0x00ffU), TRANSMIT_NET_ATC_RED);

		wSrcId = gBlueTransmitObjTypeId[ii];
		SetCiTrnsmitCycNumByNetType((UINT8)(wSrcId >> 8U), (UINT8)(wSrcId & 0x00ffU), TRANSMIT_NET_ATC_BLUE);
	}

}
ENUM_CM_RETURN AddOneAppCheckData(IN const UINT32 dwDataAddr, IN const UINT16 wDataLen)
{
	ENUM_CM_RETURN retVal = ENUM_CM_FALSE; /*返回值*/
	CM_UINT32* pTmpDataAdder = NULL;
	CM_UINT32  wTmpDataLen = 0u;

	pTmpDataAdder = (CM_UINT32*)dwDataAddr;
	wTmpDataLen = (CM_UINT32)wDataLen;

	if ((NULL != pTmpDataAdder) && (0u != wTmpDataLen))
	{
		MSCP_MemCheck_Register(pTmpDataAdder, wTmpDataLen);
		retVal = ENUM_CM_TRUE;
	}
	return retVal;
}

ENUM_CM_RETURN AddAppCheckData(UINT32* pConfigDataAdderBuf, UINT16* pConfigDataLenBuf, UINT16 wDataLen)
{
	ENUM_CM_RETURN retVal = ENUM_CM_FALSE; /*返回值*/
	UINT16 i = 0u;

	if ((NULL != pConfigDataAdderBuf) && (NULL != pConfigDataLenBuf) && (0u != wDataLen) && (UINT16_MAX != wDataLen))
	{
		for (i = 0u; i < wDataLen; i++)
		{
			retVal = AddOneAppCheckData(pConfigDataAdderBuf[i], pConfigDataLenBuf[i]);

			if (ENUM_CM_TRUE != retVal)
			{
				break;
			}
			else
			{
				;/* 无处理 */
			}
		}
	}
	else
	{
		;/* 返回失败 */
	}
	return retVal;
}
#endif
/*
* 功能描述： 退出运营处理，设置板卡退出
* 参数说明： void
* 返回值  ： void
*/
void APP_API_ExitOperation(void)
{

	UINT8 chExitOpStatus = 0U;
	/*退出运营处理*/
	Deploy_ExitOperationHandle();
	chExitOpStatus = Deploy_GetExitOperateStatus();
	if (EXIT_OP_STATUS == chExitOpStatus)
	{
		MSCP_SetBoardState(ENUM_BOARDSTATE_EXIT); /*设置板卡退出*/
		debug_infor_printf("Tell TSCP I AM INTO EXTOPRATION!\n");
	}
	else
	{
		/*- 不处理*/
		debug_infor_printf("Tell TSCP I AM  STAYOPRATION!\n");
	}
}


/**
* @brief 输出ats转车数据备用通道判断函数(串口扩展版)。
* @param UINT16 inSrcId ，UINT16 outSrcId ,UINT16 outDstId
* @details 此函数指针为一个返回值,三个参数。
* 		      返回值ENUM_CM_RETURN 0x55或0xaa
* 		      参数1入参CM_UINT16 输入目标Id
* 		      参数2出参CM_UINT16* 输出源Id
* 		      参数3出参CM_UINT16* 输出目的Id
*/
ENUM_CM_RETURN SerialOutAtsVobcFunc(UINT16 inDstId IN, UINT16* outSrcId OUT, UINT16* outDstId OUT)
{
	ENUM_CM_RETURN retVal = ENUM_CM_FALSE;
	UINT8 inDstType = 0U;

	inDstType = (UINT8)((inDstId & 0xff00U) >> 8);
	if ((CI_SYSTEM_TYPE_VOBC_BACKUP == inDstType) || (CI_SYSTEM_TYPE_ITE == inDstType))
	{
		*outSrcId = (CI_SYSTEM_TYPE_CI << 8) + GetSystemParaLocalCiId();
		*outDstId = GetATSInterfaceTypeId();

		retVal = ENUM_CM_TRUE;
	}

	return retVal;
}

/**
* @brief 输入ats转车数据备用通道判断函数(串口扩展版)。
* @param UINT16 inSrcId
* @details 此函数指针为一个返回值,三个参数。
* 		      返回值ENUM_CM_RETURN 0x55 true或0xaa false
* 		      参数1入参CM_UINT16 输入源Id
*/
ENUM_CM_RETURN SerialInVobcAtsFunc(UINT16 inSrcId IN)
{

	ENUM_CM_RETURN retVal = ENUM_CM_FALSE;
	UINT16 atsBackUpTypeId = 0U;
	atsBackUpTypeId = GetATSInterfaceTypeId();
	/*判断与列车后备通道0x1300一致*/
	if (atsBackUpTypeId == inSrcId)
	{

		retVal = ENUM_CM_TRUE;
	}

	return retVal;
}


