Remove legacy COM codec

This commit is contained in:
2026-04-11 10:33:07 +08:00
parent e610f2dc1e
commit 9ebd3ddc30
9 changed files with 47 additions and 844 deletions

View File

@@ -1,121 +0,0 @@
#pragma once
#include <QtCore/QByteArray>
#include <QtCore/QtGlobal>
struct Packet_len
{
static const quint8 Com_Len_UnKnow = 0;
static const quint8 Com_Len_HelloReq = 1;
static const quint8 Com_Len_HelloRsp = 9;
static const quint8 Com_Len_Bitmap = 29;
static const quint8 Com_Len_FunctionKeyEvent = 3;
static const quint8 Com_Len_LedState = 1;
static const quint8 Com_Len_TimeSync = 16;
static const quint8 Com_Len_ThemeRgb = 3;
static const quint8 Com_Len_Ack = 1;
static const quint8 Com_Len_Error = 2;
};
enum Packet_Type : quint8
{
Com_Type_UnKnow = 0x00,
Com_Type_HelloReq = 0x01,
Com_Type_HelloRsp = 0x02,
Com_Type_Bitmap = 0x10,
Com_Type_FunctionKeyEvent = 0x20,
Com_Type_LedState = 0x21,
Com_Type_TimeSync = 0x30,
Com_Type_ThemeRgb = 0x31,
Com_Type_Ack = 0x7E,
Com_Type_Error = 0x7F
};
enum Key_Action : quint8
{
Key_Action_Release = 0x00,
Key_Action_Press = 0x01
};
enum Error_Code : quint8
{
Error_Code_None = 0x00,
Error_Code_UnknownType = 0x01,
Error_Code_InvalidLength = 0x02,
Error_Code_InvalidParam = 0x03,
Error_Code_NotReady = 0x04
};
struct Packet
{
quint8 Com_Packet_Head1 = 0xAA;
quint8 Com_Packet_Head2 = 0x55;
quint8 len = Packet_len::Com_Len_UnKnow;
Packet_Type type = Com_Type_UnKnow;
QByteArray data;
};
struct Packet_HelloReq
{
quint8 ProtocolVersion = 0x01;
};
struct Packet_HelloRsp
{
quint8 ProtocolVersion = 0x01;
quint16 VendorId = 0;
quint16 ProductId = 0;
quint8 FirmwareMajor = 0;
quint8 FirmwareMinor = 0;
quint16 CapabilityFlags = 0;
};
struct Packet_Bitmap
{
QByteArray UsageBitmap = QByteArray(Packet_len::Com_Len_Bitmap, 0);
};
struct Packet_FunctionKeyEvent
{
quint16 Usage = 0;
quint8 Action = Key_Action_Release;
};
struct Packet_LedState
{
quint8 LedMask = 0;
};
struct Packet_TimeSync
{
quint8 Version = 1;
quint8 Flags = 0;
quint16 TimezoneMin = 0;
quint64 UtcMs = 0;
quint32 AccuracyMs = 0;
};
struct Packet_ThemeRgb
{
quint8 Red = 0;
quint8 Green = 0;
quint8 Blue = 0;
};
struct Packet_Ack
{
quint8 AckedType = 0;
};
struct Packet_Error
{
quint8 ErrorType = 0;
quint8 ErrorCode = Error_Code_None;
};

View File

@@ -1,424 +0,0 @@
#include "COM/Com_CdcDecode.h"
#include "COM/Com_CdcEncode.h"
namespace
{
constexpr quint8 COM_CDC_CONST_PACKET_HEAD1 = 0xAA;
constexpr quint8 COM_CDC_CONST_PACKET_HEAD2 = 0x55;
constexpr int COM_CDC_CONST_FRAME_OVERHEAD = 5;
constexpr int COM_CDC_CONST_MAX_PAYLOAD_LENGTH = 64;
quint16 Com_Cdc_Func_ReadLe16(const QByteArray& ByteArray, int Offset)
{
return static_cast<quint16>(
static_cast<quint8>(ByteArray.at(Offset)) |
(static_cast<quint16>(static_cast<quint8>(ByteArray.at(Offset + 1))) << 8));
}
quint32 Com_Cdc_Func_ReadLe32(const QByteArray& ByteArray, int Offset)
{
quint32 Value = 0;
for (int Index = 0; Index < 4; ++Index)
{
Value |= static_cast<quint32>(static_cast<quint8>(ByteArray.at(Offset + Index))) <<
(Index * 8);
}
return Value;
}
quint64 Com_Cdc_Func_ReadLe64(const QByteArray& ByteArray, int Offset)
{
quint64 Value = 0;
for (int Index = 0; Index < 8; ++Index)
{
Value |= static_cast<quint64>(static_cast<quint8>(ByteArray.at(Offset + Index))) <<
(Index * 8);
}
return Value;
}
bool Com_Cdc_Func_IsKnownLengthValid(Packet_Type Type, quint8 DataLength)
{
switch (Type)
{
case Com_Type_UnKnow:
return DataLength == Packet_len::Com_Len_UnKnow;
case Com_Type_HelloReq:
return DataLength == Packet_len::Com_Len_HelloReq;
case Com_Type_HelloRsp:
return DataLength == Packet_len::Com_Len_HelloRsp;
case Com_Type_Bitmap:
return DataLength == Packet_len::Com_Len_Bitmap;
case Com_Type_FunctionKeyEvent:
return DataLength == Packet_len::Com_Len_FunctionKeyEvent;
case Com_Type_LedState:
return DataLength == Packet_len::Com_Len_LedState;
case Com_Type_TimeSync:
return DataLength == Packet_len::Com_Len_TimeSync;
case Com_Type_ThemeRgb:
return DataLength == Packet_len::Com_Len_ThemeRgb;
case Com_Type_Ack:
return DataLength == Packet_len::Com_Len_Ack;
case Com_Type_Error:
return DataLength == Packet_len::Com_Len_Error;
default:
return true;
}
}
bool Com_Cdc_Func_IsExpectedPacket(
const Packet& PacketData,
Packet_Type Type,
quint8 ExpectedLength)
{
return (PacketData.type == Type) &&
(PacketData.data.size() == ExpectedLength);
}
bool Com_Cdc_Func_ParseFrameAtStart(const QByteArray& ByteArray, Packet* p_Packet)
{
if ((p_Packet == nullptr) || (ByteArray.size() < COM_CDC_CONST_FRAME_OVERHEAD))
{
return false;
}
if (static_cast<quint8>(ByteArray.at(0)) != COM_CDC_CONST_PACKET_HEAD1)
{
return false;
}
if (static_cast<quint8>(ByteArray.at(1)) != COM_CDC_CONST_PACKET_HEAD2)
{
return false;
}
const quint8 DataLength = static_cast<quint8>(ByteArray.at(2));
if (DataLength > COM_CDC_CONST_MAX_PAYLOAD_LENGTH)
{
return false;
}
const Packet_Type Type =
static_cast<Packet_Type>(static_cast<quint8>(ByteArray.at(3)));
if (!Com_Cdc_Func_IsKnownLengthValid(Type, DataLength))
{
return false;
}
const int FrameLength = COM_CDC_CONST_FRAME_OVERHEAD + static_cast<int>(DataLength);
if (ByteArray.size() != FrameLength)
{
return false;
}
const QByteArray Body = ByteArray.left(FrameLength - 1);
const quint8 Checksum = Com_Cdc_Func_CalcChecksum(Body);
const quint8 ChecksumRx = static_cast<quint8>(ByteArray.at(FrameLength - 1));
if (Checksum != ChecksumRx)
{
return false;
}
p_Packet->Com_Packet_Head1 = COM_CDC_CONST_PACKET_HEAD1;
p_Packet->Com_Packet_Head2 = COM_CDC_CONST_PACKET_HEAD2;
p_Packet->len = DataLength;
p_Packet->type = Type;
p_Packet->data = ByteArray.mid(4, DataLength);
return true;
}
int Com_Cdc_Func_FindHead(const QByteArray& ByteArray)
{
for (int Index = 0; Index + 1 < ByteArray.size(); ++Index)
{
if ((static_cast<quint8>(ByteArray.at(Index)) == COM_CDC_CONST_PACKET_HEAD1) &&
(static_cast<quint8>(ByteArray.at(Index + 1)) == COM_CDC_CONST_PACKET_HEAD2))
{
return Index;
}
}
return -1;
}
void Com_Cdc_Func_KeepTailForNextScan(QByteArray* p_Buffer)
{
if (!p_Buffer->isEmpty() &&
(static_cast<quint8>(p_Buffer->at(p_Buffer->size() - 1)) == COM_CDC_CONST_PACKET_HEAD1))
{
*p_Buffer = QByteArray(1, static_cast<char>(COM_CDC_CONST_PACKET_HEAD1));
return;
}
p_Buffer->clear();
}
} // namespace
bool Com_Cdc_Func_ParseFrame(const QByteArray& ByteArray, Packet* p_Packet)
{
return Com_Cdc_Func_ParseFrameAtStart(ByteArray, p_Packet);
}
bool Com_Cdc_Func_TryTakeFrame(QByteArray* p_Buffer, Packet* p_Packet)
{
if ((p_Buffer == nullptr) || (p_Packet == nullptr))
{
return false;
}
while (true)
{
if (p_Buffer->size() < 2)
{
return false;
}
const int HeadIndex = Com_Cdc_Func_FindHead(*p_Buffer);
if (HeadIndex < 0)
{
Com_Cdc_Func_KeepTailForNextScan(p_Buffer);
return false;
}
if (HeadIndex > 0)
{
p_Buffer->remove(0, HeadIndex);
}
if (p_Buffer->size() < 4)
{
return false;
}
const quint8 DataLength = static_cast<quint8>(p_Buffer->at(2));
if (DataLength > COM_CDC_CONST_MAX_PAYLOAD_LENGTH)
{
p_Buffer->remove(0, 1);
continue;
}
const Packet_Type Type =
static_cast<Packet_Type>(static_cast<quint8>(p_Buffer->at(3)));
if (!Com_Cdc_Func_IsKnownLengthValid(Type, DataLength))
{
p_Buffer->remove(0, 1);
continue;
}
const int FrameLength = COM_CDC_CONST_FRAME_OVERHEAD + static_cast<int>(DataLength);
if (p_Buffer->size() < FrameLength)
{
return false;
}
const QByteArray FrameBytes = p_Buffer->left(FrameLength);
if (!Com_Cdc_Func_ParseFrameAtStart(FrameBytes, p_Packet))
{
p_Buffer->remove(0, 1);
continue;
}
p_Buffer->remove(0, FrameLength);
return true;
}
}
bool Com_Cdc_Func_ParseHelloReq(
const Packet& PacketData,
Packet_HelloReq* p_HelloReq)
{
if ((p_HelloReq == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_HelloReq,
Packet_len::Com_Len_HelloReq))
{
return false;
}
Packet_HelloReq HelloReq;
HelloReq.ProtocolVersion = static_cast<quint8>(PacketData.data.at(0));
*p_HelloReq = HelloReq;
return true;
}
bool Com_Cdc_Func_ParseHelloRsp(
const Packet& PacketData,
Packet_HelloRsp* p_HelloRsp)
{
if ((p_HelloRsp == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_HelloRsp,
Packet_len::Com_Len_HelloRsp))
{
return false;
}
Packet_HelloRsp HelloRsp;
HelloRsp.ProtocolVersion = static_cast<quint8>(PacketData.data.at(0));
HelloRsp.VendorId = Com_Cdc_Func_ReadLe16(PacketData.data, 1);
HelloRsp.ProductId = Com_Cdc_Func_ReadLe16(PacketData.data, 3);
HelloRsp.FirmwareMajor = static_cast<quint8>(PacketData.data.at(5));
HelloRsp.FirmwareMinor = static_cast<quint8>(PacketData.data.at(6));
HelloRsp.CapabilityFlags = Com_Cdc_Func_ReadLe16(PacketData.data, 7);
*p_HelloRsp = HelloRsp;
return true;
}
bool Com_Cdc_Func_ParseBitmap(
const Packet& PacketData,
Packet_Bitmap* p_Bitmap)
{
if ((p_Bitmap == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_Bitmap,
Packet_len::Com_Len_Bitmap))
{
return false;
}
Packet_Bitmap Bitmap;
Bitmap.UsageBitmap = PacketData.data;
*p_Bitmap = Bitmap;
return true;
}
bool Com_Cdc_Func_ParseFunctionKeyEvent(
const Packet& PacketData,
Packet_FunctionKeyEvent* p_Event)
{
if ((p_Event == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_FunctionKeyEvent,
Packet_len::Com_Len_FunctionKeyEvent))
{
return false;
}
Packet_FunctionKeyEvent EventData;
EventData.Usage = Com_Cdc_Func_ReadLe16(PacketData.data, 0);
EventData.Action = static_cast<quint8>(PacketData.data.at(2));
*p_Event = EventData;
return true;
}
bool Com_Cdc_Func_ParseLedState(
const Packet& PacketData,
Packet_LedState* p_LedState)
{
if ((p_LedState == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_LedState,
Packet_len::Com_Len_LedState))
{
return false;
}
Packet_LedState LedState;
LedState.LedMask = static_cast<quint8>(PacketData.data.at(0));
*p_LedState = LedState;
return true;
}
bool Com_Cdc_Func_ParseTimeSync(
const Packet& PacketData,
Packet_TimeSync* p_TimeSync)
{
if ((p_TimeSync == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_TimeSync,
Packet_len::Com_Len_TimeSync))
{
return false;
}
Packet_TimeSync TimeSync;
TimeSync.Version = static_cast<quint8>(PacketData.data.at(0));
TimeSync.Flags = static_cast<quint8>(PacketData.data.at(1));
TimeSync.TimezoneMin = Com_Cdc_Func_ReadLe16(PacketData.data, 2);
TimeSync.UtcMs = Com_Cdc_Func_ReadLe64(PacketData.data, 4);
TimeSync.AccuracyMs = Com_Cdc_Func_ReadLe32(PacketData.data, 12);
*p_TimeSync = TimeSync;
return true;
}
bool Com_Cdc_Func_ParseThemeRgb(
const Packet& PacketData,
Packet_ThemeRgb* p_ThemeRgb)
{
if ((p_ThemeRgb == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_ThemeRgb,
Packet_len::Com_Len_ThemeRgb))
{
return false;
}
Packet_ThemeRgb ThemeRgb;
ThemeRgb.Red = static_cast<quint8>(PacketData.data.at(0));
ThemeRgb.Green = static_cast<quint8>(PacketData.data.at(1));
ThemeRgb.Blue = static_cast<quint8>(PacketData.data.at(2));
*p_ThemeRgb = ThemeRgb;
return true;
}
bool Com_Cdc_Func_ParseAck(
const Packet& PacketData,
Packet_Ack* p_Ack)
{
if ((p_Ack == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_Ack,
Packet_len::Com_Len_Ack))
{
return false;
}
Packet_Ack Ack;
Ack.AckedType = static_cast<quint8>(PacketData.data.at(0));
*p_Ack = Ack;
return true;
}
bool Com_Cdc_Func_ParseError(
const Packet& PacketData,
Packet_Error* p_Error)
{
if ((p_Error == nullptr) ||
!Com_Cdc_Func_IsExpectedPacket(
PacketData,
Com_Type_Error,
Packet_len::Com_Len_Error))
{
return false;
}
Packet_Error Error;
Error.ErrorType = static_cast<quint8>(PacketData.data.at(0));
Error.ErrorCode = static_cast<quint8>(PacketData.data.at(1));
*p_Error = Error;
return true;
}

View File

@@ -1,36 +0,0 @@
#pragma once
#include <QtCore/QByteArray>
#include "COM/Com_Cdc.h"
bool Com_Cdc_Func_ParseFrame(const QByteArray& ByteArray, Packet* p_Packet);
bool Com_Cdc_Func_TryTakeFrame(QByteArray* p_Buffer, Packet* p_Packet);
bool Com_Cdc_Func_ParseHelloReq(
const Packet& PacketData,
Packet_HelloReq* p_HelloReq);
bool Com_Cdc_Func_ParseHelloRsp(
const Packet& PacketData,
Packet_HelloRsp* p_HelloRsp);
bool Com_Cdc_Func_ParseBitmap(
const Packet& PacketData,
Packet_Bitmap* p_Bitmap);
bool Com_Cdc_Func_ParseFunctionKeyEvent(
const Packet& PacketData,
Packet_FunctionKeyEvent* p_Event);
bool Com_Cdc_Func_ParseLedState(
const Packet& PacketData,
Packet_LedState* p_LedState);
bool Com_Cdc_Func_ParseTimeSync(
const Packet& PacketData,
Packet_TimeSync* p_TimeSync);
bool Com_Cdc_Func_ParseThemeRgb(
const Packet& PacketData,
Packet_ThemeRgb* p_ThemeRgb);
bool Com_Cdc_Func_ParseAck(
const Packet& PacketData,
Packet_Ack* p_Ack);
bool Com_Cdc_Func_ParseError(
const Packet& PacketData,
Packet_Error* p_Error);

View File

@@ -1,159 +0,0 @@
#include "COM/Com_CdcEncode.h"
namespace
{
Packet Com_Cdc_Func_MakePacket(Packet_Type Type, const QByteArray& Data)
{
Packet PacketData;
PacketData.type = Type;
PacketData.len = static_cast<quint8>(Data.size());
PacketData.data = Data;
return PacketData;
}
void Com_Cdc_Func_WriteLe16(QByteArray* p_Data, int Offset, quint16 Value)
{
(*p_Data)[Offset] = static_cast<char>(Value & 0x00FFU);
(*p_Data)[Offset + 1] = static_cast<char>((Value >> 8) & 0x00FFU);
}
void Com_Cdc_Func_WriteLe32(QByteArray* p_Data, int Offset, quint32 Value)
{
for (int Index = 0; Index < 4; ++Index)
{
(*p_Data)[Offset + Index] = static_cast<char>((Value >> (Index * 8)) & 0xFFU);
}
}
void Com_Cdc_Func_WriteLe64(QByteArray* p_Data, int Offset, quint64 Value)
{
for (int Index = 0; Index < 8; ++Index)
{
(*p_Data)[Offset + Index] = static_cast<char>((Value >> (Index * 8)) & 0xFFULL);
}
}
QByteArray Com_Cdc_Func_FitPayload(const QByteArray& Data, int ExpectedLength)
{
QByteArray Payload = Data.left(ExpectedLength);
if (Payload.size() < ExpectedLength)
{
Payload.append(ExpectedLength - Payload.size(), 0);
}
return Payload;
}
} // namespace
quint8 Com_Cdc_Func_CalcChecksum(const QByteArray& ByteArray)
{
quint8 Checksum = 0;
for (int Index = 0; Index < ByteArray.size(); ++Index)
{
const quint8 ByteValue = static_cast<quint8>(ByteArray.at(Index));
Checksum = static_cast<quint8>(Checksum ^ ByteValue);
}
return Checksum;
}
QByteArray Com_Cdc_Func_BuildFrame(const Packet& PacketData)
{
if (PacketData.data.size() > 0xFF)
{
return QByteArray();
}
QByteArray ByteArray;
const quint8 DataLength = static_cast<quint8>(PacketData.data.size());
ByteArray.append(static_cast<char>(PacketData.Com_Packet_Head1));
ByteArray.append(static_cast<char>(PacketData.Com_Packet_Head2));
ByteArray.append(static_cast<char>(DataLength));
ByteArray.append(static_cast<char>(PacketData.type));
ByteArray.append(PacketData.data);
const quint8 Checksum = Com_Cdc_Func_CalcChecksum(ByteArray);
ByteArray.append(static_cast<char>(Checksum));
return ByteArray;
}
QByteArray Com_Cdc_Func_BuildHelloReq(const Packet_HelloReq& PacketData)
{
QByteArray Payload(Packet_len::Com_Len_HelloReq, 0);
Payload[0] = static_cast<char>(PacketData.ProtocolVersion);
return Com_Cdc_Func_BuildFrame(Com_Cdc_Func_MakePacket(Com_Type_HelloReq, Payload));
}
QByteArray Com_Cdc_Func_BuildHelloRsp(const Packet_HelloRsp& PacketData)
{
QByteArray Payload(Packet_len::Com_Len_HelloRsp, 0);
Payload[0] = static_cast<char>(PacketData.ProtocolVersion);
Com_Cdc_Func_WriteLe16(&Payload, 1, PacketData.VendorId);
Com_Cdc_Func_WriteLe16(&Payload, 3, PacketData.ProductId);
Payload[5] = static_cast<char>(PacketData.FirmwareMajor);
Payload[6] = static_cast<char>(PacketData.FirmwareMinor);
Com_Cdc_Func_WriteLe16(&Payload, 7, PacketData.CapabilityFlags);
return Com_Cdc_Func_BuildFrame(Com_Cdc_Func_MakePacket(Com_Type_HelloRsp, Payload));
}
QByteArray Com_Cdc_Func_BuildBitmap(const Packet_Bitmap& PacketData)
{
return Com_Cdc_Func_BuildFrame(
Com_Cdc_Func_MakePacket(
Com_Type_Bitmap,
Com_Cdc_Func_FitPayload(PacketData.UsageBitmap, Packet_len::Com_Len_Bitmap)));
}
QByteArray Com_Cdc_Func_BuildFunctionKeyEvent(const Packet_FunctionKeyEvent& PacketData)
{
QByteArray Payload(Packet_len::Com_Len_FunctionKeyEvent, 0);
Com_Cdc_Func_WriteLe16(&Payload, 0, PacketData.Usage);
Payload[2] = static_cast<char>(PacketData.Action);
return Com_Cdc_Func_BuildFrame(
Com_Cdc_Func_MakePacket(Com_Type_FunctionKeyEvent, Payload));
}
QByteArray Com_Cdc_Func_BuildLedState(const Packet_LedState& PacketData)
{
QByteArray Payload(Packet_len::Com_Len_LedState, 0);
Payload[0] = static_cast<char>(PacketData.LedMask);
return Com_Cdc_Func_BuildFrame(Com_Cdc_Func_MakePacket(Com_Type_LedState, Payload));
}
QByteArray Com_Cdc_Func_BuildTimeSync(const Packet_TimeSync& PacketData)
{
QByteArray Payload(Packet_len::Com_Len_TimeSync, 0);
Payload[0] = static_cast<char>(PacketData.Version);
Payload[1] = static_cast<char>(PacketData.Flags);
Com_Cdc_Func_WriteLe16(&Payload, 2, PacketData.TimezoneMin);
Com_Cdc_Func_WriteLe64(&Payload, 4, PacketData.UtcMs);
Com_Cdc_Func_WriteLe32(&Payload, 12, PacketData.AccuracyMs);
return Com_Cdc_Func_BuildFrame(Com_Cdc_Func_MakePacket(Com_Type_TimeSync, Payload));
}
QByteArray Com_Cdc_Func_BuildThemeRgb(const Packet_ThemeRgb& PacketData)
{
QByteArray Payload(Packet_len::Com_Len_ThemeRgb, 0);
Payload[0] = static_cast<char>(PacketData.Red);
Payload[1] = static_cast<char>(PacketData.Green);
Payload[2] = static_cast<char>(PacketData.Blue);
return Com_Cdc_Func_BuildFrame(Com_Cdc_Func_MakePacket(Com_Type_ThemeRgb, Payload));
}
QByteArray Com_Cdc_Func_BuildAck(const Packet_Ack& PacketData)
{
QByteArray Payload(Packet_len::Com_Len_Ack, 0);
Payload[0] = static_cast<char>(PacketData.AckedType);
return Com_Cdc_Func_BuildFrame(Com_Cdc_Func_MakePacket(Com_Type_Ack, Payload));
}
QByteArray Com_Cdc_Func_BuildError(const Packet_Error& PacketData)
{
QByteArray Payload(Packet_len::Com_Len_Error, 0);
Payload[0] = static_cast<char>(PacketData.ErrorType);
Payload[1] = static_cast<char>(PacketData.ErrorCode);
return Com_Cdc_Func_BuildFrame(Com_Cdc_Func_MakePacket(Com_Type_Error, Payload));
}

View File

@@ -1,19 +0,0 @@
#pragma once
#include <QtCore/QByteArray>
#include "COM/Com_Cdc.h"
quint8 Com_Cdc_Func_CalcChecksum(const QByteArray& ByteArray);
QByteArray Com_Cdc_Func_BuildFrame(const Packet& PacketData);
QByteArray Com_Cdc_Func_BuildHelloReq(const Packet_HelloReq& PacketData);
QByteArray Com_Cdc_Func_BuildHelloRsp(const Packet_HelloRsp& PacketData);
QByteArray Com_Cdc_Func_BuildBitmap(const Packet_Bitmap& PacketData);
QByteArray Com_Cdc_Func_BuildFunctionKeyEvent(const Packet_FunctionKeyEvent& PacketData);
QByteArray Com_Cdc_Func_BuildLedState(const Packet_LedState& PacketData);
QByteArray Com_Cdc_Func_BuildTimeSync(const Packet_TimeSync& PacketData);
QByteArray Com_Cdc_Func_BuildThemeRgb(const Packet_ThemeRgb& PacketData);
QByteArray Com_Cdc_Func_BuildAck(const Packet_Ack& PacketData);
QByteArray Com_Cdc_Func_BuildError(const Packet_Error& PacketData);

View File

@@ -1,10 +1,20 @@
#include "COM/Com_PbCodec.h" #include "COM/Com_PbCodec.h"
#include "COM/Com_CdcEncode.h"
namespace namespace
{ {
quint32 Com_Pb_Func_CalcChecksum(const QByteArray& ByteArray)
{
quint32 Checksum = 0;
for (int Index = 0; Index < ByteArray.size(); ++Index)
{
Checksum ^= static_cast<quint8>(ByteArray.at(Index));
}
return Checksum & 0xFFU;
}
quint32 Com_Pb_Func_CalcFrameChecksum(const keyboard::cdc::CdcFrame& Frame) quint32 Com_Pb_Func_CalcFrameChecksum(const keyboard::cdc::CdcFrame& Frame)
{ {
QByteArray ByteArray; QByteArray ByteArray;
@@ -14,7 +24,7 @@ quint32 Com_Pb_Func_CalcFrameChecksum(const keyboard::cdc::CdcFrame& Frame)
ByteArray.append(static_cast<char>(Frame.type())); ByteArray.append(static_cast<char>(Frame.type()));
ByteArray.append(QByteArray::fromStdString(Frame.payload())); ByteArray.append(QByteArray::fromStdString(Frame.payload()));
return Com_Cdc_Func_CalcChecksum(ByteArray); return Com_Pb_Func_CalcChecksum(ByteArray);
} }
keyboard::cdc::CdcFrame Com_Pb_Func_BuildFrame( keyboard::cdc::CdcFrame Com_Pb_Func_BuildFrame(

View File

@@ -94,11 +94,6 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="COM\Com_Cdc.h" />
<ClCompile Include="COM\Com_CdcEncode.cpp" />
<ClInclude Include="COM\Com_CdcEncode.h" />
<ClCompile Include="COM\Com_CdcDecode.cpp" />
<ClInclude Include="COM\Com_CdcDecode.h" />
<ClCompile Include="DRI\Dri_Cdc.cpp" /> <ClCompile Include="DRI\Dri_Cdc.cpp" />
<ClCompile Include="DRI\GATT\Dri_Gatt.cpp" /> <ClCompile Include="DRI\GATT\Dri_Gatt.cpp" />
<ClInclude Include="DRI\GATT\Dri_Gatt.h" /> <ClInclude Include="DRI\GATT\Dri_Gatt.h" />

View File

@@ -23,21 +23,6 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="COM\Com_Cdc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="COM\Com_CdcEncode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="COM\Com_CdcEncode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="COM\Com_CdcDecode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="COM\Com_CdcDecode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="DRI\Dri_Cdc.cpp"> <ClCompile Include="DRI\Dri_Cdc.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View File

@@ -20,69 +20,25 @@ The COM layer should not:
## Current file roles ## Current file roles
### `Com_Cdc.h` ### `Com_PbCodec.h/.cpp`
Owns the packet model: Owns the protobuf-side wrapper:
- packet types - full protobuf frame serialize / parse
- fixed payload lengths - checksum validation
- payload structs - typed helper entry points like hello request / response
### `Com_CdcEncode.h/.cpp` ### `keyboard.pb.h/.cc`
Owns the write direction: Own the generated protocol model:
- checksum - outer `CdcFrame`
- full frame build - business `CdcPacketBody`
- typed payload encode - all message definitions
### `Com_CdcDecode.h/.cpp`
Owns the read direction:
- full frame parse
- stream extraction
- typed payload decode
## Completed nodes ## Completed nodes
### Node 1: legacy frame encode baseline ### Node 1: protobuf thin wrapper
Already present before this step:
- build full frame
- build all typed packets
### Node 2: typed packet decode completion
Files updated in this step:
- `KeyBorad/KeyBorad/COM/Com_CdcDecode.h`
- `KeyBorad/KeyBorad/COM/Com_CdcDecode.cpp`
Design notes:
- keep decode logic flat and explicit
- one helper for little-endian reads
- one helper for type + length validation
- one decode function per packet type
Implemented behavior:
- parse frame header and checksum
- extract frames from a byte stream
- decode:
- `HelloReq`
- `HelloRsp`
- `Bitmap`
- `FunctionKeyEvent`
- `LedState`
- `TimeSync`
- `ThemeRgb`
- `Ack`
- `Error`
### Node 3: protobuf thin wrapper
Files added in this step: Files added in this step:
@@ -102,16 +58,32 @@ Implemented behavior:
- build `HelloReq` using generated protobuf types - build `HelloReq` using generated protobuf types
- parse `HelloRsp` using generated protobuf types - parse `HelloRsp` using generated protobuf types
Current limit: ### Node 2: remove legacy manual codec
- not wired into the project yet Files removed in this step:
- protobuf runtime include and link setup is still pending
- `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:
- no dual path
- no hand-written payload encode/decode path left behind
- protobuf is now the only packet encode/decode direction
Implemented behavior:
- checksum moved into `Com_PbCodec.cpp`
- old manual packet structs and old codec files removed
## COM done criteria ## COM done criteria
For the current project stage, COM is considered done when: For the current project stage, COM is considered done when:
1. every supported packet can be built 1. the protocol source is the `.proto` file
2. every supported packet can be parsed 2. generated `.pb.*` files exist
3. stream extraction is stable 3. `Com_PbCodec` provides thin project-facing helpers
4. higher layers no longer need to know byte offsets 4. no legacy hand-written packet codec remains