HCoreBase/src/HDProtocolServer.c
2025-08-29 10:35:10 +08:00

360 lines
8.9 KiB
C

#include "HDProtocolServer.h"
#include "HRingBuffer.h"
#include "HDLog.h"
#include <stdarg.h>
#include <string.h>
#ifndef HDDelayMs
#define HDDelayMs(ms)
#endif
#define OCCUPIED_MAX (5)
struct __attribute__((__packed__)) OccupiedInfo {
uint32_t occupyTime; ///< 当前数据占用时间(ms), 用于超时
uint8_t protocol; ///< 占用的协议
uint8_t index; ///< 占用的索引
uint8_t enbale : 1; ///< 是否占用
uint8_t waitOccupy : 1; ///< 是否等待占用
};
struct __attribute__((__packed__)) HScheduleRegisterInfo {
HDProtocolReadCallback readCall; ///< 读取回调
HDProtocolWriteCallback writeCall; ///< 写入回调
HDProtocolServerInfo *info; ///< 协议信息
uint8_t infoLen; ///< 协议信息长度
uint8_t useIndex; ///< 当前使用的索引
};
static struct HScheduleRegisterInfo sInfo;
static struct OccupiedInfo sOccupiedInfo[OCCUPIED_MAX];
// 判断当前协议是否占用
static uint8_t IsOccupied(uint8_t currIndex, uint8_t protocol, uint8_t *occupiedIndex)
{
if (currIndex >= OCCUPIED_MAX) {
LogE("index[%d] out of range[%d]", currIndex, OCCUPIED_MAX);
return 0;
}
for (int i = 0; i < OCCUPIED_MAX; ++i) {
if (sOccupiedInfo[i].enbale == 0) {
continue;
}
if ((sOccupiedInfo[i].protocol & protocol) == 0) {
continue;
}
// 占用索引
if (occupiedIndex != NULL) {
*occupiedIndex = i;
}
if (sOccupiedInfo[i].index == currIndex) {
return 0;
}
sOccupiedInfo[i].waitOccupy = 1;
return 1;
}
return 0;
}
static void SetOccupied(uint8_t currIndex, uint8_t protocol, uint8_t enable)
{
if (currIndex >= OCCUPIED_MAX) {
LogE("index[%d] out of range[%d]", currIndex, OCCUPIED_MAX);
return ;
}
uint8_t index = OCCUPIED_MAX;
for (int i = 0; i < OCCUPIED_MAX; ++i) {
if (sOccupiedInfo[i].enbale == 0) {
if (index == OCCUPIED_MAX) {
index = i;
}
continue;
}
// 检查当前索引是否已经使用占用
if (sOccupiedInfo[i].index != currIndex) {
continue;
}
// 如果是关闭的直接关闭掉
if (enable == 0) {
sOccupiedInfo[i].enbale = 0;
sOccupiedInfo[i].index = 0;
sOccupiedInfo[i].protocol = 0;
sOccupiedInfo[i].occupyTime = 0;
sOccupiedInfo[i].waitOccupy = 0;
return ;
}
sOccupiedInfo[i].protocol = protocol;
sOccupiedInfo[i].occupyTime = HDLogGetTime();
return ;
}
if (enable == 0 || index == OCCUPIED_MAX) {
return ;
}
sOccupiedInfo[index].enbale = 1;
sOccupiedInfo[index].index = currIndex;
sOccupiedInfo[index].protocol = protocol;
sOccupiedInfo[index].occupyTime = HDLogGetTime();
}
static void WaitRead(HDProtocolServerInfo *info)
{
if (info->tmpEnable == 0) {
return ;
}
for (int i = 0; i < info->delayCount; ++i) {
for (int j = 0; j < HDPROTOCOL_DELAY_TIMEOUT; ++j) {
HDProtocolRun();
if (info->tmpEnable == 0) {
break;
}
// 读取数据的时候触发的紧急读取不要去睡眠
if (info->run == 0) {
HDDelayMs(1);
}
}
if (info->tmpEnable == 0) {
break;
}
}
info->tmpEnable = 0;
}
static void ParseReadData(int index, int isTimeout)
{
sInfo.useIndex = index;
const int len = sInfo.readCall(&sInfo.info[index], isTimeout);
sInfo.useIndex = sInfo.infoLen;
if (len == 0 && sInfo.info[index].tmpEnable) {
// 临时路由转发数据
if (sInfo.info[index].tmpReadCount > 0) {
--sInfo.info[index].tmpReadCount;
}
if (sInfo.info[index].tmpReadCount == 0) {
sInfo.info[index].tmpEnable = 0;
}
}
if (isTimeout) {
sInfo.info[index].tmpEnable = 0;
}
SetOccupied(index, sInfo.info[index].supportProtocol, len == 0 ? 0 : 1);
}
void HDProtocolSetCallback(HDProtocolReadCallback readCall, HDProtocolWriteCallback writeCall)
{
sInfo.readCall = readCall;
sInfo.writeCall = writeCall;
}
void HDProtocolInitInfo(HDProtocolServerInfo *info, uint8_t src, void *data, int dataLen)
{
if (info == NULL) {
return ;
}
memset(info, 0, sizeof(HDProtocolServerInfo));
info->readBuff = data;
HRingbufferInit8(info->readBuff, dataLen);
info->delayCount = 1;
info->src = src;
info->dst = src;
}
void _HDProtocolSetSupportProtocol(HDProtocolServerInfo *info, int len, ...)
{
if (info == NULL) {
return;
}
va_list args;
va_start(args, len);
for (int i = 0; i < len; ++i) {
info->supportProtocol |= (1 << va_arg(args, int));
}
va_end(args);
}
void HDProtocolRegisterInit(HDProtocolServerInfo *info, int len)
{
sInfo.info = info;
sInfo.infoLen = len;
}
uint8_t HDProtocolCurrSend(const void *data, int len)
{
HDProtocolServerInfo *info = HDProtocolGetCurrInfo();
if (info == NULL) {
LogD("curr not read call");
return 0;
}
WaitRead(info);
sInfo.writeCall(info, (const uint8_t *)data, len);
return 1;
}
void HDProtocolSendPort(uint8_t dst, const void *data, int len)
{
if (sInfo.writeCall == NULL || sInfo.info == NULL) {
return;
}
if (dst >= sInfo.infoLen) {
LogE("index[%d] is out of range[%d]", dst, sInfo.infoLen);
return;
}
WaitRead(&sInfo.info[dst]);
sInfo.writeCall(&sInfo.info[dst], (const uint8_t *)data, len);
}
void HDProtocolTmpSend(uint8_t src, uint8_t dst, const void *data, int len, uint8_t needReadCount, uint8_t waitCount)
{
if (sInfo.writeCall == NULL || sInfo.info == NULL) {
return;
}
if (src >= sInfo.infoLen) {
LogE("index[%d] is out of range[%d]", src, sInfo.infoLen);
return;
}
WaitRead(&sInfo.info[src]);
sInfo.info[src].tmpEnable = 1;
sInfo.info[src].tmpDst = dst;
sInfo.info[src].delayCount = waitCount;
sInfo.info[src].tmpReadCount = needReadCount;
sInfo.writeCall(&sInfo.info[src], (const uint8_t *)data, len);
}
uint8_t HDProtocolGetDest(HDProtocolServerInfo *info)
{
if (info == NULL) {
return 0;
}
if (info->tmpEnable) {
return info->tmpDst;
}
return info->dst;
}
HDProtocolServerInfo *HDProtocolGetCurrInfo()
{
if (sInfo.useIndex >= sInfo.infoLen) {
return NULL;
}
return &sInfo.info[sInfo.useIndex];
}
void HDProtocolRead(uint8_t src, const void *data, int len)
{
if (sInfo.readCall == NULL || sInfo.info == NULL) {
return;
}
if (src >= sInfo.infoLen) {
LogE("index[%d] is out of range[%d]", src, sInfo.infoLen);
return;
}
if (sInfo.info[src].readBuff == NULL) {
LogE("readBuff is NULL");
return;
}
const uint8_t *srcData = (const uint8_t *)data;
uint8_t occupy = 0xff;
sInfo.info[src].run = 1;
for (int i = 0; i < len; ++i) {
if (HRingBufferFull(sInfo.info[src].readBuff)) {
// 只需要检查一次
if (occupy == 0xff) {
occupy = IsOccupied(src, sInfo.info[src].supportProtocol, NULL);
}
// 检查是否占用
if (occupy == 0) {
ParseReadData(src, 0);
}
}
HRingBufferAddDataOver(sInfo.info[src].readBuff, srcData[i]);
}
sInfo.info[src].run = 0;
}
void HDProtocolRun()
{
if (sInfo.readCall == NULL || sInfo.info == NULL) {
return;
}
for (int i = 0; i < sInfo.infoLen; ++i) {
if (HRingBufferEmpty(sInfo.info[i].readBuff)) {
continue;
}
if (i >= OCCUPIED_MAX) {
LogE("index[%d] is out of range[%d]", i, OCCUPIED_MAX);
break;
}
// 有之前的数据已经占用了, 并且检查是否超时
uint8_t occupiedIndex = OCCUPIED_MAX;
if (IsOccupied(i, sInfo.info[i].supportProtocol, &occupiedIndex)) {
// 解析被占用, 检查超时
if (HDLogGetTime() - sOccupiedInfo[occupiedIndex].occupyTime <= HDPROTOCOL_OCCUPY_TIMEOUT) {
continue;
}
// 通知协议超时
ParseReadData(occupiedIndex, 1);
// 如果还占用, 说明用户那边自己要求继续占用
if (IsOccupied(i, sInfo.info[i].supportProtocol, &occupiedIndex)) {
continue;
}
}
uint8_t waitTime = 0;
if (occupiedIndex < OCCUPIED_MAX && sOccupiedInfo[occupiedIndex].waitOccupy) {
// 还有其他协议等待抢占, 检查时间
if (HDLogGetTime() - sOccupiedInfo[occupiedIndex].occupyTime > HDPROTOCOL_OCCUPY_TIMEOUT) {
waitTime = 1;
}
}
ParseReadData(i, waitTime);
}
}