HCoreBase/include/HDProtocolServer.h
2025-08-28 15:00:18 +08:00

154 lines
5.3 KiB
C

/**
* 日期: 2025-08-26
* 作者: coffee
* 描述: 调度协议, 用于多数据口接收数据和发送数据后回复数据临时调度回来
*/
#ifndef __HD_PROTOCOL_SERVER_H__
#define __HD_PROTOCOL_SERVER_H__
#include "HRingBuffer.h"
#include <stdint.h>
#ifndef __COUNT_ARGS_IMPL
#define __COUNT_ARGS_IMPL(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
#endif
#ifndef __COUNT_ARGS
#define __COUNT_ARGS(...) __COUNT_ARGS_IMPL(dummy, ##__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#endif
/**
* demo:
* 1. 设置调度回调函数 HDProtocolSetCallback(HScheduleCallback callback);
* 2. 注册调度数据信息数组 HDProtocolRegisterInfo(HDProtocolServerInfo *info, uint8_t src, void *data, int dataLen);
* 3. HDProtocolRun();
*/
// 再次发送超时时间
#define HDPROTOCOL_DELAY_TIMEOUT (100)
// 数据占用时间
#define HDPROTOCOL_OCCUPY_TIMEOUT (3000)
enum eHDProtocolSupport
{
kHDProtocolNone = 0x00, ///< 无协议, 不阻塞等待
kHDProtocolFpga = 0x01, ///< fpga协议, 独占解析端
kHDProtocolVP = 0x02, ///< vp协议, 独占解析端
};
/**
* @brief 协议信息结构
* @note 协议信息结构里面的buffer需要用户自己分配内存, 通过 HDProtocolInitInfo 初始化传递内存
* 用户只需要读取环状缓冲区即可
*/
typedef struct __attribute__((__packed__)) HDProtocolServerInfo
{
HRingBufferType *readBuff; ///< 读取环状缓冲区, 内存需要用户调用 HDProtocolInitInfo 提供, 最低需要 sizeof(_HRingBufferBase) + 1 的空间
uint8_t supportProtocol; ///< 支持的协议, 用于解析端选择, 避免多路口同时解析
uint8_t src; ///< 源数据口
uint8_t dst; ///< 目标数据口(如果需要始终转发可以修改该项目, 否则默认和src一样)
uint8_t tmpDst; ///< 临时回送目标数据口(用于该指令需要先请求某个数据后才能回复的情况)
uint8_t tmpReadCount : 6; ///< 临时数据最大等待回复次数
uint8_t tmpEnable : 1; ///< 当前临时目标等待数据, 需要等待数据内部标记开启, 数据完成或者超时后自动关闭
uint8_t delayCount; ///< 延时等待次数(默认: 1), 每次等待时间为 HSCHEDULE_DELAY_TIMEOUT
} HDProtocolServerInfo;
/**
* @brief 读取回调函数
* @param info 协议信息
* param isTimeout 是否超时, 1: 表示当前数据已经超时, 协议需要重置让渡给其他解析, 0: 表示当前数据未超时
* @return 返回协议解析长度, 返回0表示解析结束
*/
typedef int (*HDProtocolReadCallback)(HDProtocolServerInfo *info, uint8_t isTimeout);
typedef void (*HDProtocolWriteCallback)(HDProtocolServerInfo *info, const uint8_t *data, int len);
/**
* @brief 设置协议回调函数
* @param readCall 读取回调函数
* @param writeCall 写入回调函数
*/
void HDProtocolSetCallback(HDProtocolReadCallback readCall, HDProtocolWriteCallback writeCall);
/**
* @brief 初始化协议信息结构, 将原始缓冲器转换成环状缓冲区(需要消耗一些字节)
* @param info 协议信息结构
* @param src 源数据口和目标数据口
* @param data 原始缓冲区
* @param dataLen 原始缓冲区长度
*/
void HDProtocolInitInfo(HDProtocolServerInfo *info, uint8_t src, void *data, int dataLen);
/**
* @brief 设置支持的协议
* @param info 协议信息结构
* @param len 支持的协议个数
* @param ... 支持的协议
*/
void _HDProtocolSetSupportProtocol(HDProtocolServerInfo *info, int len, ...);
#define HDProtocolSetSupportProtocol(info, ...) _HDProtocolSetSupportProtocol(info, __COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__)
/**
* @brief 注册协议信息
* @param info 协议信息结构
* @param len 协议信息结构长度
*/
void HDProtocolRegisterInit(HDProtocolServerInfo *info, int len);
/**
* @brief 根据当前路由发送(用于解析数据后回送数据, 如果不是读取回调的时候调用, 则找不到对应路由报错, 返回0)
* @param data 发送数据
* @param len 发送数据长度
* @return 发送成功返回1 失败返回0
*/
uint8_t HDProtocolCurrSend(const void *data, int len);
/**
* @brief 根据目标数据口发送
* @param dst 需要往那个目标数据口发送
* @param data 发送数据
* @param len 发送数据长度
*/
void HDProtocolSendPort(uint8_t dst, const void *data, int len);
/**
* @brief 临时路由发送(用于发送目标端口的数据后, 解析端临时更改目标端口, 通过 HDProtocolGetDest 获取目标端口)
* @param src 回送数据数据路由标记
* @param dst 需要往那个目标数据口发送
* @param data 发送数据
* @param len 发送数据长度
* @param needReadCount 需要读取次数
* @param waitCount 等待次数
*/
void HDProtocolTmpSend(uint8_t src, uint8_t dst, const void *data, int len, uint8_t needReadCount, uint8_t waitCount);
/**
* @brief 获取目标数据口
* @param info 协议信息
* @return 目标数据口
*/
uint8_t HDProtocolGetDest(HDProtocolServerInfo *info);
/**
* @brief 获取当前协议信息
* @return 当前协议信息
*/
HDProtocolServerInfo *HDProtocolGetCurrInfo();
/**
* @brief 告知服务当前对应源端读取数据
* @param src 源数据口
* @param data 读取数据
* @param len 读取数据长度
*/
void HDProtocolRead(uint8_t src, const void *data, int len);
/**
* @brief 运行调度协议
*/
void HDProtocolRun();
#endif // __HD_PROTOCOL_SERVER_H__