From e610f2dc1ec06e1e8ce04e4055bc7bd1fa4cfaa3 Mon Sep 17 00:00:00 2001 From: stli Date: Sat, 11 Apr 2026 10:27:05 +0800 Subject: [PATCH] Add protobuf COM wrapper --- KeyBorad/KeyBorad/COM/Com_PbCodec.cpp | 142 ++++++++++++++++++++++++++ KeyBorad/KeyBorad/COM/Com_PbCodec.h | 17 +++ docs/host_com_rebuild.md | 25 +++++ 3 files changed, 184 insertions(+) create mode 100644 KeyBorad/KeyBorad/COM/Com_PbCodec.cpp create mode 100644 KeyBorad/KeyBorad/COM/Com_PbCodec.h diff --git a/KeyBorad/KeyBorad/COM/Com_PbCodec.cpp b/KeyBorad/KeyBorad/COM/Com_PbCodec.cpp new file mode 100644 index 0000000..004b29d --- /dev/null +++ b/KeyBorad/KeyBorad/COM/Com_PbCodec.cpp @@ -0,0 +1,142 @@ +#include "COM/Com_PbCodec.h" + +#include "COM/Com_CdcEncode.h" + +namespace +{ + +quint32 Com_Pb_Func_CalcFrameChecksum(const keyboard::cdc::CdcFrame& Frame) +{ + QByteArray ByteArray; + ByteArray.append(static_cast(Frame.head1())); + ByteArray.append(static_cast(Frame.head2())); + ByteArray.append(static_cast(Frame.payload_length())); + ByteArray.append(static_cast(Frame.type())); + ByteArray.append(QByteArray::fromStdString(Frame.payload())); + + return Com_Cdc_Func_CalcChecksum(ByteArray); +} + +keyboard::cdc::CdcFrame Com_Pb_Func_BuildFrame( + keyboard::cdc::CdcPacketType Type, + const keyboard::cdc::CdcPacketBody& Body) +{ + keyboard::cdc::CdcFrame Frame; + std::string PayloadBytes; + + Body.SerializeToString(&PayloadBytes); + + Frame.set_head1(0xAA); + Frame.set_head2(0x55); + Frame.set_payload_length(static_cast(PayloadBytes.size())); + Frame.set_type(Type); + Frame.set_payload(PayloadBytes); + Frame.set_checksum(Com_Pb_Func_CalcFrameChecksum(Frame)); + return Frame; +} + +bool Com_Pb_Func_IsValidFrame(const keyboard::cdc::CdcFrame& Frame) +{ + return (Frame.head1() == 0xAA) && + (Frame.head2() == 0x55) && + (Frame.payload_length() == static_cast(Frame.payload().size())) && + (Frame.checksum() == Com_Pb_Func_CalcFrameChecksum(Frame)); +} + +} // namespace + +bool Com_Pb_Func_SerializeFrame( + const keyboard::cdc::CdcFrame& Frame, + QByteArray* p_ByteArray) +{ + if (p_ByteArray == nullptr) + { + return false; + } + + std::string Bytes; + if (!Frame.SerializeToString(&Bytes)) + { + p_ByteArray->clear(); + return false; + } + + *p_ByteArray = QByteArray(Bytes.data(), static_cast(Bytes.size())); + return true; +} + +bool Com_Pb_Func_ParseFrame( + const QByteArray& ByteArray, + keyboard::cdc::CdcFrame* p_Frame) +{ + if (p_Frame == nullptr) + { + return false; + } + + keyboard::cdc::CdcFrame Frame; + if (!Frame.ParseFromArray(ByteArray.constData(), ByteArray.size())) + { + return false; + } + + if (!Com_Pb_Func_IsValidFrame(Frame)) + { + return false; + } + + *p_Frame = Frame; + return true; +} + +QByteArray Com_Pb_Func_BuildHelloReqFrame() +{ + keyboard::cdc::CdcPacketBody Body; + Body.mutable_hello_req()->set_protocol_version(1); + + const keyboard::cdc::CdcFrame Frame = + Com_Pb_Func_BuildFrame(keyboard::cdc::CDC_PACKET_TYPE_HELLO_REQ, Body); + + QByteArray ByteArray; + if (!Com_Pb_Func_SerializeFrame(Frame, &ByteArray)) + { + return QByteArray(); + } + + return ByteArray; +} + +bool Com_Pb_Func_ParseHelloRspFrame( + const QByteArray& ByteArray, + keyboard::cdc::HelloRsp* p_HelloRsp) +{ + if (p_HelloRsp == nullptr) + { + return false; + } + + keyboard::cdc::CdcFrame Frame; + if (!Com_Pb_Func_ParseFrame(ByteArray, &Frame)) + { + return false; + } + + if (Frame.type() != keyboard::cdc::CDC_PACKET_TYPE_HELLO_RSP) + { + return false; + } + + keyboard::cdc::CdcPacketBody Body; + if (!Body.ParseFromString(Frame.payload())) + { + return false; + } + + if (!Body.has_hello_rsp()) + { + return false; + } + + *p_HelloRsp = Body.hello_rsp(); + return true; +} diff --git a/KeyBorad/KeyBorad/COM/Com_PbCodec.h b/KeyBorad/KeyBorad/COM/Com_PbCodec.h new file mode 100644 index 0000000..af25db1 --- /dev/null +++ b/KeyBorad/KeyBorad/COM/Com_PbCodec.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "../generated/cpp/keyboard.pb.h" + +bool Com_Pb_Func_SerializeFrame( + const keyboard::cdc::CdcFrame& Frame, + QByteArray* p_ByteArray); +bool Com_Pb_Func_ParseFrame( + const QByteArray& ByteArray, + keyboard::cdc::CdcFrame* p_Frame); + +QByteArray Com_Pb_Func_BuildHelloReqFrame(); +bool Com_Pb_Func_ParseHelloRspFrame( + const QByteArray& ByteArray, + keyboard::cdc::HelloRsp* p_HelloRsp); diff --git a/docs/host_com_rebuild.md b/docs/host_com_rebuild.md index 6189d4e..4eff245 100644 --- a/docs/host_com_rebuild.md +++ b/docs/host_com_rebuild.md @@ -82,6 +82,31 @@ Implemented behavior: - `Ack` - `Error` +### Node 3: protobuf thin wrapper + +Files added in this step: + +- `KeyBorad/KeyBorad/COM/Com_PbCodec.h` +- `KeyBorad/KeyBorad/COM/Com_PbCodec.cpp` + +Design notes: + +- stop expanding hand-written typed payload logic +- let protobuf generated code own message encode/decode +- keep only a thin Qt-friendly wrapper + +Implemented behavior: + +- serialize a full `CdcFrame` +- parse and validate a full `CdcFrame` +- build `HelloReq` using generated protobuf types +- parse `HelloRsp` using generated protobuf types + +Current limit: + +- not wired into the project yet +- protobuf runtime include and link setup is still pending + ## COM done criteria For the current project stage, COM is considered done when: