462 lines
9.1 KiB
C
462 lines
9.1 KiB
C
|
||
#define _IN_COMM_C
|
||
#include "comm.h"
|
||
#include "crc16.h"
|
||
|
||
|
||
//--------------------------------------------------------------------------------------------------
|
||
|
||
// 读空缓冲区
|
||
// 读空缓冲区
|
||
int ReadBuffEmpty(DataExFuns * funs)
|
||
{
|
||
int rslt, len;
|
||
int rdlen;
|
||
#define ONCE_READ 16
|
||
u8 tempbuf[ONCE_READ];
|
||
|
||
len = funs->GetRsvLen();
|
||
|
||
while (len > 0)
|
||
{
|
||
if (len < ONCE_READ)
|
||
{
|
||
rdlen = len;
|
||
}
|
||
else
|
||
{
|
||
rdlen = ONCE_READ;
|
||
}
|
||
rslt = funs->GetCommData(tempbuf, rdlen);
|
||
|
||
if (rslt <= 0)
|
||
{
|
||
rslt = 0;
|
||
break;
|
||
}
|
||
len -= rslt;
|
||
}
|
||
return len;
|
||
}
|
||
|
||
//--------------------------------------------------------------------------------------------------
|
||
// 功能: 从通讯口接收缓冲区中得到一个数据包,
|
||
// 只能取得普通数据包结构. 如果数据包还有附加数据, 那么需要用 GetExCommData 函数取得
|
||
// 参数: pPacket, 数据包指针
|
||
// 返回: >=0, 成功取得一个数据包,包括定长数据包和可变长度数据包,返回值为数据包长度
|
||
// -1, 参数错误
|
||
// -2, CRC错误
|
||
// -3, 数据不足
|
||
// -4, 没有找到同步序列
|
||
// -5,等待接收数据超时
|
||
// -6, 数据包参数错误
|
||
// -7, 附加数据CRC错误
|
||
// -8, 发生未知错误
|
||
|
||
// 结果: 如果正确取得数据包,或通讯口没有命令, 循环队列尾指针回向后移动
|
||
|
||
#define MAX_TCP_PACKET 1500
|
||
|
||
|
||
typedef struct
|
||
{
|
||
int len; // 已读取数据长度
|
||
u8 buff[LEN_NORMAL_PACKET+MAX_TCP_PACKET]; // 接收缓冲区
|
||
|
||
}GetPacketCtrl;
|
||
|
||
GetPacketCtrl g_gtpCtrl = {0};
|
||
|
||
#define MAX_ONCE_SCAN (LEN_NORMAL_PACKET) // 一次扫描最大字节数
|
||
|
||
/*
|
||
* return: -1,参数错误
|
||
* -2,CRC校验错误
|
||
* -3,没有足够的数据
|
||
*/
|
||
int GetANormalPacket(DataExFuns * funs, DataPacket * pPacket)
|
||
{
|
||
int rslt, len;
|
||
int i;
|
||
int phase;
|
||
int status; // 同步序列 1,FLDP 2,VLDP
|
||
int exlen;
|
||
int begidx;
|
||
|
||
u8 temp;
|
||
u8 rdBuf[LEN_NORMAL_PACKET];
|
||
DataPacket * pDat = (DataPacket *)(rdBuf);
|
||
|
||
if (funs == NULL || pPacket == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
// 读取一次数据包到缓冲区
|
||
if (g_gtpCtrl.len < LEN_NORMAL_PACKET + MAX_EXDP_LEN)
|
||
{
|
||
len = funs->GetRsvLen(); // 读取已接收数据长度
|
||
|
||
if (len <= 0)
|
||
{
|
||
rslt = -3; // 没有足够数据
|
||
}
|
||
else
|
||
{
|
||
if (len + g_gtpCtrl.len <= MAX_TCP_PACKET)
|
||
{
|
||
rslt = funs->GetCommData(&(g_gtpCtrl.buff[g_gtpCtrl.len]), len); // 读取一段数据
|
||
}
|
||
else
|
||
{
|
||
// printf("Get a big packet, len=%d\r\n", len);
|
||
rslt = funs->GetCommData(&(g_gtpCtrl.buff[g_gtpCtrl.len]), MAX_TCP_PACKET-g_gtpCtrl.len); // 读取一段数据
|
||
}
|
||
|
||
g_gtpCtrl.len += rslt; // 实际数据长度增加
|
||
// printf("load a packet to buff, len=%d, buflen=%d\r\n", len, g_gtpCtrl.len);
|
||
}
|
||
}
|
||
|
||
len = g_gtpCtrl.len;
|
||
if (len < LEN_NORMAL_PACKET)
|
||
{
|
||
rslt = -3;
|
||
return rslt; // 没有足够数据
|
||
}
|
||
|
||
i = 0; // 扫描字节计数器
|
||
begidx = 0; // 正确数据包起始计数器
|
||
phase = 0;
|
||
status = 0;
|
||
rslt = 0;
|
||
|
||
while(phase < LEN_NORMAL_PACKET)
|
||
{
|
||
if (phase == 0 && i > MAX_ONCE_SCAN)
|
||
{
|
||
rslt = -4;
|
||
break; // 查找同步序列超出最大单次扫描字节数
|
||
}
|
||
|
||
if (i < g_gtpCtrl.len)
|
||
{
|
||
temp = g_gtpCtrl.buff[i];
|
||
i++; // 扫描字数增加
|
||
}
|
||
else
|
||
{
|
||
// printf("data not enough\r\n");
|
||
rslt = -3; // 数据不足
|
||
break;
|
||
}
|
||
|
||
pDat->buff.normal[phase] = temp; // 保存数据
|
||
if (phase < DP_SYNC_LEN) // 识别同步序列
|
||
{
|
||
if (phase == 0)
|
||
{
|
||
if (temp == FLDP_SYNC[0])
|
||
{
|
||
begidx = i-1;
|
||
status = 1;
|
||
}
|
||
else if (temp == VLDP_SYNC[0])
|
||
{
|
||
begidx = i-1;
|
||
status = 2;
|
||
}
|
||
else
|
||
{
|
||
begidx = i;
|
||
status = 0;
|
||
phase = 0;
|
||
rslt = 0; // 非同步序列,继续扫描
|
||
continue;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (status == 1)
|
||
{
|
||
if (temp != FLDP_SYNC[phase]) // 同步序列不正确,继续扫描
|
||
{
|
||
begidx = 0;
|
||
status = 0;
|
||
phase = 0;
|
||
rslt = 0;
|
||
continue;
|
||
}
|
||
}
|
||
else if (status == 2)
|
||
{
|
||
if (temp != VLDP_SYNC[phase]) // 同步序列不正确,继续扫描
|
||
{
|
||
begidx = 0;
|
||
status = 0;
|
||
phase = 0;
|
||
rslt = 0;
|
||
continue;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
begidx = 0;
|
||
status = 0;
|
||
phase = 0;
|
||
rslt = -8;
|
||
printf("1. error status in GetANormalPacket\r\n");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
phase++;
|
||
}
|
||
|
||
if (phase >= LEN_NORMAL_PACKET) // 得到数据包
|
||
{
|
||
u16 crc;
|
||
crc = CalcCrc16(pDat->normal.content, DP_CONT_LEN);
|
||
if (crc == pDat->normal.crc)
|
||
{
|
||
// 得到正确数据包
|
||
memcpy(pPacket, pDat, LEN_NORMAL_PACKET);
|
||
// printf("GetANormalPacket ok\r\n");
|
||
rslt = LEN_NORMAL_PACKET;
|
||
}
|
||
else
|
||
{
|
||
// CRC 不正确
|
||
begidx = i;
|
||
printf("2. crc error in GetANormalPacket\r\n");
|
||
rslt = -2;
|
||
}
|
||
}
|
||
|
||
if (rslt == LEN_NORMAL_PACKET) // 正确得到
|
||
{
|
||
if (memcmp(pPacket->normal.sync, VLDP_SYNC, DP_SYNC_LEN) == 0) // 是可变长度数据包 vldp
|
||
{
|
||
// 附加数据
|
||
exlen = pPacket->vldp.exlen;
|
||
if (exlen > MAX_EXDP_LEN)
|
||
{
|
||
begidx += LEN_NORMAL_PACKET+exlen;
|
||
printf("data exlen error, len=%d\r\n", exlen);
|
||
rslt = -6; // 数据包参数错误
|
||
}
|
||
else if (exlen == 0)
|
||
{
|
||
begidx += LEN_NORMAL_PACKET;
|
||
rslt = LEN_NORMAL_PACKET;
|
||
}
|
||
else if (exlen + LEN_NORMAL_PACKET > g_gtpCtrl.len)
|
||
{
|
||
// 数据不足, 暂时退出
|
||
// printf("exdata not enough, exlen=%d, g_gtpCtrl.len=%d\r\n", exlen, g_gtpCtrl.len);
|
||
rslt = -3; // 数据不足
|
||
}
|
||
else
|
||
{
|
||
// 20240606 ljs 修复拷贝数据时的地址错误
|
||
#if (1)
|
||
// 增加扩展数据CRC校验(1k字节校验耗时约1ms)
|
||
u16 crc;
|
||
crc = CalcCrc16(&g_gtpCtrl.buff[i], exlen);
|
||
if (crc == pDat->vldp.excrc)
|
||
{
|
||
memcpy(pPacket->buff.exData, &(g_gtpCtrl.buff[i]), exlen); // 拷贝数据
|
||
if (exlen < MAX_EXDP_LEN)
|
||
{
|
||
pPacket->buff.exData[exlen] = 0;
|
||
}
|
||
rslt = LEN_NORMAL_PACKET+exlen;
|
||
}
|
||
else
|
||
{
|
||
printf("3. excrc error in GetANormalPacket\r\n");
|
||
rslt = -2;
|
||
}
|
||
begidx += LEN_NORMAL_PACKET+exlen;
|
||
#else
|
||
begidx += LEN_NORMAL_PACKET+exlen;
|
||
memcpy(pPacket->buff.exData, &(g_gtpCtrl.buff[i]), exlen); // 拷贝数据
|
||
if (exlen < MAX_EXDP_LEN)
|
||
{
|
||
pPacket->buff.exData[exlen] = 0;
|
||
}
|
||
rslt = LEN_NORMAL_PACKET+exlen;
|
||
#endif
|
||
}
|
||
}
|
||
else
|
||
{
|
||
begidx += LEN_NORMAL_PACKET; // 固定长度数据包
|
||
}
|
||
}
|
||
|
||
// 拷贝剩余数据到最前端
|
||
if (begidx > 0 && begidx <= g_gtpCtrl.len)
|
||
{
|
||
if (begidx < g_gtpCtrl.len)
|
||
{
|
||
// printf("copy data, begidx=%d, len=%d\r\n", begidx, (g_gtpCtrl.len - begidx));
|
||
memcpy(&(g_gtpCtrl.buff[0]), &g_gtpCtrl.buff[begidx], (g_gtpCtrl.len - begidx));
|
||
}
|
||
g_gtpCtrl.len -= begidx;
|
||
begidx = 0;
|
||
}
|
||
else if (begidx < 0)
|
||
{
|
||
printf("beginidx < 0\r\n");
|
||
}
|
||
else if (begidx > g_gtpCtrl.len)
|
||
{
|
||
g_gtpCtrl.len = 0;
|
||
printf("begidx=%d > g_gtpCtrl.len=%d, set g_gtpCtrl.len = 0\r\n", begidx, g_gtpCtrl.len);
|
||
}
|
||
else
|
||
{
|
||
}
|
||
|
||
return rslt;
|
||
}
|
||
|
||
//--------------------------------------------------------------------------------------------------
|
||
|
||
// 功能: 添加数据到发送队列中, 通过通讯口发送数据
|
||
// 参数: pPacket, 需要发送的数据,已经正确存放在了相应字段。
|
||
// 结果:
|
||
// 0, 可以发送, 添加到了发送数据队列中
|
||
// -1, 参数错误
|
||
// -2,发送错误
|
||
// 1, 队列已满, 不能发送
|
||
int SendAPacket(DataExFuns * funs, DataPacket * pPacket, int waittime)
|
||
{
|
||
int rslt;
|
||
int freelen, sendlen;
|
||
|
||
if (pPacket == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if (memcmp(pPacket->normal.sync, FLDP_SYNC, DP_SYNC_LEN) == 0)
|
||
{
|
||
sendlen = LEN_NORMAL_PACKET;
|
||
}
|
||
else if (memcmp(pPacket->normal.sync, VLDP_SYNC, DP_SYNC_LEN) == 0)
|
||
{
|
||
sendlen = LEN_NORMAL_PACKET + pPacket->vldp.exlen;
|
||
}
|
||
else
|
||
{
|
||
printf("para err, not a corrected packet\r\n");
|
||
return -1;
|
||
}
|
||
|
||
rslt = 0;
|
||
do
|
||
{
|
||
freelen = funs->GetTrsFreeLen();
|
||
if (freelen <= 0) // 可能网络未连接
|
||
{
|
||
// printf("error at call GetTrsFreeLen, freelen=%d\r\n", freelen);
|
||
rslt = -2;
|
||
break;
|
||
}
|
||
if (freelen >= sendlen)
|
||
{
|
||
break;
|
||
}
|
||
|
||
waittime--;
|
||
if (waittime <= 0)
|
||
{
|
||
rslt = 1;
|
||
// printf("buff is full in SendAPacket, timout\r\n");
|
||
break;
|
||
}
|
||
if (funs->Delay != NULL)
|
||
{
|
||
funs->Delay(1);
|
||
}
|
||
}while(1);
|
||
|
||
if (rslt == 0)
|
||
{
|
||
rslt = funs->SendCommData(pPacket->datbuff, sendlen);
|
||
if (rslt != sendlen)
|
||
{
|
||
printf("error at call SendCommData, rslt=%d\r\n", rslt);
|
||
return -2;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//printf("error:Not SendCommData\r\n");
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
//--------------------------------------------------------------------------------------------------
|
||
|
||
// 功能: 打包一个固定长度数据包
|
||
// 参数:
|
||
// pPacket, 需要打包的数据包,其中除了sync和crc的部分已经就绪
|
||
// 结果:
|
||
// 0, 打包好数据
|
||
// -1, 参数错误
|
||
|
||
int PacketAFLDP(DataPacket * pPacket)
|
||
{
|
||
if (pPacket == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
memcpy(pPacket->normal.sync, FLDP_SYNC, DP_SYNC_LEN);
|
||
pPacket->normal.crc = CalcCrc16(pPacket->normal.content, DP_CONT_LEN);
|
||
|
||
return 0;
|
||
}
|
||
|
||
//--------------------------------------------------------------------------------------------------
|
||
|
||
// 功能: 打包一个可变长度数据包
|
||
// 参数: pPacket, 需要打包的数据包,需要填充其中的 SYNC EXLEN EXCRC 和 EXDAT 等部分
|
||
// pExdat, 附加数据,可以为空
|
||
// exlen,附加数据长度,可以为0
|
||
// 结果:
|
||
// 0, 打包好数据
|
||
// -1, 参数错误
|
||
// -2,
|
||
|
||
int PacketAVLDP(DataPacket * pPacket, const u8 * pExdat, u16 exlen)
|
||
{
|
||
if (pPacket == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if (pExdat == NULL)
|
||
{
|
||
exlen = 0;
|
||
}
|
||
|
||
memcpy(pPacket->vldp.sync, VLDP_SYNC, DP_SYNC_LEN);
|
||
pPacket->vldp.exlen = exlen;
|
||
pPacket->vldp.excrc = CalcCrc16(pExdat, exlen);
|
||
pPacket->vldp.crc = CalcCrc16(pPacket->normal.content, DP_CONT_LEN);
|
||
if (exlen != 0 && pPacket->vldp.exData != pExdat)
|
||
{
|
||
memcpy(pPacket->vldp.exData, pExdat, exlen);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
//--------------------------------------------------------------------------------------------------
|
||
|
||
|