#include "LOGIC/Lgc_Core.h" #include "MID/Mid_Def.h" #include #include #include 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(UsageBitmap.at(ByteIndex)) & static_cast(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(1U << (Usage % 8)); quint8 Value = static_cast(p_UsageBitmap->at(ByteIndex)); Value = IsEnabled ? static_cast(Value | BitMask) : static_cast(Value & static_cast(~BitMask)); (*p_UsageBitmap)[ByteIndex] = static_cast(Value); } void Lgc_Core_Func_FillMaskAllEnabled(QByteArray* p_UsageBitmap) { *p_UsageBitmap = QByteArray(MID_CONST_USAGE_BITMAP_SIZE, static_cast(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(0xFF)); for (int Index = 0; Index < MID_CONST_USAGE_BITMAP_SIZE; ++Index) { p_State->KeyboardMaskBitmap[Index] = static_cast( static_cast(p_State->FunctionMaskBitmap.at(Index)) & static_cast(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(Mid_Enum_ReportId_Vendor); Packet[1] = static_cast(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); }