Push layered Qt host source files

This commit is contained in:
2026-04-17 16:25:19 +08:00
parent b576d3f19d
commit 89b23b2291
58 changed files with 10349 additions and 2461 deletions

35
COM/Com_Def.h Normal file
View File

@@ -0,0 +1,35 @@
#pragma once
#include "COM/Com_Protocol.h"
#include <QtCore/QByteArray>
#include <QtCore/QString>
enum Com_Enum_RawPacketSource : quint8
{
Com_Enum_RawPacketSource_None = 0,
Com_Enum_RawPacketSource_UsbCdc,
Com_Enum_RawPacketSource_BleNus
};
const quint16 COM_CONST_VENDOR_ID_DEFAULT = 0x1209;
const quint16 COM_CONST_PRODUCT_ID_DEFAULT = 0x0001;
const int COM_CONST_KEYBOARD_USAGE_MAX = 0x00E7;
const int COM_CONST_USAGE_BITMAP_SIZE = 29;
struct Com_Struct_DeviceConfig
{
quint16 VendorId = COM_CONST_VENDOR_ID_DEFAULT;
quint16 ProductId = COM_CONST_PRODUCT_ID_DEFAULT;
};
struct Com_Struct_RawPacket
{
bool IsValid = false;
Com_Enum_RawPacketSource Source = Com_Enum_RawPacketSource_None;
Com_Enum_ProtocolType ProtocolType = Com_Enum_ProtocolType_None;
QByteArray ByteArray;
QString PortName;
// Stable candidate id used by LOGIC to confirm or discard a transport candidate.
QString EndpointId;
};

975
COM/Com_Protocol.cpp Normal file
View File

@@ -0,0 +1,975 @@
#include "COM/Com_Protocol.h"
namespace
{
constexpr quint8 kProtoWireVarint = 0;
constexpr quint8 kProtoWireFixed64 = 1;
constexpr quint8 kProtoWireBytes = 2;
constexpr quint8 kProtoWireFixed32 = 5;
constexpr quint32 kFieldHelloReq = 1;
constexpr quint32 kFieldHelloRsp = 2;
constexpr quint32 kFieldBitmap = 3;
constexpr quint32 kFieldFunctionKeyEvent = 4;
constexpr quint32 kFieldLedState = 5;
constexpr quint32 kFieldTimeSync = 6;
constexpr quint32 kFieldThemeRgb = 7;
constexpr quint32 kFieldAck = 8;
constexpr quint32 kFieldError = 9;
constexpr quint16 kUsageModifierFirst = 0x00E0;
constexpr quint16 kUsageModifierLast = 0x00E7;
constexpr quint16 kUsageNormalLast = 0x00DF;
constexpr int kUsageBitmapSize = 29;
bool Com_Protocol_ReadVarint(const QByteArray& Bytes, int* p_Offset, quint64* p_Value)
{
quint64 Value = 0;
int Shift = 0;
int Offset = *p_Offset;
while (Offset < Bytes.size())
{
const quint8 Byte = static_cast<quint8>(Bytes.at(Offset++));
Value |= static_cast<quint64>(Byte & 0x7FU) << Shift;
if ((Byte & 0x80U) == 0U)
{
*p_Offset = Offset;
*p_Value = Value;
return true;
}
Shift += 7;
if (Shift >= 64)
{
return false;
}
}
return false;
}
bool Com_Protocol_ReadKey(
const QByteArray& Bytes,
int* p_Offset,
quint32* p_FieldNumber,
quint8* p_WireType)
{
quint64 Key = 0;
if (!Com_Protocol_ReadVarint(Bytes, p_Offset, &Key))
{
return false;
}
*p_FieldNumber = static_cast<quint32>(Key >> 3);
*p_WireType = static_cast<quint8>(Key & 0x07U);
return *p_FieldNumber > 0;
}
bool Com_Protocol_ReadLengthDelimited(
const QByteArray& Bytes,
int* p_Offset,
QByteArray* p_Value)
{
quint64 Length = 0;
if (!Com_Protocol_ReadVarint(Bytes, p_Offset, &Length))
{
return false;
}
if ((Length > static_cast<quint64>(Bytes.size())) ||
(*p_Offset > Bytes.size() - static_cast<int>(Length)))
{
return false;
}
*p_Value = Bytes.mid(*p_Offset, static_cast<int>(Length));
*p_Offset += static_cast<int>(Length);
return true;
}
bool Com_Protocol_ReadFixed32(const QByteArray& Bytes, int* p_Offset, quint32* p_Value)
{
if (*p_Offset > Bytes.size() - 4)
{
return false;
}
quint32 Value = 0;
for (int Index = 0; Index < 4; ++Index)
{
Value |= static_cast<quint32>(
static_cast<quint8>(Bytes.at(*p_Offset + Index))) << (Index * 8);
}
*p_Offset += 4;
*p_Value = Value;
return true;
}
bool Com_Protocol_ReadFixed64(const QByteArray& Bytes, int* p_Offset, quint64* p_Value)
{
if (*p_Offset > Bytes.size() - 8)
{
return false;
}
quint64 Value = 0;
for (int Index = 0; Index < 8; ++Index)
{
Value |= static_cast<quint64>(
static_cast<quint8>(Bytes.at(*p_Offset + Index))) << (Index * 8);
}
*p_Offset += 8;
*p_Value = Value;
return true;
}
bool Com_Protocol_SkipField(const QByteArray& Bytes, int* p_Offset, quint8 WireType)
{
switch (WireType)
{
case kProtoWireVarint:
{
quint64 Dummy = 0;
return Com_Protocol_ReadVarint(Bytes, p_Offset, &Dummy);
}
case kProtoWireFixed64:
if (*p_Offset > Bytes.size() - 8)
{
return false;
}
*p_Offset += 8;
return true;
case kProtoWireBytes:
{
QByteArray Dummy;
return Com_Protocol_ReadLengthDelimited(Bytes, p_Offset, &Dummy);
}
case kProtoWireFixed32:
if (*p_Offset > Bytes.size() - 4)
{
return false;
}
*p_Offset += 4;
return true;
default:
return false;
}
}
void Com_Protocol_AppendVarint(QByteArray* p_Bytes, quint64 Value)
{
do
{
quint8 Byte = static_cast<quint8>(Value & 0x7FU);
Value >>= 7;
if (Value != 0)
{
Byte = static_cast<quint8>(Byte | 0x80U);
}
p_Bytes->append(static_cast<char>(Byte));
} while (Value != 0);
}
void Com_Protocol_AppendKey(QByteArray* p_Bytes, quint32 FieldNumber, quint8 WireType)
{
Com_Protocol_AppendVarint(
p_Bytes,
(static_cast<quint64>(FieldNumber) << 3) | static_cast<quint64>(WireType));
}
void Com_Protocol_AppendUInt32Field(QByteArray* p_Bytes, quint32 FieldNumber, quint32 Value)
{
Com_Protocol_AppendKey(p_Bytes, FieldNumber, kProtoWireVarint);
Com_Protocol_AppendVarint(p_Bytes, Value);
}
void Com_Protocol_AppendSInt32Field(QByteArray* p_Bytes, quint32 FieldNumber, qint32 Value)
{
const quint32 ZigZag = static_cast<quint32>(
(static_cast<quint32>(Value) << 1) ^ static_cast<quint32>(Value >> 31));
Com_Protocol_AppendUInt32Field(p_Bytes, FieldNumber, ZigZag);
}
void Com_Protocol_AppendFixed32Field(QByteArray* p_Bytes, quint32 FieldNumber, quint32 Value)
{
Com_Protocol_AppendKey(p_Bytes, FieldNumber, kProtoWireFixed32);
for (int Index = 0; Index < 4; ++Index)
{
p_Bytes->append(static_cast<char>((Value >> (Index * 8)) & 0xFFU));
}
}
void Com_Protocol_AppendFixed64Field(QByteArray* p_Bytes, quint32 FieldNumber, quint64 Value)
{
Com_Protocol_AppendKey(p_Bytes, FieldNumber, kProtoWireFixed64);
for (int Index = 0; Index < 8; ++Index)
{
p_Bytes->append(static_cast<char>((Value >> (Index * 8)) & 0xFFU));
}
}
void Com_Protocol_AppendBytesField(
QByteArray* p_Bytes,
quint32 FieldNumber,
const QByteArray& Value)
{
Com_Protocol_AppendKey(p_Bytes, FieldNumber, kProtoWireBytes);
Com_Protocol_AppendVarint(p_Bytes, static_cast<quint64>(Value.size()));
p_Bytes->append(Value);
}
quint32 Com_Protocol_FieldNumberForType(Com_Enum_ProtocolType Type)
{
switch (Type)
{
case Com_Enum_ProtocolType_HelloReq: return kFieldHelloReq;
case Com_Enum_ProtocolType_HelloRsp: return kFieldHelloRsp;
case Com_Enum_ProtocolType_Bitmap: return kFieldBitmap;
case Com_Enum_ProtocolType_FunctionKeyEvent: return kFieldFunctionKeyEvent;
case Com_Enum_ProtocolType_LedState: return kFieldLedState;
case Com_Enum_ProtocolType_TimeSync: return kFieldTimeSync;
case Com_Enum_ProtocolType_ThemeRgb: return kFieldThemeRgb;
case Com_Enum_ProtocolType_Ack: return kFieldAck;
case Com_Enum_ProtocolType_Error: return kFieldError;
default:
return 0;
}
}
Com_Enum_ProtocolType Com_Protocol_TypeForFieldNumber(quint32 FieldNumber)
{
switch (FieldNumber)
{
case kFieldHelloReq: return Com_Enum_ProtocolType_HelloReq;
case kFieldHelloRsp: return Com_Enum_ProtocolType_HelloRsp;
case kFieldBitmap: return Com_Enum_ProtocolType_Bitmap;
case kFieldFunctionKeyEvent: return Com_Enum_ProtocolType_FunctionKeyEvent;
case kFieldLedState: return Com_Enum_ProtocolType_LedState;
case kFieldTimeSync: return Com_Enum_ProtocolType_TimeSync;
case kFieldThemeRgb: return Com_Enum_ProtocolType_ThemeRgb;
case kFieldAck: return Com_Enum_ProtocolType_Ack;
case kFieldError: return Com_Enum_ProtocolType_Error;
default:
return Com_Enum_ProtocolType_None;
}
}
QByteArray Com_Protocol_EncodeEnvelope(Com_Enum_ProtocolType Type, const QByteArray& MessageBytes)
{
QByteArray PacketBody;
const quint32 FieldNumber = Com_Protocol_FieldNumberForType(Type);
if ((FieldNumber == 0) || MessageBytes.isEmpty())
{
return PacketBody;
}
Com_Protocol_AppendBytesField(&PacketBody, FieldNumber, MessageBytes);
return PacketBody;
}
bool Com_Protocol_DecodeEnvelope(
const QByteArray& PacketBody,
Com_Enum_ProtocolType* p_Type,
QByteArray* p_MessageBytes)
{
int Offset = 0;
while (Offset < PacketBody.size())
{
quint32 FieldNumber = 0;
quint8 WireType = 0;
if (!Com_Protocol_ReadKey(PacketBody, &Offset, &FieldNumber, &WireType))
{
return false;
}
const Com_Enum_ProtocolType Type = Com_Protocol_TypeForFieldNumber(FieldNumber);
if (Type == Com_Enum_ProtocolType_None)
{
if (!Com_Protocol_SkipField(PacketBody, &Offset, WireType))
{
return false;
}
continue;
}
if (WireType != kProtoWireBytes)
{
return false;
}
QByteArray MessageBytes;
if (!Com_Protocol_ReadLengthDelimited(PacketBody, &Offset, &MessageBytes))
{
return false;
}
*p_Type = Type;
*p_MessageBytes = MessageBytes;
return true;
}
return false;
}
bool Com_Protocol_DecodeEnvelopeForExpectedType(
const QByteArray& PacketBody,
Com_Enum_ProtocolType ExpectedType,
QByteArray* p_MessageBytes)
{
Com_Enum_ProtocolType Type = Com_Enum_ProtocolType_None;
if (!Com_Protocol_DecodeEnvelope(PacketBody, &Type, p_MessageBytes))
{
return false;
}
return Type == ExpectedType;
}
bool Com_Protocol_DecodeHelloRspMessage(
const QByteArray& MessageBytes,
Com_Struct_ProtocolHelloRsp* p_Message)
{
*p_Message = Com_Struct_ProtocolHelloRsp();
int Offset = 0;
while (Offset < MessageBytes.size())
{
quint32 FieldNumber = 0;
quint8 WireType = 0;
quint64 Value = 0;
if (!Com_Protocol_ReadKey(MessageBytes, &Offset, &FieldNumber, &WireType))
{
return false;
}
switch (FieldNumber)
{
case 1:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->ProtocolVersion = static_cast<quint32>(Value);
break;
case 2:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->VendorId = static_cast<quint32>(Value);
break;
case 3:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->ProductId = static_cast<quint32>(Value);
break;
case 4:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->FirmwareMajor = static_cast<quint32>(Value);
break;
case 5:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->FirmwareMinor = static_cast<quint32>(Value);
break;
case 6:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->CapabilityFlags = static_cast<quint32>(Value);
break;
default:
if (!Com_Protocol_SkipField(MessageBytes, &Offset, WireType))
{
return false;
}
break;
}
}
return true;
}
bool Com_Protocol_DecodeUsageBitmapMessage(
const QByteArray& MessageBytes,
QByteArray* p_UsageBitmap)
{
p_UsageBitmap->clear();
int Offset = 0;
while (Offset < MessageBytes.size())
{
quint32 FieldNumber = 0;
quint8 WireType = 0;
if (!Com_Protocol_ReadKey(MessageBytes, &Offset, &FieldNumber, &WireType))
{
return false;
}
if (FieldNumber == 1)
{
if ((WireType != kProtoWireBytes) ||
!Com_Protocol_ReadLengthDelimited(MessageBytes, &Offset, p_UsageBitmap))
{
return false;
}
return Com_Protocol_IsUsageBitmapValid(*p_UsageBitmap);
}
if (!Com_Protocol_SkipField(MessageBytes, &Offset, WireType))
{
return false;
}
}
return false;
}
bool Com_Protocol_DecodeFunctionKeyEventMessage(
const QByteArray& MessageBytes,
Com_Struct_ProtocolFunctionKeyEvent* p_Message)
{
*p_Message = Com_Struct_ProtocolFunctionKeyEvent();
bool HasBitmap = false;
bool HasLegacyUsage = false;
bool HasLegacyAction = false;
int Offset = 0;
while (Offset < MessageBytes.size())
{
quint32 FieldNumber = 0;
quint8 WireType = 0;
quint64 Value = 0;
if (!Com_Protocol_ReadKey(MessageBytes, &Offset, &FieldNumber, &WireType))
{
return false;
}
switch (FieldNumber)
{
case 1:
if (WireType == kProtoWireBytes)
{
if (!Com_Protocol_ReadLengthDelimited(
MessageBytes,
&Offset,
&p_Message->UsageBitmap) ||
!Com_Protocol_IsUsageBitmapValid(p_Message->UsageBitmap))
{
return false;
}
HasBitmap = true;
break;
}
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
if (Value > 0xFFFFU)
{
return false;
}
p_Message->Usage = static_cast<quint16>(Value);
HasLegacyUsage = true;
break;
case 2:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->Action = static_cast<quint32>(Value);
HasLegacyAction = true;
break;
default:
if (!Com_Protocol_SkipField(MessageBytes, &Offset, WireType))
{
return false;
}
break;
}
}
p_Message->HasUsageAction = HasLegacyUsage && HasLegacyAction;
return HasBitmap || p_Message->HasUsageAction;
}
bool Com_Protocol_DecodeLedStateMessage(
const QByteArray& MessageBytes,
Com_Struct_ProtocolLedState* p_Message)
{
*p_Message = Com_Struct_ProtocolLedState();
int Offset = 0;
while (Offset < MessageBytes.size())
{
quint32 FieldNumber = 0;
quint8 WireType = 0;
quint64 Value = 0;
if (!Com_Protocol_ReadKey(MessageBytes, &Offset, &FieldNumber, &WireType))
{
return false;
}
if (FieldNumber == 1)
{
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->LedMask = static_cast<quint32>(Value);
continue;
}
if (!Com_Protocol_SkipField(MessageBytes, &Offset, WireType))
{
return false;
}
}
return true;
}
bool Com_Protocol_DecodeAckMessage(
const QByteArray& MessageBytes,
Com_Struct_ProtocolAck* p_Message)
{
*p_Message = Com_Struct_ProtocolAck();
int Offset = 0;
while (Offset < MessageBytes.size())
{
quint32 FieldNumber = 0;
quint8 WireType = 0;
quint64 Value = 0;
if (!Com_Protocol_ReadKey(MessageBytes, &Offset, &FieldNumber, &WireType))
{
return false;
}
if (FieldNumber == 1)
{
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->AckedType = static_cast<quint32>(Value);
continue;
}
if (!Com_Protocol_SkipField(MessageBytes, &Offset, WireType))
{
return false;
}
}
return true;
}
bool Com_Protocol_DecodeErrorMessage(
const QByteArray& MessageBytes,
Com_Struct_ProtocolError* p_Message)
{
*p_Message = Com_Struct_ProtocolError();
int Offset = 0;
while (Offset < MessageBytes.size())
{
quint32 FieldNumber = 0;
quint8 WireType = 0;
quint64 Value = 0;
if (!Com_Protocol_ReadKey(MessageBytes, &Offset, &FieldNumber, &WireType))
{
return false;
}
switch (FieldNumber)
{
case 1:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->ErrorType = static_cast<quint32>(Value);
break;
case 2:
if ((WireType != kProtoWireVarint) ||
!Com_Protocol_ReadVarint(MessageBytes, &Offset, &Value))
{
return false;
}
p_Message->ErrorCode = static_cast<quint32>(Value);
break;
default:
if (!Com_Protocol_SkipField(MessageBytes, &Offset, WireType))
{
return false;
}
break;
}
}
return true;
}
bool Com_Protocol_GetBitmapPosition(quint16 Usage, int* p_ByteIndex, quint8* p_BitMask)
{
if ((p_ByteIndex == nullptr) || (p_BitMask == nullptr))
{
return false;
}
if ((Usage >= kUsageModifierFirst) && (Usage <= kUsageModifierLast))
{
*p_ByteIndex = 0;
*p_BitMask = static_cast<quint8>(1U << (Usage - kUsageModifierFirst));
return true;
}
if (Usage <= kUsageNormalLast)
{
*p_ByteIndex = 1 + static_cast<int>(Usage / 8U);
*p_BitMask = static_cast<quint8>(1U << (Usage % 8U));
return true;
}
return false;
}
} // namespace
bool Com_Protocol_DecodeMessageType(
const QByteArray& PacketBody,
Com_Enum_ProtocolType* p_Type)
{
if (p_Type == nullptr)
{
return false;
}
QByteArray MessageBytes;
return Com_Protocol_DecodeEnvelope(PacketBody, p_Type, &MessageBytes);
}
bool Com_Protocol_TryTakePacket(
QByteArray* p_StreamBuffer,
QByteArray* p_PacketBody,
Com_Enum_ProtocolType* p_Type)
{
if ((p_StreamBuffer == nullptr) ||
(p_PacketBody == nullptr) ||
(p_Type == nullptr))
{
return false;
}
p_PacketBody->clear();
*p_Type = Com_Enum_ProtocolType_None;
if (p_StreamBuffer->isEmpty())
{
return false;
}
int Offset = 0;
quint32 FieldNumber = 0;
quint8 WireType = 0;
if (!Com_Protocol_ReadKey(*p_StreamBuffer, &Offset, &FieldNumber, &WireType))
{
return false;
}
const Com_Enum_ProtocolType Type = Com_Protocol_TypeForFieldNumber(FieldNumber);
if ((Type == Com_Enum_ProtocolType_None) || (WireType != kProtoWireBytes))
{
return false;
}
QByteArray MessageBytes;
if (!Com_Protocol_ReadLengthDelimited(*p_StreamBuffer, &Offset, &MessageBytes))
{
return false;
}
*p_PacketBody = p_StreamBuffer->left(Offset);
*p_Type = Type;
p_StreamBuffer->remove(0, Offset);
return true;
}
QByteArray Com_Protocol_EncodeHelloReq()
{
QByteArray MessageBytes;
Com_Protocol_AppendUInt32Field(&MessageBytes, 1, 1);
return Com_Protocol_EncodeEnvelope(Com_Enum_ProtocolType_HelloReq, MessageBytes);
}
QByteArray Com_Protocol_EncodeBitmap(const QByteArray& UsageBitmap)
{
if (!Com_Protocol_IsUsageBitmapValid(UsageBitmap))
{
return QByteArray();
}
QByteArray MessageBytes;
Com_Protocol_AppendBytesField(&MessageBytes, 1, UsageBitmap);
return Com_Protocol_EncodeEnvelope(Com_Enum_ProtocolType_Bitmap, MessageBytes);
}
QByteArray Com_Protocol_EncodeTimeSync(
quint32 Version,
quint32 Flags,
qint32 TimezoneMinutes,
quint64 UtcMilliseconds,
quint32 AccuracyMilliseconds)
{
QByteArray MessageBytes;
Com_Protocol_AppendUInt32Field(&MessageBytes, 1, Version);
Com_Protocol_AppendUInt32Field(&MessageBytes, 2, Flags);
Com_Protocol_AppendSInt32Field(&MessageBytes, 3, TimezoneMinutes);
Com_Protocol_AppendFixed64Field(&MessageBytes, 4, UtcMilliseconds);
Com_Protocol_AppendFixed32Field(&MessageBytes, 5, AccuracyMilliseconds);
return Com_Protocol_EncodeEnvelope(Com_Enum_ProtocolType_TimeSync, MessageBytes);
}
QByteArray Com_Protocol_EncodeThemeRgb(quint8 Red, quint8 Green, quint8 Blue)
{
QByteArray MessageBytes;
Com_Protocol_AppendUInt32Field(&MessageBytes, 1, Red);
Com_Protocol_AppendUInt32Field(&MessageBytes, 2, Green);
Com_Protocol_AppendUInt32Field(&MessageBytes, 3, Blue);
return Com_Protocol_EncodeEnvelope(Com_Enum_ProtocolType_ThemeRgb, MessageBytes);
}
bool Com_Protocol_DecodeHelloRsp(
const QByteArray& PacketBody,
Com_Struct_ProtocolHelloRsp* p_Message)
{
Com_Enum_ProtocolType Type = Com_Enum_ProtocolType_None;
QByteArray MessageBytes;
if ((p_Message == nullptr) ||
!Com_Protocol_DecodeEnvelope(PacketBody, &Type, &MessageBytes) ||
(Type != Com_Enum_ProtocolType_HelloRsp))
{
return false;
}
return Com_Protocol_DecodeHelloRspMessage(MessageBytes, p_Message);
}
bool Com_Protocol_DecodeFunctionKeyEvent(
const QByteArray& PacketBody,
Com_Struct_ProtocolFunctionKeyEvent* p_Message)
{
Com_Enum_ProtocolType Type = Com_Enum_ProtocolType_None;
QByteArray MessageBytes;
if ((p_Message == nullptr) ||
!Com_Protocol_DecodeEnvelope(PacketBody, &Type, &MessageBytes) ||
(Type != Com_Enum_ProtocolType_FunctionKeyEvent))
{
return false;
}
return Com_Protocol_DecodeFunctionKeyEventMessage(MessageBytes, p_Message);
}
bool Com_Protocol_DecodeLedState(
const QByteArray& PacketBody,
Com_Struct_ProtocolLedState* p_Message)
{
Com_Enum_ProtocolType Type = Com_Enum_ProtocolType_None;
QByteArray MessageBytes;
if ((p_Message == nullptr) ||
!Com_Protocol_DecodeEnvelope(PacketBody, &Type, &MessageBytes) ||
(Type != Com_Enum_ProtocolType_LedState))
{
return false;
}
return Com_Protocol_DecodeLedStateMessage(MessageBytes, p_Message);
}
bool Com_Protocol_DecodeAck(
const QByteArray& PacketBody,
Com_Struct_ProtocolAck* p_Message)
{
Com_Enum_ProtocolType Type = Com_Enum_ProtocolType_None;
QByteArray MessageBytes;
if ((p_Message == nullptr) ||
!Com_Protocol_DecodeEnvelope(PacketBody, &Type, &MessageBytes) ||
(Type != Com_Enum_ProtocolType_Ack))
{
return false;
}
return Com_Protocol_DecodeAckMessage(MessageBytes, p_Message);
}
bool Com_Protocol_DecodeError(
const QByteArray& PacketBody,
Com_Struct_ProtocolError* p_Message)
{
Com_Enum_ProtocolType Type = Com_Enum_ProtocolType_None;
QByteArray MessageBytes;
if ((p_Message == nullptr) ||
!Com_Protocol_DecodeEnvelope(PacketBody, &Type, &MessageBytes) ||
(Type != Com_Enum_ProtocolType_Error))
{
return false;
}
return Com_Protocol_DecodeErrorMessage(MessageBytes, p_Message);
}
bool Com_Protocol_DecodeAckForType(
const QByteArray& PacketBody,
Com_Enum_ProtocolType EnvelopeType,
Com_Struct_ProtocolAck* p_Message)
{
QByteArray MessageBytes;
if ((p_Message == nullptr) ||
(EnvelopeType != Com_Enum_ProtocolType_Ack) ||
!Com_Protocol_DecodeEnvelopeForExpectedType(
PacketBody,
Com_Enum_ProtocolType_Ack,
&MessageBytes))
{
return false;
}
return Com_Protocol_DecodeAckMessage(MessageBytes, p_Message);
}
bool Com_Protocol_DecodeErrorForType(
const QByteArray& PacketBody,
Com_Enum_ProtocolType EnvelopeType,
Com_Struct_ProtocolError* p_Message)
{
QByteArray MessageBytes;
if ((p_Message == nullptr) ||
(EnvelopeType != Com_Enum_ProtocolType_Error) ||
!Com_Protocol_DecodeEnvelopeForExpectedType(
PacketBody,
Com_Enum_ProtocolType_Error,
&MessageBytes))
{
return false;
}
return Com_Protocol_DecodeErrorMessage(MessageBytes, p_Message);
}
bool Com_Protocol_IsUsageBitmapValid(const QByteArray& UsageBitmap)
{
return UsageBitmap.size() == kUsageBitmapSize;
}
QByteArray Com_Protocol_CreateUsageBitmap()
{
return QByteArray(kUsageBitmapSize, 0);
}
bool Com_Protocol_TestUsageBitmapBit(const QByteArray& UsageBitmap, quint16 Usage)
{
int ByteIndex = 0;
quint8 BitMask = 0;
if (!Com_Protocol_IsUsageBitmapValid(UsageBitmap) ||
!Com_Protocol_GetBitmapPosition(Usage, &ByteIndex, &BitMask))
{
return false;
}
return (static_cast<quint8>(UsageBitmap.at(ByteIndex)) & BitMask) != 0U;
}
bool Com_Protocol_SetUsageBitmapBit(QByteArray* p_UsageBitmap, quint16 Usage, bool IsPressed)
{
int ByteIndex = 0;
quint8 BitMask = 0;
if ((p_UsageBitmap == nullptr) ||
!Com_Protocol_IsUsageBitmapValid(*p_UsageBitmap) ||
!Com_Protocol_GetBitmapPosition(Usage, &ByteIndex, &BitMask))
{
return false;
}
quint8 ByteValue = static_cast<quint8>(p_UsageBitmap->at(ByteIndex));
if (IsPressed)
{
ByteValue = static_cast<quint8>(ByteValue | BitMask);
}
else
{
ByteValue = static_cast<quint8>(ByteValue & ~BitMask);
}
(*p_UsageBitmap)[ByteIndex] = static_cast<char>(ByteValue);
return true;
}
QVector<quint16> Com_Protocol_BuildPressedUsageList(const QByteArray& UsageBitmap)
{
QVector<quint16> UsageList;
if (!Com_Protocol_IsUsageBitmapValid(UsageBitmap))
{
return UsageList;
}
for (quint16 Usage = 0; Usage <= kUsageNormalLast; ++Usage)
{
if (Com_Protocol_TestUsageBitmapBit(UsageBitmap, Usage))
{
UsageList.append(Usage);
}
}
for (quint16 Usage = kUsageModifierFirst; Usage <= kUsageModifierLast; ++Usage)
{
if (Com_Protocol_TestUsageBitmapBit(UsageBitmap, Usage))
{
UsageList.append(Usage);
}
}
return UsageList;
}

117
COM/Com_Protocol.h Normal file
View File

@@ -0,0 +1,117 @@
#pragma once
#include <QtCore/QByteArray>
#include <QtCore/QVector>
#include <QtGlobal>
enum Com_Enum_ProtocolType : quint8
{
Com_Enum_ProtocolType_None = 0x00,
Com_Enum_ProtocolType_HelloReq = 0x01,
Com_Enum_ProtocolType_HelloRsp = 0x02,
Com_Enum_ProtocolType_Bitmap = 0x10,
Com_Enum_ProtocolType_FunctionKeyEvent = 0x20,
Com_Enum_ProtocolType_LedState = 0x21,
Com_Enum_ProtocolType_TimeSync = 0x30,
Com_Enum_ProtocolType_ThemeRgb = 0x31,
Com_Enum_ProtocolType_Ack = 0x7E,
Com_Enum_ProtocolType_Error = 0x7F
};
enum Com_Enum_ProtocolErrorCode : quint32
{
Com_Enum_ProtocolErrorCode_None = 0,
Com_Enum_ProtocolErrorCode_UnknownType = 1,
Com_Enum_ProtocolErrorCode_InvalidLength = 2,
Com_Enum_ProtocolErrorCode_InvalidParam = 3,
Com_Enum_ProtocolErrorCode_NotReady = 4
};
enum Com_Enum_ProtocolKeyAction : quint32
{
Com_Enum_ProtocolKeyAction_None = 0,
Com_Enum_ProtocolKeyAction_Press = 1,
Com_Enum_ProtocolKeyAction_Release = 2
};
struct Com_Struct_ProtocolHelloRsp
{
quint32 ProtocolVersion = 0;
quint32 VendorId = 0;
quint32 ProductId = 0;
quint32 FirmwareMajor = 0;
quint32 FirmwareMinor = 0;
quint32 CapabilityFlags = 0;
};
struct Com_Struct_ProtocolFunctionKeyEvent
{
QByteArray UsageBitmap;
bool HasUsageAction = false;
quint16 Usage = 0;
quint32 Action = Com_Enum_ProtocolKeyAction_None;
};
struct Com_Struct_ProtocolLedState
{
quint32 LedMask = 0;
};
struct Com_Struct_ProtocolAck
{
quint32 AckedType = 0;
};
struct Com_Struct_ProtocolError
{
quint32 ErrorType = 0;
quint32 ErrorCode = 0;
};
bool Com_Protocol_DecodeMessageType(
const QByteArray& PacketBody,
Com_Enum_ProtocolType* p_Type);
bool Com_Protocol_TryTakePacket(
QByteArray* p_StreamBuffer,
QByteArray* p_PacketBody,
Com_Enum_ProtocolType* p_Type);
QByteArray Com_Protocol_EncodeHelloReq();
QByteArray Com_Protocol_EncodeBitmap(const QByteArray& UsageBitmap);
QByteArray Com_Protocol_EncodeTimeSync(
quint32 Version,
quint32 Flags,
qint32 TimezoneMinutes,
quint64 UtcMilliseconds,
quint32 AccuracyMilliseconds);
QByteArray Com_Protocol_EncodeThemeRgb(quint8 Red, quint8 Green, quint8 Blue);
bool Com_Protocol_DecodeHelloRsp(
const QByteArray& PacketBody,
Com_Struct_ProtocolHelloRsp* p_Message);
bool Com_Protocol_DecodeFunctionKeyEvent(
const QByteArray& PacketBody,
Com_Struct_ProtocolFunctionKeyEvent* p_Message);
bool Com_Protocol_DecodeLedState(
const QByteArray& PacketBody,
Com_Struct_ProtocolLedState* p_Message);
bool Com_Protocol_DecodeAck(
const QByteArray& PacketBody,
Com_Struct_ProtocolAck* p_Message);
bool Com_Protocol_DecodeError(
const QByteArray& PacketBody,
Com_Struct_ProtocolError* p_Message);
bool Com_Protocol_DecodeAckForType(
const QByteArray& PacketBody,
Com_Enum_ProtocolType EnvelopeType,
Com_Struct_ProtocolAck* p_Message);
bool Com_Protocol_DecodeErrorForType(
const QByteArray& PacketBody,
Com_Enum_ProtocolType EnvelopeType,
Com_Struct_ProtocolError* p_Message);
bool Com_Protocol_IsUsageBitmapValid(const QByteArray& UsageBitmap);
QByteArray Com_Protocol_CreateUsageBitmap();
bool Com_Protocol_TestUsageBitmapBit(const QByteArray& UsageBitmap, quint16 Usage);
bool Com_Protocol_SetUsageBitmapBit(QByteArray* p_UsageBitmap, quint16 Usage, bool IsPressed);
QVector<quint16> Com_Protocol_BuildPressedUsageList(const QByteArray& UsageBitmap);