#include "protclInterFun.h"
#include "ProtclManage.h"
#include "Convert.h"
#include "protclMgeCfg.h"
#include "dsuRsspFunc.h"
#include "CommonMemory.h"
#include "CommonRecord.h"

#define RSSPI_OPP_IDS_NUM (255) /*RSSPI的对方唯一ID数量*/

#define DEV_LEN_ILLEGAL (2u) /*DevDataFormatCheck设备数据长度非法*/
#define DEV_IDX_ILLEGAL (3u) /*DevDataFormatCheck设备数据下标非法*/
#define DATA_IDX_ILLEGAL (4u) /*RepeatDataFormatCheck数据下标非法*/
#define DEV_SFP_LEN_ILLEGAL (5u) /*RepeatValCheck设备SFP数据长度非法*/
#define DEV_RSSPI_FSFB_LEN_ILLEGAL (6u) /*RepeatValCheck设备RSSPI-FSFB数据长度非法*/
#define DEV_RSSPII_LEN_ILLEGAL (7u) /*RepeatValCheck设备RSSPII数据长度非法*/
#define DATA1_NET_LEN_ILLEGAL (8u) /*RepeatCheckSet一份数据网数据长度非法*/
#define DATA2_STAGING_NO_SPACE (9u) /*RepeatCheckSet二份数据暂存数组无空间*/
#define DATA2_IDX_ILLEGAL (10u) /*TwoDevRepeat二份数据下标非法*/
#define DATA2_DEV_LEN_ILLEGAL (11u) /*TwoDevRepeat二份数据设备数据长度非法*/
#define DATA1_IDX_ILLEGAL (12u) /*TwoDevRepeat一份数据位置非法*/
#define DATA2STAGING_NET_ILLEGAL (13u) /*TwoNetRepeat二份暂存网长度非法*/
#define DATA2_NET_IDX_ILLEGAL (14u) /*TwoRepeat二份数据网下标非法*/
#define DATA2STAGING_COPY_ILLEGAL (15u) /*TwoRepeat二份暂存赋值到二份数据长度非法*/
#define NET_LEN_ILLEGAL (16u) /*DevDataFormatCheck网数据长度非法*/
#define NET2_LEN_ILLEGAL (17u) /*TwoNetRepeat网2数据长度非法*/
#define NET1_LEN_ILLEGAL (18u) /*TwoDevRepeat网1数据长度非法*/
#define DATA2_STAGING_NO (19u) /*TwoDevRepeat二份数据暂存数组无空间*/
#define NO_DATA_NET1_LEN_ILLEGAL (20u) /*TwoDevRepeat网1无数据时数据长度非法*/

static UINT16 DelRsspiNotOppId(UINT16 linkDataLen, UINT8 linkData[], UINT16 singleLinkLen, UINT16 oppIdIdx, UINT8 oppIdsNum, const UINT32 oppIds[]);

static UINT8 ProtclTwoRepeatParam(ProtclConfigInfoStru* protcl, UINT8* data1, UINT8* data2, UINT32* data2Len, UINT8* data2Staging);
static UINT8 RepeatDataFormatCheck(UINT8* data, const UINT32 dataLen);
static UINT8 DevDataFormatCheck(UINT8* data, const UINT32 dataLen, UINT32* dataIdx, UINT32* netLen);
static UINT8 TwoRepeat(ProtclConfigInfoStru* protcl, UINT8* data1, const UINT32 data1Len, UINT8* data2, UINT32* data2Len, UINT8* data2Staging, const UINT32 data2StagingMaxLen);
static UINT8 RepeatDataNetFormatCheck(UINT8* data, const UINT32 dataLen, const UINT32 netDataIdx, UINT32* netLen);
static UINT8 TwoNetRepeat(ProtclConfigInfoStru* protcl, UINT8* data1, UINT32* data1Idx, const UINT32 data1Len, UINT8* data2, UINT32* data2Idx, const UINT32 data2Len, UINT8* data2Staging, UINT32* data2StagingIdx, const UINT32 data2StagingMaxLen);
static UINT8 TwoNetRepeatParam(ProtclConfigInfoStru* protcl, UINT8* data1, UINT32* data1Idx, UINT8* data2, UINT32* data2Idx, UINT8* data2Staging, UINT32* data2StagingIdx);
static UINT8 TwoDevRepeat(ProtclConfigInfoStru* protcl, UINT8* data1, const UINT32 data1IdxNet, UINT32* data1Idx, const UINT32 data1Len, UINT8* data2, UINT32* data2Idx, const UINT32 data2Len, UINT32* net2Idx, const UINT32 net2Len, UINT8* data2Staging, UINT32* data2StagingIdx, const UINT32 data2StagingMaxLen);
static UINT8 TwoDevRepeatParam(ProtclConfigInfoStru* protcl, UINT8* data1, UINT32* data1Idx, UINT8* data2, UINT32* data2Idx, UINT32* net2Idx, UINT8* data2Staging, UINT32* data2StagingIdx);
static UINT8 RepeatCheck(const UINT8 dev2OppTypePtl, const  UINT32 dev2UniqueId, UINT8* dev2Data, const  UINT16 dev2Len, UINT8* data1, UINT32* data1Idx, const UINT32 data1Len, const UINT32 data1IdxNet, UINT32* net1Idx, const  UINT32 net1Len, UINT8* data2Staging, UINT32* data2StagingIdx, const UINT32 data2StagingMaxLen);
static UINT8 RepeatCheckParam(UINT8* dev2Data, UINT8* data1, UINT32* data1Idx, UINT32* net1Idx, UINT8* data2Staging, UINT32* data2StagingIdx);
static UINT8 RepeatCheckSet(UINT8 isRepeat, UINT8 isFirst, UINT8* dev2Data, UINT16 dev2Len, UINT32* data1Idx, UINT32 net1Idx, UINT32 net1Len, UINT8* data2Staging, UINT32* data2StagingIdx, const UINT32 data2StagingMaxLen);
static UINT8 RepeatDataCheck(UINT8* isRepeat, UINT8 dev2OppTypePtl, UINT32 dev2UniqueId, UINT8* dev2Data, UINT16 dev2Len, UINT8* data1, UINT32 data1IdxNet, const UINT32 data1Len, UINT32* net1Idx, UINT32 net1Len);
static UINT8 RepeatDataCheckParam(UINT8* isRepeat, UINT8* dev2Data, UINT8* data1, UINT32* net1Idx);
static UINT8 RepeatValCheck(UINT8* isRepeat, UINT8 dev2OppTypePtl, UINT8* dev2Data, UINT16 devLen, UINT8* data1, UINT32 data1Idx, const UINT32 data1MaxLen);
static UINT8 RepeatValCheckParam(UINT8* isRepeat, UINT8* devData, UINT16 devLen, UINT8* data1, UINT32 data1Idx, const UINT32 data1MaxLen);

/*
* 协议初始化模块
* 参数： 
* 输入参数：    char*  fileName         存放数据的地址
*				UINT32 inDataLen 内部参数长度
*				UINT8 inData[] 内部参数
*    			ProtclConfigInfoStru * pUnifyInfo   统一结构体
* 返回值：
*   1 ：初始化成功
*   0: 初始化失败
*/
UINT8 ProtclInitFunc(UINT8* fileName, UINT32 inDataLen, UINT8 inData[], ProtclConfigInfoStru* pUnifyInfo)
{
	UINT8 ret = 0;

	if ((NULL != pUnifyInfo) && (NULL != fileName))
	{
		ret = Init(fileName, inDataLen, inData, pUnifyInfo);
	}

	return ret;
}

/*
*函数名:	ProtclEndFunc
*功能描述:	适配层销毁清理协议
*输入参数:	ProtclConfigInfoStru *pUnifyInfo	适配层协议统一结构体
*输入出参:	无
*输出参数:	无
*返回值:	1;销毁成功,0:销毁失败
*/
UINT8 ProtclEndFunc(ProtclConfigInfoStru *pUnifyInfo)
{
	UINT8 ret = 0;
	if (NULL != pUnifyInfo)
	{
		ret = FreeSpace(pUnifyInfo);
	}
	

	return ret;
}

/*
* 功能：协议发送数据
*
* 参数： 
* 输入输出参数：  ProtclConfigInfoStru * pUnifyInfo   统一结构体
* 返回值：
*    UINT8 1 正常，其他不正常
*/

UINT8 ProtclSendDataFunc(ProtclConfigInfoStru * pUnifyInfo)
{
	UINT8 ret =0;
	if (NULL != pUnifyInfo)
	{
		if ((pUnifyInfo->AppArray != NULL) && (pUnifyInfo->VarArray != NULL))
		{
			ret = SendAppData(pUnifyInfo);
		}
		else
		{
			ret = 0;
		}
	}
	else
	{
		ret = 0;
	}
	return ret;
}

/*
* 功能：协议接收数组
* 参数：
* 输入输出参数：ProtclConfigInfoStru * pUnifyInfo   统一结构体
* 返回值：
*    1：接收数据成功
0：失败
*/

UINT8 ProtclReceiveDataFunc (ProtclConfigInfoStru * pUnifyInfo)
{
	UINT8 ret =0;

	if (pUnifyInfo != NULL)
	{
		ret = ReceiveAppData(pUnifyInfo);
	}
	else
	{
		ret=0;
	}

	return ret;
}

/*
* 功能：查询链路状态
*
* 参数： 
* 输入参数：  UINT8 DestType    对方设备类型
* 			  UINT8 DestID      对方设备ID
*             UINT16 logId      若卡斯柯的CI与VOBC通信，需要填写VOBC的站台号。其他的系统填0。
*             ProtclConfigInfoStru * pUnifyInfo   统一结构体
* 返回值： 
*     0：不存在该条链路，返回错误
*     0x17：链路在数据传输正常状态
*     0x2b：链路在通信中断状态
*     0x33：链路在准备建立链接状态
*     0x4e：链路在等待建立链接状态
*     0x01: 表示刷新无用的链路
*/
UINT8 ProtclGetLnkStatus (UINT8 destType,UINT8 destId,UINT16 logId,ProtclConfigInfoStru * pUnifyInfo)
{
	UINT8 ret =0;
	if (NULL!=pUnifyInfo)
	{
		ret = GetLnkStatus(destType,destId,logId,pUnifyInfo);
	}

	return ret;
}


/*
* 功能：删除链路
*
* 参数： 
* 输入参数：  UINT8 DestType    对方设备类型
* 			  UINT8 DestID      对方设备ID
*             UINT16 logId      动态ID
*             ProtclConfigInfoStru * pUnifyInfo   统一结构体
* 返回值：
*    UINT8 1 删链成功
*          0 删链失败
*/

UINT8 ProtclDeleteLnkFunc(UINT8 DestType,UINT8 DestID,UINT16 logId,ProtclConfigInfoStru * pUnifyInfo)
{
	UINT8 retnVal =0;

	if (NULL!= pUnifyInfo)
	{
		retnVal = DelLnkFunc(DestType, DestID, logId, pUnifyInfo);
	}
	
	return retnVal;
}


/*
* 功能：刷新链路状态
*
* 参数： 
* 输入参数： 	 UINT8* pLnkStatusData     协议状态数据
* 返回值： 
*     0：刷新链路失败
*     1：刷新链路成功 
*/
UINT8 ProtclReFreshFunc(UINT8* pLnkStatusData, ProtclConfigInfoStru *pUnifyInfo)
{
	UINT8 retVal =0;
	if ((NULL != pLnkStatusData) && (NULL != pUnifyInfo))
	{
		retVal = ReFresh(pLnkStatusData, pUnifyInfo);
	}
	
	return retVal;
}

/************************************************************************
功能：向协议层输入TCP链路状态信息
描述: 用户需要每周期调用且仅调用一次本函数,为协议层更新TCP链路状态信息，
    注意，如果先调用协议接收函数ProtclReceiveDataFunc()，后调用本函数，可
	能导致本周期的协议接收函数无法正确工作，极端情况下会因为未正确接收AU1
	消息导致建链时间延长
输入参数：
	UINT16 TcpStateDataLen,  TCP状态信息字节数
	UINT8* pTcpStateData	TCP状态信息
返回值：0失败 1成功
************************************************************************/
UINT8 ProtclReceiveTcpStateFunc(UINT16 TcpStateDataLen,UINT8* pTcpStateData, ProtclConfigInfoStru *pUnifyInfo)
{
	UINT8 ret =0;
	if ((NULL!= pTcpStateData)&&(NULL!= pUnifyInfo))
	{
		ret = ReceiveTcpState(TcpStateDataLen, pTcpStateData, pUnifyInfo);
	}
	
	return ret;
}

/************************************************************************
功能：协议层输出TCP链路控制信息
描述：使用TCP通信（如RSSP2协议）时，用户需要每周期调用且仅调用一次本函数,
    获取协议层输出的TCP链路控制信息，并将该信息透明转发给2个通信控制器，
	注意，建议先向通信控制器发送TCP链路控制信息，后发送通信报文。
输出参数:
	UINT16 *pTcpCtrlDataLen, TCP控制信息字节数
	UINT8 *pTcpCtrlData      TCP控制信息
返回值：
************************************************************************/
UINT8 ProtclSendTcpCtrlFunc(UINT16 *pTcpCtrlDataLen,UINT8 *pTcpCtrlData, ProtclConfigInfoStru *pUnifyInfo)
{
	UINT8 ret = 0;
	if ((NULL != pTcpCtrlDataLen)&&(NULL!= pTcpCtrlData)&&(NULL!= pUnifyInfo))
	{
		ret = SendTcpCtrl(pTcpCtrlDataLen, pTcpCtrlData, pUnifyInfo);
	}
	
	return ret;
}

/*
*函数名:	DelRsspiNotOppId
*功能描述:	删除RSSPI链路中非指定的对方地址链路
*输入参数:	UINT16 linkDataLen 链路数据长度
*			UINT8 linkData[] 链路数据
*			UINT16 singleLinkLen 单个链路长度
*			UINT16 oppIdIdx 对方唯一ID在链路中位置
*			UINT8 oppIdsNum 对方唯一ID数量
*			const UINT32 oppIds[] 对方唯一ID数组
*输入出参:	无
*输出参数:	无
*返回值:	UINT16 aftLinkDataLen 处理后的链路数据长度
*/
static UINT16 DelRsspiNotOppId(UINT16 linkDataLen, UINT8 linkData[], UINT16 singleLinkLen, UINT16 oppIdIdx, UINT8 oppIdsNum, const UINT32 oppIds[])
{
	UINT16 aftLinkDataLen = linkDataLen; /*处理后链路数据长度*/
	UINT16 i = 0; /*用于循环*/
	UINT16 j = 0; /*用于循环*/
	UINT16 linkNum = linkDataLen / singleLinkLen; /*包含的单个链路数量*/
	UINT32 oppIdLink = 0; /*链路信息中对方唯一ID*/
	UINT16 curIdx = 0; /*当前链路下标位置*/

	if (( NULL != linkData)&&( NULL != oppIds))
	{
		for (i = 0; i < linkNum; i++) /*遍历链路信息*/
		{
			oppIdLink = LongFromChar(&linkData[curIdx + oppIdIdx]); /*链路中对方唯一ID*/
			for (j = 0; j < oppIdsNum; j++)
			{
				if (oppIds[j] == oppIdLink) /*找到退出循环*/
				{
					break;
				}
			}
			if (j == oppIdsNum) /*未找到,删除此对方唯一ID的链路*/
			{
				if (i < (linkNum - 1)) /*非最后一个,移动链路信息*/
				{
					CommonMemCpy(&linkData[curIdx], linkDataLen - (singleLinkLen * (i + 1)), &linkData[curIdx + singleLinkLen], linkDataLen - (singleLinkLen * (i + 1)));
				}
				aftLinkDataLen -= singleLinkLen; /*调整处理后长度*/
			}
			else
			{
				curIdx += singleLinkLen; /*下标偏移一个链路长度*/
			}
		}

	}
	
	return aftLinkDataLen;
}

/*
*函数名:	AdjustRsspiVarArray
*功能描述:	调整RSSPI链路,只保留指定的对方地址链路
*输入参数:	UINT8 oppIdsNum 对方类型ID逻辑ID数量
*			const UINT16 oppTypeIds[] 对方类型ID数组
*			const UINT16 oppLogicIds[] 对方逻辑ID数组
*			ProtclConfigInfoStru *pUnifyInfo 适配结构体变量
*输入出参:	无
*输出参数:	无
*返回值:	无
*/
void AdjustRsspiVarArray(UINT8 oppIdsNum, const UINT16 oppTypeIds[], const UINT16 oppLogicIds[], ProtclConfigInfoStru *pUnifyInfo)
{
	const UINT16 oppIdSafeIdx = 7; /*对方唯一ID在安全层中位置*/
	const UINT16 oppIdRedundIdx = 0; /*对方唯一ID在冗余层中位置*/

	UINT32 oppIds[RSSPI_OPP_IDS_NUM] = { 0 }; /*对方唯一ID*/
	UINT32 i = 0; /*用于循环*/
	UINT8 *linkData = NULL; /*链路信息*/
	UINT16 totalLen = 0; /*链路总长度*/
	UINT16 curIdx = 0; /*当前链路下标位置*/
	UINT32 curProtcl = 1; /*当前协议标识*/
	UINT16 curLen = 0; /*当前协议链路长度*/
	UINT16 curLenIdx = 0; /*当前协议链路长度位置*/
	UINT16 safeLen = 0; /*RSSPI安全层链路长度*/
	UINT16 safeLenIdx = 0; /*RSSPI安全层链路长度位置*/
	UINT16 aftSafeLen = 0; /*处理后的RSSPI安全层链路长度*/
	UINT16 redundLen = 0; /*RSSPI冗余层链路长度*/
	UINT16 redundLenIdx = 0; /*RSSPI冗余层链路长度位置*/
	UINT16 aftRedundLen = 0; /*处理后的RSSPI冗余层链路长度*/
	UINT8 isAdjustRear = 0; /*是否调整尾部数据*/

#ifdef USE_RSSPI
	if ((0 < oppIdsNum) && (RSSPI_OPP_IDS_NUM > oppIdsNum) && (NULL != oppTypeIds) && (NULL != oppLogicIds) && (NULL != pUnifyInfo) && (NULL != pUnifyInfo->VarArray)
		&& (NULL != pUnifyInfo->GlobalVar) && (NULL != pUnifyInfo->GlobalVar->gpRsspUnitInfo) && (NULL != pUnifyInfo->GlobalVar->gpRsspUnitInfo->pDsuRsspInfoStruWL)) /*参数检查*/
	{
		for (i = 0; i < oppIdsNum; i++) /*获取到RSSPI对方唯一ID*/
		{
#ifdef RSSP_NO_HLHT
			oppIds[i] = oppTypeIds[i];
#else
			oppIds[i] = DquTypeIdToHlhtId(oppTypeIds[i], oppLogicIds[i], pUnifyInfo->GlobalVar->gpRsspUnitInfo->pDsuRsspInfoStruWL); /*对方唯一ID*/
#endif
		}

		linkData = pUnifyInfo->VarArray; /*链路信息*/
		/*链路总长度*/
		totalLen = 2 + ShortFromChar(linkData);
		curIdx += 2;

		for (curProtcl = 1; curProtcl <= PROTCL_MGECFG_MAXCNT; curProtcl++) /*遍历协议*/
		{
			/*当前链路下标位置*/
			curLen = ShortFromChar(&linkData[curIdx]);
			curLenIdx = curIdx;
			curIdx += 2;

			if ((curIdx + curLen) <= totalLen) /*协议链路长度有效*/
			{
				if ((DSU_PROTCL_RSSP == curProtcl) && (2 < curLen)) /*当前是RSSPI协议,有链路信息*/
				{
					safeLen = ShortFromChar(&linkData[curIdx]); /*安全层链路长度*/
					if (((2 + safeLen) <= curLen) && (0 == (safeLen%RSSP_VAR_NODE_LEN_WL))) /*安全层链路长度有效*/
					{
						safeLenIdx = curIdx; /*安全层链路长度位置*/
						curIdx += 2;

						if (0 < safeLen) /*有安全层链路信息*/
						{
							aftSafeLen = DelRsspiNotOppId(safeLen, &linkData[curIdx], RSSP_VAR_NODE_LEN_WL, oppIdSafeIdx, oppIdsNum, oppIds);
						}

						redundLenIdx = curIdx + safeLen;
						redundLen = curLen - 2 - safeLen;
						if ((0 < redundLen) && (0 == (redundLen % RP_LINK_LEN)))
						{
							aftRedundLen = DelRsspiNotOppId(redundLen, &linkData[redundLenIdx], RP_LINK_LEN, oppIdRedundIdx, oppIdsNum, oppIds);
						}

						if ((aftSafeLen <= safeLen) && (aftRedundLen <= redundLen)) /*处理后长度有效*/
						{
							curIdx += aftSafeLen; /*处理后冗余层开始位置*/
							if (aftSafeLen < safeLen) /*安全层调整过*/
							{
								CommonMemCpy(&linkData[curIdx], aftRedundLen, &linkData[redundLenIdx], aftRedundLen); /*调整冗余层数据*/
								ShortToChar(aftSafeLen, &linkData[safeLenIdx]); /*设置处理后的安全层长度*/
								isAdjustRear = 1;
							}
							else
							{
								if (aftRedundLen < redundLen) /*冗余层调整过*/
								{
									isAdjustRear = 1;
								}
							}
							curIdx += aftRedundLen; /*尾部数据开始位置*/
							if (1 == isAdjustRear) /*需调整尾部数据*/
							{
								CommonMemCpy(&linkData[curIdx], totalLen - curLenIdx - 2 - curLen, &linkData[curLenIdx + 2 + curLen], totalLen - curLenIdx - 2 - curLen); /*调整尾部数据*/
								ShortToChar(2 + aftSafeLen + aftRedundLen, &linkData[curLenIdx]); /*设置处理后的RSSPI链路长度*/
								ShortToChar(totalLen - 2 - (safeLen - aftSafeLen) - (redundLen - aftRedundLen), linkData); /*设置适配层链路总长度*/
							}
						}
					}

					break; /*找到RSSPI处理完链路退出循环*/
				}
				else /*非RSSPI协议继续循环处理*/
				{
					curIdx += curLen;
				}
			}
			else /*协议链路长度无效,退出循环*/
			{
				break;
			}
		}
	}
#endif
}

/*
*功能描述:	获取各网收到包数
*输入参数:	ProtclConfigInfoStru* pUnifyInfo 适配层变量
*			const UINT8 dstType	目的设备类型
*			const UINT8 dstId 目的设备ID
*			const UINT16 dstLogicId 目的逻辑ID
*输入出参:	UINT16* redRecvPkgNum 红网收到包数
*			UINT16* blueRecvPkgNum 篮网收到包数
*输出参数:	无
*返回值:	无
*/
void ProtclGetNetsRecvPkgNumFunc(ProtclConfigInfoStru* pUnifyInfo, const UINT8 dstType, const UINT8 dstId, const UINT16 dstLogicId, UINT16* redRecvPkgNum, UINT16* blueRecvPkgNum)
{
	if ((NULL != pUnifyInfo) && (NULL != redRecvPkgNum) && (NULL != blueRecvPkgNum)) /*参数检查*/
	{
		GetNetsRecvPkgNum(pUnifyInfo, dstType, dstId, dstLogicId, redRecvPkgNum, blueRecvPkgNum);
	}
}

/*
*函数名:	ProtclGetSwapData
*功能描述:	获取输出数据中双CPU交互数据
*输入参数:	UINT8 swapData[] 交互数据 2字节总长度+SFP(2字节长度+N个[4字节CRC])+RSSPI(2字节长度+N个[4字节SVC]) 空间大于2046
*           const UINT16 swapDataMaxLen 交互数据最大长度 大于2046
*           ProtclConfigInfoStru* protcl 协议结构体变量
*输入出参:	无
*输出参数:	无
*返回值:	无
*/
void ProtclGetSwapData(UINT8 swapData[], const UINT16 swapDataMaxLen, ProtclConfigInfoStru* protcl)
{
	UINT16 swapDataLen = 0u; /*交互数据长度*/
	UINT8* record = NULL; /*日志数组*/
	UINT16 recordSize = 0u; /*日志数组长度*/

	if ((NULL != swapData) && (NULL != protcl) && (NULL != protcl->GlobalVar) && (2u < swapDataMaxLen)) /*非空检查*/
	{
		record = protcl->RecordArray;
		recordSize = protcl->RecordArraySize;
		PrintRecArrayByte(record, recordSize, 0xD1u);

		ShortToChar(0u, &swapData[0]); /*总长度清零*/

#ifdef USE_SFP
		SfpGetSwapData(&swapData[2], swapDataMaxLen, protcl->GlobalVar->gpsfpUnitInfo);
#else
		ShortToChar(0u, &swapData[2]); /*长度设置为0*/
#endif
		swapDataLen = 2u + 2u + ShortFromChar(&swapData[2]); /*累加上SFP长度,即rsspi开始位置*/
		if (swapDataLen < swapDataMaxLen) /*有空间*/
		{
#ifdef USE_RSSPI
			RsspiGetSwapData(&swapData[swapDataLen], swapDataMaxLen - swapDataLen, protcl->GlobalVar->gpRsspUnitInfo);
#else
			ShortToChar(0u, &swapData[swapDataLen]); /*长度设置为0*/
#endif
			swapDataLen += (2u + ShortFromChar(&swapData[swapDataLen])); /*累加上RSSPI长度*/

			ShortToChar(swapDataLen - 2u, &swapData[0]); /*设置总长度*/
		}
		else /*无空间*/
		{
			PrintRecArrayByte(record, recordSize, 1u);
			PrintRecArray2ByteB(record, recordSize, swapDataLen);
			PrintRecArray2ByteB(record, recordSize, swapDataMaxLen);
		}
	}
}

/*
*函数名:	ProtclSetSwapData
*功能描述:	设置输出数据中双CPU交互数据
*输入参数:	UINT8 swapData[] 交互数据 2字节总长度+SFP(2字节长度+N个[4字节CRC])+RSSPI(2字节长度+N个[4字节SVC])
*			ProtclConfigInfoStru* protcl 协议结构体变量
*输入出参:	无
*输出参数:	无
*返回值:	无
*/
void ProtclSetSwapData(UINT8 swapData[], ProtclConfigInfoStru* protcl)
{
	UINT16 swapDataLen = 0u; /*交互数据长度*/
	UINT32 allLen = 0u; /*总长度*/
	UINT32 outAppIdx = 0u; /*输出应用数据位置*/
	UINT8* outAppData = NULL; /*输出应用数据*/
	UINT16 pkgLen = 0u; /*包长度*/
	UINT8  protclType = 0u; /*协议类型*/
	UINT16 sfpLen = 0u; /*SFP长度*/
	UINT16 rsspiLen = 0u; /*RSSPI长度*/
	UINT16 sfpStartIdx = 0u; /*SFP开始位置*/
	UINT16 rsspiStartIdx = 0u; /*RSSPI开始位置*/
	UINT8 isProSfp = 0u; /*是否处理过SFP*/
	UINT8 isProRsspi = 0u; /*是否处理过RSSPI*/
	UINT8* record = NULL; /*日志数组*/
	UINT16 recordSize = 0u; /*日志数组长度*/

	if ((NULL != swapData) && (NULL != protcl) && (NULL != protcl->GlobalVar))
	{
		record = protcl->RecordArray;
		recordSize = protcl->RecordArraySize;
		PrintRecArrayByte(record, recordSize, 0xD2u);

		swapDataLen = ShortFromChar(&swapData[0]); /*总长度*/

		sfpStartIdx = 2u; /*RSSPI开始位置*/
		sfpLen = ShortFromChar(&swapData[2]);
		rsspiStartIdx = 2u + sfpStartIdx + sfpLen; /*RSSPI开始位置*/
		rsspiLen = ShortFromChar(&swapData[rsspiStartIdx]);
		if (((2u + sfpLen + 2u + rsspiLen) == swapDataLen) && (0u == (sfpLen % 4u)) && (0u == (rsspiLen % 4u))) /*长度检查*/
		{
			/*AppArray:4字节总长度+|&2字节长度+1字节协议类型+1字节目的类型+1字节目的ID+2字节预留+网络上发送数据(协议包)*/
			allLen = LongFromChar(&protcl->AppArray[0]);
			if (0u < allLen) /*有输出*/
			{
				outAppData = &protcl->AppArray[4];
				while (outAppIdx < allLen) /*遍历输出应用数据*/
				{
					pkgLen = 2u + ShortFromChar(&outAppData[outAppIdx]);
					if ((outAppIdx + pkgLen) <= allLen) /*当前输出应用位置加长度小于等于输出应用长度,合法*/
					{
						protclType = outAppData[outAppIdx + 2u]; /*协议类型*/
						if ((DSU_PROTCL_SFP == protclType) || (DSU_PROTCL_RSSP == protclType)) /*SFP或RSSPI*/
						{
							if (DSU_PROTCL_SFP == protclType) /*SFP*/
							{
								if (0u == isProSfp) /*只处理一次,适配层输出数据中,SFP数据一份*/
								{
#ifdef USE_SFP
									SfpSetSwapDataForOut(&swapData[sfpStartIdx], &outAppData[outAppIdx], protcl->GlobalVar->gpsfpUnitInfo);
#endif
									isProSfp = 1u;
								}
							}
							else /*RSSPI*/
							{
								if (0u == isProRsspi) /*只处理一次,适配层输出数据中,RSSPI数据一份*/
								{
#ifdef USE_RSSPI
									RsspiSetSwapDataForOut(&swapData[rsspiStartIdx], &outAppData[outAppIdx], protcl->GlobalVar->gpRsspUnitInfo);
#endif
									isProRsspi = 1u;
								}
							}
						}

						outAppIdx += pkgLen;
					}
					else /*包长度非法*/
					{
						PrintRecArrayByte(record, recordSize, 3u);
						PrintRecArray2ByteB(record, recordSize, pkgLen);
						PrintRecArray4ByteB(record, recordSize, outAppIdx);
						PrintRecArray4ByteB(record, recordSize, allLen);

						break;
					}
				}
			}
			else /*无输出*/
			{
				PrintRecArrayByte(record, recordSize, 2u);
				PrintRecArrayByte(record, recordSize, 0u);
			}
		}
		else /*长度检查错误*/
		{
			PrintRecArrayByte(record, recordSize, 1u);
			PrintRecArray2ByteB(record, recordSize, swapDataLen);
			PrintRecArray2ByteB(record, recordSize, sfpLen);
			PrintRecArray2ByteB(record, recordSize, rsspiLen);
		}
	}
}

/*
*函数名:	ProtclDelAllLink
*功能描述:	适配层删除所有链路
*输入参数:	ProtclConfigInfoStru* protcl 协议结构体变量
*输入出参:	无
*输出参数:	无
*返回值:	无
*/
void ProtclDelAllLink(ProtclConfigInfoStru* protcl)
{
	if ((NULL != protcl) && (NULL != protcl->GlobalVar)) /*参数检查*/
	{
#ifdef USE_SFP
		SfpDelAllLink(protcl->GlobalVar->gpsfpUnitInfo);
#endif
#ifdef USE_RSSPI
		RsspiDelAllLink(protcl->GlobalVar->gpRsspUnitInfo);
#endif
	}
}

/*
*函数名:	ProtclTwoRepeat
*功能描述:	两份数据比较去除重复数据(两份中都有去除二份中的,否则各自保留)
*输入参数:	
*			ProtclConfigInfoStru* protcl 协议结构体变量
*			UINT8* data1 一份数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			const UINT32 data1Len 一份数据长度
*			UINT8* data2Staging 二份数据暂存数组
*			const UINT32 data2StagingMaxLen 二份数据暂存数组最大长度
*输入出参:	
*			UINT8* data2 二份数据(格式:同上)
*			UINT32* data2Len 二份数据长度
*输出参数:	无
*返回值:	成功:1 失败:0
*/
UINT8 ProtclTwoRepeat(ProtclConfigInfoStru* protcl, UINT8* data1, const UINT32 data1Len, UINT8* data2, UINT32* data2Len, UINT8* data2Staging, const UINT32 data2StagingMaxLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT8 funRtn = 0u; /*调用函数返回值*/

	funRtn = ProtclTwoRepeatParam(protcl, data1, data2, data2Len, data2Staging);
	if (1u == funRtn) /*调用函数返回正常*/
	{
		if ((0u == data1Len) && (0u == *data2Len)) /*两份无数据*/
		{
			rtnVal = 1u;
		}
		else if ((0u < data1Len) && (0u == *data2Len)) /*一份有数据,二份无数据*/
		{
			rtnVal = RepeatDataFormatCheck(data1, data1Len);
		}
		else if ((0u == data1Len) && (0u < *data2Len)) /*一份无数据,二份有数据*/
		{
			rtnVal = RepeatDataFormatCheck(data2, *data2Len);
		}
		else /*一份有数据,二份有数据*/
		{
			rtnVal = TwoRepeat(protcl, data1, data1Len, data2, data2Len, data2Staging, data2StagingMaxLen);
		}
	}

	return rtnVal;
}

/*
*函数名:	ProtclTwoRepeatParam
*功能描述:	两份数据比较去除重复数据函数参数检查
*输入参数:
*			ProtclConfigInfoStru* protcl 协议结构体变量
*			UINT8* data1 一份数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			UINT8* data2Staging 二份数据暂存数组
*输入出参:
*			UINT8* data2 二份数据(格式:同上)
*			UINT32* data2Len 二份数据长度
*输出参数:	无
*返回值:	成功:1 失败:0
*/
static UINT8 ProtclTwoRepeatParam(ProtclConfigInfoStru* protcl, UINT8* data1, UINT8* data2, UINT32* data2Len, UINT8* data2Staging)
{
	UINT8 rtnVal = 0u; /*返回值*/

	if ((NULL != protcl) && (NULL != data1) && (NULL != data2) && (NULL != data2Len) && (NULL != data2Staging)) /*参数检查*/
	{
		rtnVal = 1u;
	}

	return rtnVal;
}

/*
*函数名:	RepeatDataFormatCheck
*功能描述:	要比较去重的数据格式检查
*输入参数:
*			UINT8* data 数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			const UINT32 dataLen 数据长度
*输入出参:	无
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 RepeatDataFormatCheck(UINT8* data, const UINT32 dataLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT32 dataIdx = 0u; /*数据当前位置*/
	UINT32 netLen = 0u; /*网数据长度*/
	UINT8 isBreak = 0u; /*是否退出遍历*/
	UINT8 funRtn = 0u; /*调用函数返回值*/

	if (NULL != data) /*参数检查*/
	{
		while (dataIdx < dataLen) /*遍历网数据*/
		{
			if (dataIdx + 4u <= dataLen) /*数据下标合法.4为网4字节数据长度*/
			{
				funRtn = DevDataFormatCheck(data, dataLen, &dataIdx, &netLen);
				if (1u != funRtn) /*调用函数返回值异常*/
				{
					rtnVal = funRtn;
					isBreak = 1u;
				}
			}
			else /*数据下标非法*/
			{
				rtnVal = DATA_IDX_ILLEGAL;
				isBreak = 1u;
			}
			if (1u == isBreak) /*退出遍历*/
			{
				break;
			}
		}
		if ((0u == isBreak) && (dataIdx == dataLen)) /*不退出遍历且数据长度合法*/
		{
			rtnVal = 1u;
		}
	}

	return rtnVal;
}

/*
*函数名:	DevDataFormatCheck
*功能描述:	设备数据格式检查
*输入参数:
*			UINT8* data 数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			const UINT32 dataLen 数据长度
*输入出参:
*			UINT32* dataIdx 数据当前位置
*			UINT32* netLen 网数据长度
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 DevDataFormatCheck(UINT8* data, const UINT32 dataLen, UINT32* dataIdx, UINT32* netLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT32 netIdx = 0u; /*网数据当前位置*/
	UINT16 devLen = 0u; /*设备数据长度*/
	UINT8 isBreak = 0u; /*是否退出遍历*/

	if ((NULL != data) && (NULL != dataIdx) && (NULL != netLen)) /*参数检查*/
	{
		netIdx = 0u; /*网数据当前位置清零*/
		*netLen = 4u + LongFromChar(&data[*dataIdx]); /*网数据长度*/
		if (*netLen <= dataLen) /*网数据长度合法*/
		{
			netIdx += 4u;
			*dataIdx += 4u;
			while (netIdx < *netLen) /*遍历设备包数据*/
			{
				if (*dataIdx + 6u < dataLen) /*数据下标合法.6为2字节设备数据长度+4字节设备唯一ID*/
				{
					devLen = 2u + ShortFromChar(&data[*dataIdx]); /*设备数据长度*/
					if ((6u < (UINT32)devLen) && (4u + (UINT32)devLen <= *netLen)) /*设备数据长度合法*/
					{
						netIdx += devLen;
						*dataIdx += devLen;
					}
					else /*设备数据长度非法*/
					{
						rtnVal = DEV_LEN_ILLEGAL;
						isBreak = 1u;
					}
				}
				else /*数据下标非法*/
				{
					rtnVal = DEV_IDX_ILLEGAL;
					isBreak = 1u;
				}
				if (1u == isBreak) /*有错误,退出遍历*/
				{
					break;
				}
			}
			if (netIdx == *netLen) /*网数据长度检查*/
			{
				rtnVal = 1u;
			}
		}
		else /*网数据长度非法*/
		{
			rtnVal = NET_LEN_ILLEGAL;
		}
	}

	return rtnVal;
}

/*
*函数名:	TwoRepeat
*功能描述:	两份都有数据比较去除重复数据(两份中都有去除二份中的,否则各自保留)
*输入参数:
*			ProtclConfigInfoStru* protcl 协议结构体变量
*			UINT8* data1 一份数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			UINT32 data1Len 一份数据长度
*			UINT8* data2Staging 二份数据暂存数组
*			UINT32 data2StagingMaxLen 二份数据暂存数组最大长度
*输入出参:
*			UINT8* data2 二份数据(格式:同上)
*			UINT32* data2Len 二份数据长度
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 TwoRepeat(ProtclConfigInfoStru* protcl, UINT8* data1, const UINT32 data1Len, UINT8* data2, UINT32* data2Len, UINT8* data2Staging, const UINT32 data2StagingMaxLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT32 data2Idx = 0u; /*数据当前位置*/
	UINT32 data1Idx = 0u; /*数据1当前位置*/
	UINT8 funRtn = 0u; /*调用函数返回值*/
	UINT8 isBreak = 0u; /*是否退出遍历*/
	UINT32 data2StagingIdx = 0u; /*二份数据暂存数组当前位置*/

	funRtn = ProtclTwoRepeatParam(protcl, data1, data2, data2Len, data2Staging);
	if (1u == funRtn) /*调用函数返回正常*/
	{
		while (data2Idx < *data2Len) /*遍历二份数据*/
		{
			if (data2Idx + 4u <= *data2Len) /*数据下标合法.4为网4字节数据长度*/
			{
				funRtn = TwoNetRepeat(protcl, data1, &data1Idx, data1Len, data2, &data2Idx, *data2Len, data2Staging, &data2StagingIdx, data2StagingMaxLen);
				if (1u != funRtn)
				{
					rtnVal = funRtn;
					isBreak = 1u;
				}
			}
			else /*数据下标非法*/
			{
				rtnVal = DATA2_NET_IDX_ILLEGAL;
				isBreak = 1u;
			}
			if (1u == isBreak) /*退出遍历*/
			{
				break;
			}
		}
		if ((0u == isBreak) && (data1Idx == data1Len) && (data2Idx == *data2Len)) /*不退出遍历且一二份数据长度合法*/
		{
			if (data2StagingIdx <= *data2Len) /*暂存数据长度合法*/
			{
				(void)CommonMemCpy(&data2[0], *data2Len, &data2Staging[0], data2StagingIdx);
				*data2Len = data2StagingIdx;
				rtnVal = 1u;
			}
			else /*暂存数据长度非法*/
			{
				rtnVal = DATA2STAGING_COPY_ILLEGAL;
			}
		}
	}

	return rtnVal;
}


/*
*函数名:	RepeatDataNetFormatCheck
*功能描述:	要比较去重数据的某段网数据格式检查
*输入参数:
*			UINT8* data 数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			const UINT32 dataLen 数据长度
*			const UINT32 netDataIdx 网数据位置
*输入出参:
*			UINT32* netLen 网数据长度
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 RepeatDataNetFormatCheck(UINT8* data, const UINT32 dataLen, const UINT32 netDataIdx, UINT32* netLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT32 dataIdx = 0u; /*数据当前位置*/
	UINT8 funRtn = 0u; /*调用函数返回值*/

	if ((NULL != data) && (NULL != netLen)) /*参数检查*/
	{
		dataIdx = netDataIdx;
		if (dataIdx + 4u <= dataLen) /*数据下标合法.4为网4字节数据长度*/
		{
			funRtn = DevDataFormatCheck(data, dataLen, &dataIdx, netLen);
			if (1u == funRtn) /*调用函数返回值正常*/
			{
				if (dataIdx <= dataLen) /*数据长度合法*/
				{
					rtnVal = 1u;
				}
			}
			else /*调用函数返回值错误*/
			{
				rtnVal = funRtn;
			}
		}
	}

	return rtnVal;
}

/*
*函数名:	TwoNetRepeat
*功能描述:	两份网数据比较去除重复数据
*输入参数:
*			ProtclConfigInfoStru* protcl 协议结构体变量
*			UINT8* data1 一份数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			const UINT32 data1Len 一份数据长度
*			UINT8* data2 二份数据(格式:同上)
*			const UINT32 data2Len 二份数据长度
*			UINT32 data2StagingMaxLen 二份数据暂存数组最大长度
*输入出参:
*			UINT32* data1Idx 网1下标
*			UINT32* data2Idx 网2下标
*			UINT8* data2Staging 二份数据暂存数组
*			UINT32* data2StagingIdx 二份数据暂存数组下标
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 TwoNetRepeat(ProtclConfigInfoStru* protcl, UINT8* data1, UINT32* data1Idx, const UINT32 data1Len, UINT8* data2, UINT32* data2Idx, const UINT32 data2Len, UINT8* data2Staging, UINT32* data2StagingIdx, const UINT32 data2StagingMaxLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT32 data1IdxNet = 0u; /*数据1当前网包位置*/
	UINT32 net2Len = 0u; /*网2包数据长度*/
	UINT32 net2Idx = 0u; /*网2包数据当前位置*/
	UINT32 net1Len = 0u; /*网1包数据长度*/
	UINT8 funRtn = 0u; /*调用函数返回值*/
	UINT8 isErr = 0u; /*是否错误*/
	UINT32 data2StagingStartIdx = 0u; /*二份数据暂存数组网数据开始位置*/

	funRtn = TwoNetRepeatParam(protcl, data1, data1Idx, data2, data2Idx, data2Staging, data2StagingIdx);
	if (1u == funRtn) /*调用函数返回正常*/
	{
		if (*data2StagingIdx + 4u <= data2StagingMaxLen) /*二份数据暂存数组有空间*/
		{
			data1IdxNet = *data1Idx; /*一份数据当前位置*/

			data2StagingStartIdx = *data2StagingIdx; /*设置二份数据暂存数组网数据开始位置*/
			(void)CommonMemCpy(&data2Staging[data2StagingStartIdx], data2StagingMaxLen - data2StagingStartIdx, &data2[*data2Idx], 4u);
			*data2StagingIdx += 4u;

			net2Len = 4u + LongFromChar(&data2[*data2Idx]); /*网数据长度*/
			if (net2Len <= data2Len) /*网数据长度合法*/
			{
				net2Idx += 4u;
				*data2Idx += 4u;

				if (4u < net2Len) /*有设备数据*/
				{
					while (net2Idx < net2Len) /*遍历二份网数据*/
					{
						funRtn = TwoDevRepeat(protcl, data1, data1IdxNet, data1Idx, data1Len, data2, data2Idx, data2Len, &net2Idx, net2Len, data2Staging, data2StagingIdx, data2StagingMaxLen);
						if (1u != funRtn) /*退出遍历*/
						{
							rtnVal = funRtn;
							isErr = 1u;
							break;
						}
					}
				}
				else /*无设备数据*/
				{
					funRtn = RepeatDataNetFormatCheck(data1, data1Len, data1IdxNet, &net1Len);
					if (1u == funRtn) /*正常*/
					{
						*data1Idx += net1Len;
					}
					else /*异常*/
					{
						rtnVal = funRtn;
						isErr = 1u;
					}
				}

				if ((0u == isErr) && (net2Idx == net2Len)) /*不退出遍历且网数据长度非法*/
				{
					if (data2StagingStartIdx + 4u <= *data2StagingIdx) /*二份暂存长度合法*/
					{
						LongToChar(*data2StagingIdx - data2StagingStartIdx - 4u, &data2Staging[data2StagingStartIdx]);
						rtnVal = 1u;
					}
					else /*二份暂存长度非法*/
					{
						rtnVal = DATA2STAGING_NET_ILLEGAL;
					}
				}
			}
			else /*网数据长度非法*/
			{
				rtnVal = NET2_LEN_ILLEGAL;
			}
		}
	}

	return rtnVal;
}

/*
*函数名:	TwoNetRepeatParam
*功能描述:	两份网数据比较去除重复数据参数检查
*输入参数:
*			ProtclConfigInfoStru* protcl 协议结构体变量
*			UINT8* data1 一份数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			UINT8* data2 二份数据(格式:同上)
*			UINT32* data1Idx 网1下标
*			UINT32* data2Idx 网2下标
*			UINT8* data2Staging 二份数据暂存数组
*			UINT32* data2StagingIdx 二份数据暂存数组下标
*输入出参:  无
*输出参数:	无
*返回值:	成功:1 失败:0
*/
static UINT8 TwoNetRepeatParam(ProtclConfigInfoStru* protcl, UINT8* data1, UINT32* data1Idx, UINT8* data2, UINT32* data2Idx, UINT8* data2Staging, UINT32* data2StagingIdx)
{
	UINT8 rtnVal = 0u; /*返回值*/

	if ((NULL != protcl) && (NULL != data1) && (NULL != data1Idx) && (NULL != data2) && (NULL != data2Idx) && (NULL != data2Staging) && (NULL != data2StagingIdx)) /*参数检查*/
	{
		rtnVal = 1u;
	}

	return rtnVal;
}

/*
*函数名:	TwoDevRepeat
*功能描述:	两份设备数据比较去除重复数据
*输入参数:
*			ProtclConfigInfoStru* protcl 协议结构体变量
*			UINT8* data1 一份数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			const UINT32 data1IdxNet 网1当前下标
*			const UINT32 data1Len 一份数据长度
*			UINT8* data2 二份数据(格式:同上)
*			const UINT32 data2Len 二份数据长度
*			const UINT32 net2Len 网2长度
*			const UINT32 data2StagingMaxLen 二份数据暂存数组最大长度
*输入出参:
*			UINT32* data1Idx 数据1下标
*			UINT32* data2Idx 数据2下标
*			UINT32* net2Idx 网2下标
*			UINT8* data2Staging 二份数据暂存数组
*			UINT32* data2StagingIdx 二份数据暂存数组下标
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 TwoDevRepeat(ProtclConfigInfoStru* protcl, UINT8* data1, const UINT32 data1IdxNet, UINT32* data1Idx, const UINT32 data1Len, UINT8* data2, UINT32* data2Idx, const UINT32 data2Len, UINT32* net2Idx, const UINT32 net2Len, UINT8* data2Staging, UINT32* data2StagingIdx, const UINT32 data2StagingMaxLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT16 dev2Len = 0u; /*设备包数据长度*/
	UINT32 dev2UniqueId = 0u; /*设备唯一ID(类型ID+逻辑ID)*/
	UINT8 dev2oppTypePtl = 0u; /*对方设备协议类型*/
	UINT32 net1Len = 0u; /*网1长度*/
	UINT32 net1Idx = 0u; /*网1下标*/
	UINT8 funRtn = 0u; /*调用函数返回值*/
	UINT8 isErr = 0u; /*是否错误*/

	funRtn = TwoDevRepeatParam(protcl, data1, data1Idx, data2, data2Idx, net2Idx, data2Staging, data2StagingIdx);
	if (1u == funRtn) /*调用函数返回正常*/
	{
		if (*data2Idx + 6u < data2Len) /*数据下标合法.6为2字节设备数据长度+4字节设备唯一ID*/
		{
			dev2Len = 2u + ShortFromChar(&data2[*data2Idx]); /*设备数据长度*/
			if ((6u < (UINT32)dev2Len) && (4u + (UINT32)dev2Len <= net2Len)) /*设备数据长度合法*/
			{
				dev2oppTypePtl = protcl->GlobalVar->oppTypePtl[data2[*data2Idx + 2u]];
				dev2UniqueId = LongFromChar(&data2[*data2Idx + 2u]); /*设备唯一ID*/
				if ((data1IdxNet + 4u) <= data1Len) /*数据位置合法*/
				{
					net1Len = 4u + LongFromChar(&data1[data1IdxNet]); /*网包长度*/
					if (net1Len <= data1Len) /*网包长度合法*/
					{
						net1Idx += 4u;
						if (4u < net1Len) /*有设备数据*/
						{
							funRtn = RepeatCheck(dev2oppTypePtl, dev2UniqueId, &data2[*data2Idx], dev2Len, data1, data1Idx, data1Len, data1IdxNet, &net1Idx, net1Len, data2Staging, data2StagingIdx, data2StagingMaxLen);
							if (1u == funRtn) /*调用函数返回值正常*/
							{
								*net2Idx += dev2Len;
								*data2Idx += dev2Len;
								rtnVal = 1u;
							}
							else /*调用函数返回值错误*/
							{
								rtnVal = funRtn;
							}
						}
						else /*无设备数据*/
						{
							if (data1IdxNet == *data1Idx) /*第一次*/
							{
								if (net1Idx == net1Len) /*-< 检查网包长度是否合法*/
								{
									*data1Idx += net1Len; /*-< 设置一份数据下标增网长度*/
								}
								else /*网包长度非法*/
								{
									isErr = 1u; /*-< 设置错误标志为1*/
								}
							}
							if (0u == isErr) /*-< 是否无错误*/
							{
								if (*data2StagingIdx + dev2Len <= data2StagingMaxLen) /*-< 二份数据暂存数组是否有空间*/
								{
									(void)CommonMemCpy(&data2Staging[*data2StagingIdx], data2StagingMaxLen - (*data2StagingIdx), &data2[*data2Idx], dev2Len); /*-< 二份设备数据复制到二份数据暂存数组*/
									*data2StagingIdx += dev2Len; /*-< 设置二份数据暂存长度增设备长度*/

									*net2Idx += dev2Len; /*-< 设置二份数据网下标增设备长度*/
									*data2Idx += dev2Len; /*-< 设置二份数据下标增设备长度*/

									rtnVal = 1u; /*-< 设置函数返回值为1*/
								}
								else /*二份数据暂存数组无空间*/
								{
									rtnVal = DATA2_STAGING_NO; /*-< 设置函数返回值为19*/
								}
							}
							else /*有错误*/
							{
								rtnVal = NO_DATA_NET1_LEN_ILLEGAL; /*-< 设置函数返回值为20*/
							}
						}
					}
					else /*网包长度非法*/
					{
						rtnVal = NET1_LEN_ILLEGAL;
					}
				}
				else /*数据位置非法*/
				{
					rtnVal = DATA1_IDX_ILLEGAL;
				}
			}
			else /*设备数据长度非法*/
			{
				rtnVal = DATA2_DEV_LEN_ILLEGAL;
			}
		}
		else /*数据下标非法*/
		{
			rtnVal = DATA2_IDX_ILLEGAL;
		}
	}

	return rtnVal;
}

/*
*函数名:	TwoDevRepeatParam
*功能描述:	两份设备数据比较去除重复数据函数参数检查
*输入参数:
*			ProtclConfigInfoStru* protcl 协议结构体变量
*			UINT8* data1 一份数据(格式:网络数据{4字节长度+{2字节长度+2字节设备类型ID+2字节逻辑ID+网络数据包}+{N个}}+{N个})
*			UINT8* data2 二份数据(格式:同上)
*			UINT32* data1Idx 数据1下标
*			UINT32* data2Idx 数据2下标
*			UINT32* net2Idx 网2下标
*			UINT8* data2Staging 二份数据暂存数组
*			UINT32* data2StagingIdx 二份数据暂存数组下标
*输入出参:	无
*输出参数:	无
*返回值:	成功:1 失败:0
*/
static UINT8 TwoDevRepeatParam(ProtclConfigInfoStru* protcl, UINT8* data1, UINT32* data1Idx, UINT8* data2, UINT32* data2Idx, UINT32* net2Idx, UINT8* data2Staging, UINT32* data2StagingIdx)
{
	UINT8 rtnVal = 0u; /*返回值*/

	if ((NULL != protcl) && (NULL != data1) && (NULL != data1Idx) && (NULL != data2) && (NULL != data2Idx) && (NULL != net2Idx) && (NULL != data2Staging) && (NULL != data2StagingIdx)) /*参数检查*/
	{
		rtnVal = 1u;
	}

	return rtnVal;
}

/*
*函数名:	RepeatCheck
*功能描述:	重复检查
*输入参数:	ProtclConfigInfoStru* protcl 协议结构体变量
*			const UINT8 dev2OppTypePtl 协议类型
*			const  UINT32 dev2UniqueId 设备唯一ID(类型ID+逻辑ID)
*			UINT8* dev2Data 设备数据(格式:网络协议数据包)
*			UINT16 dev2Len 设备数据长度
*			UINT8* data1 一份数据
*			UINT32* data1Idx 一份数据当前位置
*			const UINT32 data1Len 一份数据长度
*			const UINT32 data1IdxNet 一份数据当前网包位置
*			const  UINT32 net1Len 网1长度
*			UINT8* data2Staging 二份数据暂存数组
*			UINT32* data2StagingIdx 二份数据暂存数组下标
*			const UINT32 data2StagingMaxLen 二份数据暂存数组最大长度
*输入出参:
*			UINT32* net1Idx 网1当前位置
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 RepeatCheck(const UINT8 dev2OppTypePtl, const  UINT32 dev2UniqueId, UINT8* dev2Data, const  UINT16 dev2Len, UINT8* data1, UINT32* data1Idx, const UINT32 data1Len, const UINT32 data1IdxNet, UINT32* net1Idx, const  UINT32 net1Len, UINT8* data2Staging, UINT32* data2StagingIdx, const UINT32 data2StagingMaxLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT8 funRtn = 0u; /*调用函数返回值*/
	UINT8 isBreak = 0u; /*是否退出遍历*/
	UINT8 isFirst = 0u; /*是否第一次*/
	UINT8 isRepeat = 0u; /*是否有重复*/

	funRtn = RepeatCheckParam(dev2Data, data1, data1Idx, net1Idx, data2Staging, data2StagingIdx);
	if (1u == funRtn) /*调用函数返回正常*/
	{
		if (data1IdxNet == *data1Idx) /*第一次处理网1数据*/
		{
			isFirst = 1u;
		}
		while (*net1Idx < net1Len) /*有处理设备数据*/
		{
			funRtn = RepeatDataCheck(&isRepeat, dev2OppTypePtl, dev2UniqueId, &dev2Data[6], dev2Len - 6u, data1, data1IdxNet, data1Len, net1Idx, net1Len);
			if (1u == funRtn) /*调用函数返回正常*/
			{
				if (1u == isRepeat) /*重复*/
				{
					if (0u == isFirst) /*非第一次,不再遍历*/
					{
						isBreak = 1u;
					}
				}
			}
			else /*调用函数返回异常*/
			{
				rtnVal = funRtn;
			}

			if ((1u != funRtn) || (1u == isBreak)) /*调用错误或是退出遍历*/
			{
				break;
			}
		}

		if (1u == funRtn) /*无错误*/
		{
			rtnVal = RepeatCheckSet(isRepeat, isFirst, dev2Data, dev2Len, data1Idx, *net1Idx, net1Len, data2Staging, data2StagingIdx, data2StagingMaxLen);
		}
	}

	return rtnVal;
}

/*
*函数名:	RepeatCheckParam
*功能描述:	重复检查函数参数检查
*输入参数:	ProtclConfigInfoStru* protcl 协议结构体变量
*			UINT8* dev2Data 设备数据
*			UINT8* data1 一份数据
*			UINT32* data1Idx 一份数据当前位置
*			UINT8* data2Staging 二份数据暂存数组
*			UINT32* data2StagingIdx 二份数据暂存数组下标
*			UINT32* net1Idx 网1当前位置
*输入出参:	无
*输出参数:	无
*返回值:	成功:1 失败:0
*/
static UINT8 RepeatCheckParam(UINT8* dev2Data, UINT8* data1, UINT32* data1Idx, UINT32* net1Idx, UINT8* data2Staging, UINT32* data2StagingIdx)
{
	UINT8 rtnVal = 0u; /*返回值*/

	if ((NULL != dev2Data) && (NULL != data1) && (NULL != data1Idx) && (NULL != net1Idx) && (NULL != data2Staging) && (NULL != data2StagingIdx)) /*参数检查*/
	{
		rtnVal = 1u;
	}

	return rtnVal;
}

/*
*函数名:	RepeatCheckSet
*功能描述:	重复检查设置
*输入参数:	UINT8 isRepeat 是否重复
*			UINT8 isFirst 是否第一次
*			UINT8* dev2Data 设备数据(格式:网络协议数据包)
*			UINT16 dev2Len 设备数据长度
*			UINT8* data1 一份数据
*			UINT32* data1Idx 一份数据当前位置
*			const UINT32 data1Len 一份数据长度
*			const UINT32 data1IdxNet 一份数据当前网包位置
*			const  UINT32 net1Len 网1长度
*			UINT8* data2Staging 二份数据暂存数组
*			UINT32* data2StagingIdx 二份数据暂存数组下标
*			const UINT32 data2StagingMaxLen 二份数据暂存数组最大长度
*输入出参:
*			UINT32* net1Idx 网1当前位置
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 RepeatCheckSet(UINT8 isRepeat, UINT8 isFirst, UINT8* dev2Data, UINT16 dev2Len, UINT32* data1Idx, UINT32 net1Idx, UINT32 net1Len, UINT8* data2Staging, UINT32* data2StagingIdx, const UINT32 data2StagingMaxLen)
{
	UINT8 isErr = 0u; /*是否错误*/
	UINT8 rtnVal = 0u; /*返回值*/

	if ((NULL != dev2Data) && (NULL != data1Idx) && (NULL != data2Staging) && (NULL != data2StagingIdx)) /*参数检查*/
	{
		if (0u == isRepeat) /*不重复*/
		{
			if (*data2StagingIdx + dev2Len <= data2StagingMaxLen) /*二份数据暂存数组有空间*/
			{
				(void)CommonMemCpy(&data2Staging[*data2StagingIdx], data2StagingMaxLen - (*data2StagingIdx), &dev2Data[0], dev2Len);
				*data2StagingIdx += dev2Len;
			}
			else /*二份数据暂存数组无空间*/
			{
				isErr = 1u;
			}
		}

		if (0u == isErr) /*无错误*/
		{
			if (1u == isFirst) /*第一次*/
			{
				if (net1Idx == net1Len) /*检查网包长度合法*/
				{
					*data1Idx += net1Len;
					rtnVal = 1u;
				}
				else /*检查网包长度合法*/
				{
					rtnVal = DATA1_NET_LEN_ILLEGAL;
				}
			}
			else /*非第一次*/
			{
				rtnVal = 1u;
			}
		}
		else /*有错误*/
		{
			rtnVal = DATA2_STAGING_NO_SPACE;
		}
	}

	return rtnVal;
}

/*
*函数名:	RepeatDataCheck
*功能描述:	重复数据检查设置
*输入参数:	UINT8* isRepeat 是否重复
*			UINT8 dev2OppTypePtl 协议类型
*			UINT32 devUniqueId 设备唯一ID(类型ID+逻辑ID)
*			UINT8* dev2Data 设备数据(格式:网络协议数据包)
*			UINT16 dev2Len 设备数据长度
*			UINT8* data1 一份数据
*			UINT32* data1Idx 一份数据当前位置
*			const UINT32 data1Len 一份数据长度
*			const UINT32 data1IdxNet 一份数据当前网包位置
*			const  UINT32 net1Len 网1长度
*输入出参:
*			UINT32* net1Idx 网1当前位置
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 RepeatDataCheck(UINT8* isRepeat, UINT8 dev2OppTypePtl, UINT32 dev2UniqueId, UINT8* dev2Data, UINT16 dev2Len, UINT8* data1, UINT32 data1IdxNet, const UINT32 data1Len, UINT32* net1Idx, UINT32 net1Len)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT16 curDevLen = 0u; /*当前设备包数据长度*/
	UINT32 curDevUniqueId = 0u; /*当前设备唯一ID(类型ID+逻辑ID)*/
	UINT8 funRtn = 0u; /*调用函数返回值*/

	funRtn = RepeatDataCheckParam(isRepeat, dev2Data, data1, net1Idx);
	if (1u == funRtn) /*调用函数返回正常*/
	{
		if ((data1IdxNet + 4u) <= data1Len) /*数据位置,长度检查*/
		{
			if ((data1IdxNet + *net1Idx + 6u) < data1Len) /*数据下标有效*/
			{
				curDevLen = ShortFromChar(&data1[data1IdxNet + *net1Idx]); /*设备数据长度*/
				*net1Idx += 2u;
				if ((4u < (UINT32)curDevLen) && (6u + (UINT32)curDevLen <= net1Len)) /*设备数据长度有效*/
				{
					curDevUniqueId = LongFromChar(&data1[data1IdxNet + *net1Idx]); /*当前设备唯一ID*/
					if ((curDevLen == 4u + dev2Len) && (curDevUniqueId == dev2UniqueId))
					{
						funRtn = RepeatValCheck(isRepeat, dev2OppTypePtl, dev2Data, dev2Len, data1, data1IdxNet + *net1Idx + 4u, data1Len);
						if (1u == funRtn) /*调用函数返回正常*/
						{
							*net1Idx += curDevLen;
							rtnVal = 1u;
						}
						else /*调用函数返回异常*/
						{
							rtnVal = funRtn;
						}
					}
					else
					{
						*net1Idx += curDevLen;
						rtnVal = 1u;
					}

				}
			}
		}
	}

	return rtnVal;
}

/*
*函数名:	RepeatDataCheckParam
*功能描述:	重复数据检查设置函数参数检查
*输入参数:	UINT8* isRepeat 是否重复
*			UINT8* dev2Data 设备数据(格式:网络协议数据包)
*			UINT8* data1 一份数据
*			UINT32* net1Idx 网1当前位置
*输入出参:	无
*输出参数:	无
*返回值:	成功:1 失败:0
*/
static UINT8 RepeatDataCheckParam(UINT8* isRepeat, UINT8* dev2Data, UINT8* data1, UINT32* net1Idx)
{
	UINT8 rtnVal = 0u; /*返回值*/

	if ((NULL != isRepeat) && (NULL != dev2Data) && (NULL != data1) && (NULL != net1Idx)) /*参数检查*/
	{
		rtnVal = 1u;
	}

	return rtnVal;
}

/*
*函数名:	RepeatValCheck
*功能描述:	重复值检查
*输入参数:	UINT8 dev2OppTypePtl 协议类型
*			UINT8* dev2Data 设备数据(格式:网络协议数据包)
*			UINT16 devLen 设备数据长度
*			UINT8* data1 一份数据
*			UINT32* data1Idx 一份数据下标
*			const UINT32 data1MaxLen 一份数据最大长度
*输入出参:
*			UINT8* isRepeat 是否重复
*输出参数:	无
*返回值:	成功:1 失败:非1
*/
static UINT8 RepeatValCheck(UINT8* isRepeat, UINT8 dev2OppTypePtl, UINT8* dev2Data, UINT16 devLen, UINT8* data1, UINT32 data1Idx, const UINT32 data1MaxLen)
{
	UINT8 rtnVal = 0u; /*返回值*/
	UINT8 funRtn = 0u; /*调用函数返回值*/
	INT32 cmpRtn = 0; /*比较返回值*/

	funRtn = RepeatValCheckParam(isRepeat, dev2Data, devLen, data1, data1Idx, data1MaxLen);
	if (1u == funRtn) /*调用函数返回正常*/
	{
		if (DSU_PROTCL_SFP == dev2OppTypePtl) /*SFP协议*/
		{
			if (23u <= devLen) /*长度合法*/
			{
				cmpRtn = memcmp(&dev2Data[devLen - 4u], &data1[data1Idx + devLen - 4u], 4u);
				rtnVal = 1u;
			}
			else /*长度非法*/
			{
				rtnVal = DEV_SFP_LEN_ILLEGAL;
			}
		}
		else if (DSU_PROTCL_RSSP == dev2OppTypePtl || DSU_PROTCL_FSFB == dev2OppTypePtl) /*RSSP FSFB协议*/
		{
			if (20u <= devLen) /*长度合法*/
			{
				cmpRtn = memcmp(&dev2Data[devLen - 2u], &data1[data1Idx + devLen - 2u], 2u);
				rtnVal = 1u;
			}
			else /*长度非法*/
			{
				rtnVal = DEV_RSSPI_FSFB_LEN_ILLEGAL;
			}
		}
		else if (DSU_PROTCL_RSSP2 == dev2OppTypePtl) /*RSSPII协议*/
		{
			if (19u <= devLen) /*长度合法*/
			{
				cmpRtn = memcmp(&dev2Data[8], &data1[data1Idx + 8u], 2u);
				rtnVal = 1u;
			}
			else /*长度非法*/
			{
				rtnVal = DEV_RSSPII_LEN_ILLEGAL;
			}
		}
		else /*其他*/
		{
			cmpRtn = memcmp(&dev2Data[0], &data1[data1Idx], devLen);
			rtnVal = 1u;
		}
		if (0 == cmpRtn) /*相同*/
		{
			*isRepeat = 1u;
		}
	}

	return rtnVal;
}

/*
*函数名:	RepeatValCheckParam
*功能描述:	重复值检查函数参数检查
*输入参数:	UINT8* devData 设备数据(格式:网络协议数据包)
*			UINT16 devLen 设备数据长度
*			UINT8* data1 一份数据
*			UINT32* data1Idx 一份数据下标
*			const UINT32 data1MaxLen 一份数据最大长度
*			UINT8* isRepeat 是否重复
*输入出参:	无
*输出参数:	无
*返回值:	成功:1 失败:0
*/
static UINT8 RepeatValCheckParam(UINT8* isRepeat, UINT8* devData, UINT16 devLen, UINT8* data1, UINT32 data1Idx, const UINT32 data1MaxLen)
{
	UINT8 rtnVal = 0u; /*返回值*/

	if ((NULL != isRepeat) && (NULL != devData) && (NULL != data1)) /*参数检查*/
	{
		if (data1Idx + devLen <= data1MaxLen) /*长度合法*/
		{
			rtnVal = 1u;
		}
	}

	return rtnVal;
}