#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; } //--------------------------------------------------------------------------------------------------