添加项目文件。

This commit is contained in:
2026-03-26 10:45:29 +08:00
parent 10441f488c
commit b576d3f19d
48 changed files with 4812 additions and 0 deletions

606
LOGIC/Lgc_Core.cpp Normal file
View File

@@ -0,0 +1,606 @@
#include "LOGIC/Lgc_Core.h"
#include "MID/Mid_Def.h"
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
#include <Windows.h>
namespace
{
/* ---------- 日志与状态文本 ---------- */
QString Lgc_Core_Func_GetTimeText()
{
return QDateTime::currentDateTime().toString(QStringLiteral("HH:mm:ss.zzz"));
}
void Lgc_Core_Func_AppendLog(Lgc_Core_Struct_State* p_State, const QString& Text)
{
if (Text.isEmpty())
{
return;
}
if (p_State->TextLog.isEmpty())
{
p_State->TextLog = Text;
}
else
{
p_State->TextLog.append(QStringLiteral("\n\n"));
p_State->TextLog.append(Text);
}
if (p_State->TextLog.size() > 24000)
{
p_State->TextLog = p_State->TextLog.right(20000);
}
}
void Lgc_Core_Func_AppendStatusLog(Lgc_Core_Struct_State* p_State, const QString& Text)
{
if (!Text.isEmpty())
{
Lgc_Core_Func_AppendLog(
p_State,
QStringLiteral("[%1] 状态\n%2").arg(Lgc_Core_Func_GetTimeText(), Text));
}
}
void Lgc_Core_Func_AppendPacketLog(
Lgc_Core_Struct_State* p_State,
const QString& ActionText,
const QString& PortName,
const QByteArray& Packet,
const QString& ExplainText)
{
QString Text = QStringLiteral("[%1] %2\n端口: %3\nHEX: %4")
.arg(Lgc_Core_Func_GetTimeText(), ActionText, PortName, Mid_Func_GetHexText(Packet));
if (!ExplainText.isEmpty())
{
Text.append(QLatin1Char('\n'));
Text.append(ExplainText);
}
Lgc_Core_Func_AppendLog(p_State, Text);
}
struct Lgc_Core_Struct_MaskStateBackup
{
QByteArray FunctionMaskBitmap;
QByteArray SwapMaskBitmap;
QByteArray KeyboardMaskBitmap;
bool IsSwapModeOn = false;
quint16 SwapUsageLeft = 0;
quint16 SwapUsageRight = 0;
bool IsSwapLeftPhysicalPressed = false;
bool IsSwapRightPhysicalPressed = false;
};
/* ---------- 按键状态与掩码 ---------- */
void Lgc_Core_Func_ClearAllKeyStates(Lgc_Core_Struct_State* p_State)
{
p_State->IsVisibleKeyStateValid = false;
p_State->VisibleModifier = 0;
p_State->VisibleUsageList.clear();
p_State->IsPhysicalKeyStateValid = false;
p_State->PhysicalModifier = 0;
p_State->PhysicalUsageList.clear();
p_State->LastPhysicalUsageList.clear();
p_State->IsSwapLeftPhysicalPressed = false;
p_State->IsSwapRightPhysicalPressed = false;
}
void Lgc_Core_Func_CloseAllPorts(Lgc_Core_Struct_State* p_State)
{
Dri_NkroRaw_Func_Close(&p_State->DriNkroPort);
Dri_Consumer_Func_Close(&p_State->DriConsumerPort);
Dri_Vendor_Func_Close(&p_State->DriVendorPort);
}
Lgc_Core_Struct_MaskStateBackup Lgc_Core_Func_BackupMaskState(const Lgc_Core_Struct_State* p_State)
{
return {
p_State->FunctionMaskBitmap,
p_State->SwapMaskBitmap,
p_State->KeyboardMaskBitmap,
p_State->IsSwapModeOn,
p_State->SwapUsageLeft,
p_State->SwapUsageRight,
p_State->IsSwapLeftPhysicalPressed,
p_State->IsSwapRightPhysicalPressed
};
}
void Lgc_Core_Func_RestoreMaskState(
Lgc_Core_Struct_State* p_State,
const Lgc_Core_Struct_MaskStateBackup& Backup)
{
p_State->FunctionMaskBitmap = Backup.FunctionMaskBitmap;
p_State->SwapMaskBitmap = Backup.SwapMaskBitmap;
p_State->KeyboardMaskBitmap = Backup.KeyboardMaskBitmap;
p_State->IsSwapModeOn = Backup.IsSwapModeOn;
p_State->SwapUsageLeft = Backup.SwapUsageLeft;
p_State->SwapUsageRight = Backup.SwapUsageRight;
p_State->IsSwapLeftPhysicalPressed = Backup.IsSwapLeftPhysicalPressed;
p_State->IsSwapRightPhysicalPressed = Backup.IsSwapRightPhysicalPressed;
}
bool Lgc_Core_Func_IsUsageEnabledInMask(const QByteArray& UsageBitmap, quint16 Usage)
{
const int ByteIndex = Usage / 8;
if (ByteIndex >= UsageBitmap.size())
{
return false;
}
return (static_cast<quint8>(UsageBitmap.at(ByteIndex)) &
static_cast<quint8>(1U << (Usage % 8))) != 0;
}
void Lgc_Core_Func_SetUsageEnabledInMask(QByteArray* p_UsageBitmap, quint16 Usage, bool IsEnabled)
{
const int ByteIndex = Usage / 8;
if (ByteIndex >= p_UsageBitmap->size())
{
return;
}
const quint8 BitMask = static_cast<quint8>(1U << (Usage % 8));
quint8 Value = static_cast<quint8>(p_UsageBitmap->at(ByteIndex));
Value = IsEnabled ? static_cast<quint8>(Value | BitMask) : static_cast<quint8>(Value & static_cast<quint8>(~BitMask));
(*p_UsageBitmap)[ByteIndex] = static_cast<char>(Value);
}
void Lgc_Core_Func_FillMaskAllEnabled(QByteArray* p_UsageBitmap)
{
*p_UsageBitmap = QByteArray(MID_CONST_USAGE_BITMAP_SIZE, static_cast<char>(0xFF));
}
void Lgc_Core_Func_RebuildKeyboardMask(Lgc_Core_Struct_State* p_State)
{
if (p_State->FunctionMaskBitmap.size() != MID_CONST_USAGE_BITMAP_SIZE)
{
Lgc_Core_Func_FillMaskAllEnabled(&p_State->FunctionMaskBitmap);
}
if (p_State->SwapMaskBitmap.size() != MID_CONST_USAGE_BITMAP_SIZE)
{
Lgc_Core_Func_FillMaskAllEnabled(&p_State->SwapMaskBitmap);
}
p_State->KeyboardMaskBitmap = QByteArray(MID_CONST_USAGE_BITMAP_SIZE, static_cast<char>(0xFF));
for (int Index = 0; Index < MID_CONST_USAGE_BITMAP_SIZE; ++Index)
{
p_State->KeyboardMaskBitmap[Index] = static_cast<char>(
static_cast<quint8>(p_State->FunctionMaskBitmap.at(Index)) &
static_cast<quint8>(p_State->SwapMaskBitmap.at(Index)));
}
}
QByteArray Lgc_Core_Func_BuildVendorMaskPacket(const Lgc_Core_Struct_State* p_State)
{
QByteArray Packet(MID_CONST_PACKET_SIZE_VENDOR, 0);
Packet[0] = static_cast<char>(Mid_Enum_ReportId_Vendor);
Packet[1] = static_cast<char>(0xFF);
for (int Index = 0; Index < MID_CONST_USAGE_BITMAP_SIZE; ++Index)
{
Packet[2 + Index] = p_State->KeyboardMaskBitmap.at(Index);
}
return Packet;
}
bool Lgc_Core_Func_WriteCurrentMask(
Lgc_Core_Struct_State* p_State,
QString* p_TextStatus,
QByteArray* p_Packet)
{
Lgc_Core_Func_RebuildKeyboardMask(p_State);
if (p_Packet != nullptr)
{
*p_Packet = Lgc_Core_Func_BuildVendorMaskPacket(p_State);
}
if (!p_State->DriVendorPort.IsOpened)
{
if (p_TextStatus != nullptr)
{
*p_TextStatus = QStringLiteral("Vendor 接口未打开,无法同步当前掩码。");
}
return false;
}
const QByteArray Packet = (p_Packet != nullptr) ? *p_Packet : Lgc_Core_Func_BuildVendorMaskPacket(p_State);
return Dri_Vendor_Func_Write(&p_State->DriVendorPort, Packet, p_TextStatus);
}
bool Lgc_Core_Func_CommitMaskChange(
Lgc_Core_Struct_State* p_State,
const Lgc_Core_Struct_MaskStateBackup& Backup,
const QString& ExplainText)
{
QString TextStatus;
QByteArray Packet;
if (!Lgc_Core_Func_WriteCurrentMask(p_State, &TextStatus, &Packet))
{
Lgc_Core_Func_RestoreMaskState(p_State, Backup);
Lgc_Core_Func_AppendStatusLog(p_State, TextStatus);
return false;
}
Lgc_Core_Func_AppendStatusLog(p_State, TextStatus);
Lgc_Core_Func_AppendPacketLog(p_State, QStringLiteral("鍙戦€?"), QStringLiteral("Vendor"), Packet, ExplainText);
return true;
}
/* ---------- 数据包解析 ---------- */
bool Lgc_Core_Func_SyncSystemState(Lgc_Core_Struct_State* p_State)
{
const bool OldNumLock = p_State->IsSystemNumLockOn;
const bool OldConnected = p_State->IsConnected;
const QString OldConnection = p_State->TextConnection;
p_State->IsSystemNumLockOn = (GetKeyState(VK_NUMLOCK) & 0x0001) != 0;
p_State->IsConnected = p_State->DriVendorPort.IsOpened;
p_State->TextConnection = p_State->IsConnected
? QStringLiteral("已连接到 0xFF00 / 0x0002 Vendor 接口。")
: QStringLiteral("未连接到目标 Vendor 接口。");
return (OldNumLock != p_State->IsSystemNumLockOn) ||
(OldConnected != p_State->IsConnected) ||
(OldConnection != p_State->TextConnection);
}
void Lgc_Core_Func_HandleNkroPacket(Lgc_Core_Struct_State* p_State, const Mid_Struct_RawPacket& Packet)
{
Lgc_Nkro_Struct_Result Result;
Lgc_Nkro_Func_Parse(Packet.ByteArray, &Result);
if (Result.IsMatch && Result.IsLengthOk)
{
p_State->IsVisibleKeyStateValid = true;
p_State->VisibleModifier = Result.Modifier;
p_State->VisibleUsageList = Result.UsageList;
}
Lgc_Core_Func_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, Result.TextExplain);
}
void Lgc_Core_Func_HandleConsumerPacket(Lgc_Core_Struct_State* p_State, const Mid_Struct_RawPacket& Packet)
{
Lgc_Consumer_Struct_Result Result;
Lgc_Consumer_Func_Parse(Packet.ByteArray, &Result);
Lgc_Core_Func_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, Result.TextExplain);
}
void Lgc_Core_Func_HandleVendorPacket(Lgc_Core_Struct_State* p_State, const Mid_Struct_RawPacket& Packet)
{
Lgc_Vendor_Struct_Result Result;
Lgc_Vendor_Func_Parse(Packet.ByteArray, &Result);
if (Result.IsMatch && Result.IsLengthOk && Result.VendorState.IsValid)
{
p_State->IsPhysicalKeyStateValid = true;
p_State->PhysicalModifier = Result.VendorState.Modifier;
p_State->PhysicalUsageList = Result.VendorState.UsageList;
}
Lgc_Core_Func_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, Result.TextExplain);
}
/* ---------- 功能键与交换逻辑 ---------- */
bool Lgc_Core_Func_HandleFunctionButtons(Lgc_Core_Struct_State* p_State)
{
if (!p_State->IsPhysicalKeyStateValid)
{
p_State->LastPhysicalUsageList.clear();
return false;
}
bool IsChanged = false;
for (quint16 Usage : p_State->PhysicalUsageList)
{
if (p_State->LastPhysicalUsageList.contains(Usage) || !Lgc_Core_Func_IsUsageFunctionMode(p_State, Usage))
{
continue;
}
QString TextStatus;
if (!Lgc_Func_Button_Func_HandlePressedUsage(p_State, Usage, &TextStatus) || TextStatus.isEmpty())
{
continue;
}
p_State->TextFunctionStatus = TextStatus;
Lgc_Core_Func_AppendStatusLog(p_State, TextStatus);
IsChanged = true;
}
p_State->LastPhysicalUsageList = p_State->PhysicalUsageList;
return IsChanged;
}
void Lgc_Core_Func_ReleaseSwapOutputs(
quint16 UsageLeft,
quint16 UsageRight,
bool IsSwapLeftPhysicalPressed,
bool IsSwapRightPhysicalPressed)
{
if (IsSwapLeftPhysicalPressed)
{
Lgc_Func_Button_Func_SendUsageToWindows(UsageRight, false);
}
if (IsSwapRightPhysicalPressed)
{
Lgc_Func_Button_Func_SendUsageToWindows(UsageLeft, false);
}
}
void Lgc_Core_Func_ReleaseSwapOutputs(Lgc_Core_Struct_State* p_State)
{
Lgc_Core_Func_ReleaseSwapOutputs(
p_State->SwapUsageLeft,
p_State->SwapUsageRight,
p_State->IsSwapLeftPhysicalPressed,
p_State->IsSwapRightPhysicalPressed);
p_State->IsSwapLeftPhysicalPressed = false;
p_State->IsSwapRightPhysicalPressed = false;
}
bool Lgc_Core_Func_HandleSwapSource(
Lgc_Core_Struct_State* p_State,
quint16 PhysicalUsage,
quint16 TargetUsage,
bool* p_IsPhysicalPressed)
{
const bool IsPressedNow = p_State->PhysicalUsageList.contains(PhysicalUsage);
if (IsPressedNow == *p_IsPhysicalPressed)
{
return false;
}
if (!Lgc_Func_Button_Func_SendUsageToWindows(TargetUsage, IsPressedNow))
{
p_State->TextFunctionStatus = QStringLiteral("按键交换补发失败。");
Lgc_Core_Func_AppendStatusLog(p_State, p_State->TextFunctionStatus);
return true;
}
*p_IsPhysicalPressed = IsPressedNow;
return true;
}
bool Lgc_Core_Func_HandleSwapMode(Lgc_Core_Struct_State* p_State)
{
const bool HadInjectedKey = p_State->IsSwapLeftPhysicalPressed || p_State->IsSwapRightPhysicalPressed;
if (!p_State->IsSwapModeOn || !p_State->IsPhysicalKeyStateValid)
{
Lgc_Core_Func_ReleaseSwapOutputs(p_State);
return HadInjectedKey;
}
bool IsChanged = false;
IsChanged |= Lgc_Core_Func_HandleSwapSource(
p_State,
p_State->SwapUsageLeft,
p_State->SwapUsageRight,
&p_State->IsSwapLeftPhysicalPressed);
IsChanged |= Lgc_Core_Func_HandleSwapSource(
p_State,
p_State->SwapUsageRight,
p_State->SwapUsageLeft,
&p_State->IsSwapRightPhysicalPressed);
return IsChanged;
}
} // namespace
/* ---------- 对外接口 ---------- */
void Lgc_Core_Func_Init(Lgc_Core_Struct_State* p_State)
{
p_State->DriNkroPort = Dri_NkroRaw_Struct_Port();
p_State->DriConsumerPort = Dri_Consumer_Struct_Port();
p_State->DriVendorPort = Dri_Vendor_Struct_Port();
p_State->DeviceConfig = Mid_Struct_DeviceConfig();
p_State->TextConnection = QStringLiteral("未连接,等待枚举设备。");
p_State->TextLog.clear();
p_State->TextFunctionStatus = QStringLiteral("等待功能键动作。");
Lgc_Core_Func_ClearAllKeyStates(p_State);
p_State->IsSystemNumLockOn = (GetKeyState(VK_NUMLOCK) & 0x0001) != 0;
Lgc_Core_Func_FillMaskAllEnabled(&p_State->FunctionMaskBitmap);
Lgc_Core_Func_FillMaskAllEnabled(&p_State->SwapMaskBitmap);
Lgc_Core_Func_FillMaskAllEnabled(&p_State->KeyboardMaskBitmap);
p_State->FunctionButtonConfig = Lgc_Func_Button_Struct_Config();
p_State->SwapUsageLeft = p_State->FunctionButtonConfig.SwapUsageLeft;
p_State->SwapUsageRight = p_State->FunctionButtonConfig.SwapUsageRight;
p_State->WindowHandle = nullptr;
p_State->IsConnected = false;
p_State->IsStarted = false;
}
void Lgc_Core_Func_SetWindowHandle(Lgc_Core_Struct_State* p_State, void* WindowHandle)
{
p_State->WindowHandle = WindowHandle;
}
void Lgc_Core_Func_HandleNativeMessage(Lgc_Core_Struct_State* p_State, void* p_Message)
{
QString TextStatus;
Dri_NkroRaw_Func_HandleNativeMessage(&p_State->DriNkroPort, p_Message, &TextStatus);
Lgc_Core_Func_AppendStatusLog(p_State, TextStatus);
}
void Lgc_Core_Func_Start(Lgc_Core_Struct_State* p_State)
{
if (p_State->IsStarted)
{
return;
}
p_State->IsStarted = true;
Lgc_Core_Func_RefreshDevice(p_State);
}
void Lgc_Core_Func_Close(Lgc_Core_Struct_State* p_State)
{
Lgc_Core_Func_ReleaseSwapOutputs(p_State);
Lgc_Core_Func_CloseAllPorts(p_State);
p_State->TextConnection = QStringLiteral("未连接,等待枚举设备。");
p_State->TextFunctionStatus = QStringLiteral("等待功能键动作。");
p_State->IsConnected = false;
Lgc_Core_Func_ClearAllKeyStates(p_State);
}
void Lgc_Core_Func_RefreshDevice(Lgc_Core_Struct_State* p_State)
{
Lgc_Core_Func_ReleaseSwapOutputs(p_State);
Lgc_Core_Func_CloseAllPorts(p_State);
Lgc_Core_Func_ClearAllKeyStates(p_State);
const auto OpenPort = [p_State](auto OpenFunc, auto* p_Port, auto... Args)
{
QString TextStatus;
OpenFunc(p_Port, Args..., &TextStatus);
Lgc_Core_Func_AppendStatusLog(p_State, TextStatus);
};
OpenPort(Dri_NkroRaw_Func_Open, &p_State->DriNkroPort, p_State->DeviceConfig, p_State->WindowHandle);
OpenPort(Dri_Consumer_Func_Open, &p_State->DriConsumerPort, p_State->DeviceConfig);
OpenPort(Dri_Vendor_Func_Open, &p_State->DriVendorPort, p_State->DeviceConfig);
QString TextStatus;
TextStatus.clear();
Lgc_Core_Func_WriteCurrentMask(p_State, &TextStatus, nullptr);
Lgc_Core_Func_AppendStatusLog(p_State, TextStatus);
Lgc_Core_Func_SyncSystemState(p_State);
}
void Lgc_Core_Func_ClearLog(Lgc_Core_Struct_State* p_State)
{
p_State->TextLog.clear();
}
bool Lgc_Core_Func_Poll(Lgc_Core_Struct_State* p_State)
{
bool IsChanged = false;
Mid_Struct_RawPacket Packet;
const auto PollPort = [p_State, &Packet, &IsChanged](auto ReadFunc, auto* p_Port, auto HandlePacket)
{
QString TextStatus;
if (ReadFunc(p_Port, &Packet, &TextStatus))
{
HandlePacket(p_State, Packet);
IsChanged = true;
}
if (!TextStatus.isEmpty())
{
Lgc_Core_Func_AppendStatusLog(p_State, TextStatus);
IsChanged = true;
}
};
PollPort(Dri_NkroRaw_Func_Read, &p_State->DriNkroPort, Lgc_Core_Func_HandleNkroPacket);
PollPort(Dri_Consumer_Func_Read, &p_State->DriConsumerPort, Lgc_Core_Func_HandleConsumerPacket);
PollPort(Dri_Vendor_Func_Read, &p_State->DriVendorPort, Lgc_Core_Func_HandleVendorPacket);
IsChanged |= Lgc_Core_Func_HandleFunctionButtons(p_State);
IsChanged |= Lgc_Core_Func_HandleSwapMode(p_State);
IsChanged |= Lgc_Core_Func_SyncSystemState(p_State);
return IsChanged;
}
bool Lgc_Core_Func_SetUsageFunctionMode(Lgc_Core_Struct_State* p_State, quint16 Usage, bool IsEnabled)
{
if (p_State->FunctionMaskBitmap.size() != MID_CONST_USAGE_BITMAP_SIZE)
{
Lgc_Core_Func_FillMaskAllEnabled(&p_State->FunctionMaskBitmap);
}
if (Lgc_Core_Func_IsUsageFunctionMode(p_State, Usage) == IsEnabled)
{
return true;
}
const Lgc_Core_Struct_MaskStateBackup Backup = Lgc_Core_Func_BackupMaskState(p_State);
Lgc_Core_Func_SetUsageEnabledInMask(&p_State->FunctionMaskBitmap, Usage, !IsEnabled);
const QString ExplainText = IsEnabled
? QStringLiteral("已把 %1 切到功能键模式。").arg(Mid_Func_GetKeyboardUsageText(Usage))
: QStringLiteral("已恢复 %1 的普通键模式。").arg(Mid_Func_GetKeyboardUsageText(Usage));
return Lgc_Core_Func_CommitMaskChange(p_State, Backup, ExplainText);
}
bool Lgc_Core_Func_SetSwapMode(
Lgc_Core_Struct_State* p_State,
quint16 UsageLeft,
quint16 UsageRight,
bool IsEnabled)
{
if ((UsageLeft == 0) || (UsageRight == 0) || (UsageLeft == UsageRight))
{
return false;
}
if ((p_State->IsSwapModeOn == IsEnabled) &&
(p_State->SwapUsageLeft == UsageLeft) &&
(p_State->SwapUsageRight == UsageRight))
{
return true;
}
const Lgc_Core_Struct_MaskStateBackup Backup = Lgc_Core_Func_BackupMaskState(p_State);
p_State->IsSwapModeOn = IsEnabled;
p_State->SwapUsageLeft = UsageLeft;
p_State->SwapUsageRight = UsageRight;
Lgc_Core_Func_FillMaskAllEnabled(&p_State->SwapMaskBitmap);
if (IsEnabled)
{
Lgc_Core_Func_SetUsageEnabledInMask(&p_State->SwapMaskBitmap, UsageLeft, false);
Lgc_Core_Func_SetUsageEnabledInMask(&p_State->SwapMaskBitmap, UsageRight, false);
}
p_State->IsSwapLeftPhysicalPressed = false;
p_State->IsSwapRightPhysicalPressed = false;
const QString ExplainText = IsEnabled
? QStringLiteral("已开启按键交换:%1 <-> %2")
.arg(Mid_Func_GetKeyboardUsageText(UsageLeft))
.arg(Mid_Func_GetKeyboardUsageText(UsageRight))
: QStringLiteral("已关闭按键交换:%1 <-> %2")
.arg(Mid_Func_GetKeyboardUsageText(UsageLeft))
.arg(Mid_Func_GetKeyboardUsageText(UsageRight));
if (!Lgc_Core_Func_CommitMaskChange(p_State, Backup, ExplainText))
{
return false;
}
if (Backup.IsSwapModeOn &&
(!IsEnabled || (Backup.SwapUsageLeft != UsageLeft) || (Backup.SwapUsageRight != UsageRight)))
{
Lgc_Core_Func_ReleaseSwapOutputs(
Backup.SwapUsageLeft,
Backup.SwapUsageRight,
Backup.IsSwapLeftPhysicalPressed,
Backup.IsSwapRightPhysicalPressed);
}
return true;
}
bool Lgc_Core_Func_IsUsageFunctionMode(const Lgc_Core_Struct_State* p_State, quint16 Usage)
{
if (p_State->FunctionMaskBitmap.size() != MID_CONST_USAGE_BITMAP_SIZE)
{
return false;
}
return !Lgc_Core_Func_IsUsageEnabledInMask(p_State->FunctionMaskBitmap, Usage);
}