diff --git a/KeyBorad/KeyBorad/COM/Com_ProtoCodec.cpp b/KeyBorad/KeyBorad/COM/Com_ProtoCodec.cpp new file mode 100644 index 0000000..35a456c --- /dev/null +++ b/KeyBorad/KeyBorad/COM/Com_ProtoCodec.cpp @@ -0,0 +1,59 @@ +#include "COM/Com_ProtoCodec.h" + +#include "COM/Com_CdcDecode.h" +#include "COM/Com_CdcEncode.h" + +namespace +{ + +quint16 Com_Func_ReadLe16(const QByteArray& ByteArray, int Offset) +{ + return static_cast( + static_cast(ByteArray.at(Offset)) | + (static_cast(static_cast(ByteArray.at(Offset + 1))) << 8)); +} + +} // namespace + +bool Com_ProtoCodec_ParseFrame(const QByteArray& ByteArray, Packet* p_Packet) +{ + return Com_Cdc_Func_ParseFrame(ByteArray, p_Packet); +} + +bool Com_ProtoCodec_TryTakeFrame(QByteArray* p_Buffer, Packet* p_Packet) +{ + return Com_Cdc_Func_TryTakeFrame(p_Buffer, p_Packet); +} + +QByteArray Com_ProtoCodec_BuildHelloReq() +{ + const Packet_HelloReq HelloReq; + return Com_Cdc_Func_BuildHelloReq(HelloReq); +} + +bool Com_ProtoCodec_IsHelloRsp(const Packet& PacketData) +{ + return (PacketData.type == Com_Type_HelloRsp) && + (PacketData.data.size() == Packet_len::Com_Len_HelloRsp); +} + +bool Com_ProtoCodec_ParseHelloRsp( + const Packet& PacketData, + Packet_HelloRsp* p_HelloRsp) +{ + if ((p_HelloRsp == nullptr) || !Com_ProtoCodec_IsHelloRsp(PacketData)) + { + return false; + } + + Packet_HelloRsp HelloRsp; + HelloRsp.ProtocolVersion = static_cast(PacketData.data.at(0)); + HelloRsp.VendorId = Com_Func_ReadLe16(PacketData.data, 1); + HelloRsp.ProductId = Com_Func_ReadLe16(PacketData.data, 3); + HelloRsp.FirmwareMajor = static_cast(PacketData.data.at(5)); + HelloRsp.FirmwareMinor = static_cast(PacketData.data.at(6)); + HelloRsp.CapabilityFlags = Com_Func_ReadLe16(PacketData.data, 7); + + *p_HelloRsp = HelloRsp; + return true; +} diff --git a/KeyBorad/KeyBorad/COM/Com_ProtoCodec.h b/KeyBorad/KeyBorad/COM/Com_ProtoCodec.h new file mode 100644 index 0000000..a99e140 --- /dev/null +++ b/KeyBorad/KeyBorad/COM/Com_ProtoCodec.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "COM/Com_Cdc.h" + +bool Com_ProtoCodec_ParseFrame(const QByteArray& ByteArray, Packet* p_Packet); +bool Com_ProtoCodec_TryTakeFrame(QByteArray* p_Buffer, Packet* p_Packet); + +QByteArray Com_ProtoCodec_BuildHelloReq(); +bool Com_ProtoCodec_IsHelloRsp(const Packet& PacketData); +bool Com_ProtoCodec_ParseHelloRsp( + const Packet& PacketData, + Packet_HelloRsp* p_HelloRsp); diff --git a/KeyBorad/KeyBorad/KeyBorad.vcxproj b/KeyBorad/KeyBorad/KeyBorad.vcxproj index 8ab9680..0aa0a86 100644 --- a/KeyBorad/KeyBorad/KeyBorad.vcxproj +++ b/KeyBorad/KeyBorad/KeyBorad.vcxproj @@ -96,6 +96,8 @@ + + diff --git a/KeyBorad/KeyBorad/KeyBorad.vcxproj.filters b/KeyBorad/KeyBorad/KeyBorad.vcxproj.filters index 4a8ba16..fbe6f25 100644 --- a/KeyBorad/KeyBorad/KeyBorad.vcxproj.filters +++ b/KeyBorad/KeyBorad/KeyBorad.vcxproj.filters @@ -29,6 +29,12 @@ Header Files + + Source Files + + + Header Files + Source Files diff --git a/docs/host_com_rebuild.md b/docs/host_com_rebuild.md new file mode 100644 index 0000000..88161a4 --- /dev/null +++ b/docs/host_com_rebuild.md @@ -0,0 +1,58 @@ +# Host COM Rebuild + +## Goal + +Keep the protocol layer small and explicit. + +The COM layer should: + +- define packet-facing helpers +- own frame parsing and packet building +- avoid transport concerns +- avoid UI and session concerns + +## Completed Nodes + +### Node 1: legacy protocol baseline + +Files already present before this step: + +- `KeyBorad/KeyBorad/COM/Com_Cdc.h` +- `KeyBorad/KeyBorad/COM/Com_CdcEncode.h` +- `KeyBorad/KeyBorad/COM/Com_CdcEncode.cpp` +- `KeyBorad/KeyBorad/COM/Com_CdcDecode.h` +- `KeyBorad/KeyBorad/COM/Com_CdcDecode.cpp` + +Design notes: + +- these files preserve the old packet format +- they already encode and decode complete CDC frames +- they also contain per-packet payload helpers + +### Node 2: unified protocol entry + +Files added in this step: + +- `KeyBorad/KeyBorad/COM/Com_ProtoCodec.h` +- `KeyBorad/KeyBorad/COM/Com_ProtoCodec.cpp` + +Design notes: + +- provides a thin and readable entry point for higher layers +- keeps `DRI` from depending on packet parsing +- keeps `LGC` from depending on low-level byte layout details +- starts from the smallest useful handshake path + +Implemented behavior: + +- build `HelloReq` frame +- validate whether a parsed packet is `HelloRsp` +- decode `HelloRsp` +- forward frame parsing and stream extraction to the existing low-level codec + +## Next COM nodes + +- bitmap encode/decode helper +- ack/error helper +- time sync and theme helper +- replace direct `Com_Cdc*` calls in higher layers with `Com_ProtoCodec*`