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_CdcEncode.h"
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)
{
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(QByteArray::fromStdString(Frame.payload()));
return Com_Cdc_Func_CalcChecksum(ByteArray);
return Com_Pb_Func_CalcChecksum(ByteArray);
}
keyboard::cdc::CdcFrame Com_Pb_Func_BuildFrame(

View File

@@ -94,11 +94,6 @@
</Link>
</ItemDefinitionGroup>
<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\GATT\Dri_Gatt.cpp" />
<ClInclude Include="DRI\GATT\Dri_Gatt.h" />

View File

@@ -23,21 +23,6 @@
</Filter>
</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">
<Filter>Source Files</Filter>
</ClCompile>

View File

@@ -20,69 +20,25 @@ The COM layer should not:
## Current file roles
### `Com_Cdc.h`
### `Com_PbCodec.h/.cpp`
Owns the packet model:
Owns the protobuf-side wrapper:
- packet types
- fixed payload lengths
- payload structs
- full protobuf frame serialize / parse
- checksum validation
- 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
- full frame build
- typed payload encode
### `Com_CdcDecode.h/.cpp`
Owns the read direction:
- full frame parse
- stream extraction
- typed payload decode
- outer `CdcFrame`
- business `CdcPacketBody`
- all message definitions
## Completed nodes
### Node 1: legacy frame encode baseline
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
### Node 1: protobuf thin wrapper
Files added in this step:
@@ -102,16 +58,32 @@ Implemented behavior:
- build `HelloReq` using generated protobuf types
- parse `HelloRsp` using generated protobuf types
Current limit:
### Node 2: remove legacy manual codec
- not wired into the project yet
- protobuf runtime include and link setup is still pending
Files removed in 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:
- 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
For the current project stage, COM is considered done when:
1. every supported packet can be built
2. every supported packet can be parsed
3. stream extraction is stable
4. higher layers no longer need to know byte offsets
1. the protocol source is the `.proto` file
2. generated `.pb.*` files exist
3. `Com_PbCodec` provides thin project-facing helpers
4. no legacy hand-written packet codec remains