first push
This commit is contained in:
372
LOGIC/Lgc_Core_Input.cpp
Normal file
372
LOGIC/Lgc_Core_Input.cpp
Normal file
@@ -0,0 +1,372 @@
|
||||
#include "LOGIC/Lgc_Core_Private.h"
|
||||
|
||||
#include "MID/Mid_Ble.h"
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QTimeZone>
|
||||
#include <Windows.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
QString Lgc_Core_GetTimeText()
|
||||
{
|
||||
return QDateTime::currentDateTimeUtc()
|
||||
.toTimeZone(QTimeZone("Asia/Shanghai"))
|
||||
.toString(QStringLiteral("HH:mm:ss.zzz"));
|
||||
}
|
||||
|
||||
void Lgc_Core_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_CollectKeyboardUsage(
|
||||
const QByteArray& UsageBitmap,
|
||||
QVector<quint16>* p_UsageList,
|
||||
QStringList* p_UsageTextList)
|
||||
{
|
||||
p_UsageList->clear();
|
||||
p_UsageTextList->clear();
|
||||
|
||||
for (quint16 Usage = 0; Usage <= MID_CONST_KEYBOARD_USAGE_MAX; ++Usage)
|
||||
{
|
||||
const int ByteIndex = Usage / 8;
|
||||
const quint8 BitMask = static_cast<quint8>(1U << (Usage % 8));
|
||||
const quint8 ByteValue = static_cast<quint8>(UsageBitmap.at(ByteIndex));
|
||||
if ((ByteValue & BitMask) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
p_UsageList->append(Usage);
|
||||
p_UsageTextList->append(Mid_GetKeyboardUsageText(Usage));
|
||||
}
|
||||
}
|
||||
|
||||
bool Lgc_Core_HandleBleHidPacket(Lgc_Core_Struct_State* p_State, const Mid_Struct_RawPacket& Packet)
|
||||
{
|
||||
switch (Packet.Source)
|
||||
{
|
||||
case Mid_Enum_RawPacketSource_BleHidKeyboard:
|
||||
case Mid_Enum_RawPacketSource_BleHidConsumer:
|
||||
case Mid_Enum_RawPacketSource_BleHidVendor:
|
||||
case Mid_Enum_RawPacketSource_BleHidVendorCommand:
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Packet.ByteArray.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (static_cast<quint8>(Packet.ByteArray.at(0)))
|
||||
{
|
||||
case Mid_Enum_ReportId_Nkro:
|
||||
Lgc_Core_HandleNkroPacket(p_State, Packet);
|
||||
return true;
|
||||
|
||||
case Mid_Enum_ReportId_Consumer:
|
||||
Lgc_Core_HandleConsumerPacket(p_State, Packet);
|
||||
return true;
|
||||
|
||||
case Mid_Enum_ReportId_Vendor:
|
||||
case Mid_Enum_ReportId_VendorCommand:
|
||||
Lgc_Core_HandleVendorPacket(p_State, Packet);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Lgc_Core_UpdateSendTransportByPacket(
|
||||
Lgc_Core_Struct_State* p_State,
|
||||
Mid_Enum_RawPacketSource Source)
|
||||
{
|
||||
switch (Source)
|
||||
{
|
||||
case Mid_Enum_RawPacketSource_UsbNkroRaw:
|
||||
case Mid_Enum_RawPacketSource_UsbConsumerHid:
|
||||
case Mid_Enum_RawPacketSource_UsbVendorHid:
|
||||
p_State->ActiveSendTransport = Lgc_Core_Enum_SendTransport_Usb;
|
||||
break;
|
||||
|
||||
case Mid_Enum_RawPacketSource_BleGatt:
|
||||
case Mid_Enum_RawPacketSource_BleHidKeyboard:
|
||||
case Mid_Enum_RawPacketSource_BleHidConsumer:
|
||||
case Mid_Enum_RawPacketSource_BleHidVendor:
|
||||
case Mid_Enum_RawPacketSource_BleHidVendorCommand:
|
||||
p_State->ActiveSendTransport = Lgc_Core_Enum_SendTransport_Ble;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Lgc_Core_NormalizeSendTransport(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
const bool HasUsb = p_State->DriVendorPort.ReadPort.IsOpened;
|
||||
const bool HasBle = p_State->DriBlePort.IsConnected;
|
||||
|
||||
if ((p_State->ActiveSendTransport == Lgc_Core_Enum_SendTransport_Usb) && HasUsb)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_State->ActiveSendTransport == Lgc_Core_Enum_SendTransport_Ble) && HasBle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasBle && !HasUsb)
|
||||
{
|
||||
p_State->ActiveSendTransport = Lgc_Core_Enum_SendTransport_Ble;
|
||||
}
|
||||
else if (HasUsb && !HasBle)
|
||||
{
|
||||
p_State->ActiveSendTransport = Lgc_Core_Enum_SendTransport_Usb;
|
||||
}
|
||||
else if (!HasUsb && !HasBle)
|
||||
{
|
||||
p_State->ActiveSendTransport = Lgc_Core_Enum_SendTransport_None;
|
||||
}
|
||||
}
|
||||
|
||||
void Lgc_Core_AppendStatusLog(Lgc_Core_Struct_State* p_State, const QString& Text)
|
||||
{
|
||||
if (!Text.isEmpty())
|
||||
{
|
||||
Lgc_Core_AppendLog(
|
||||
p_State,
|
||||
QStringLiteral("[%1] 状态\n%2").arg(Lgc_Core_GetTimeText(), Text));
|
||||
}
|
||||
}
|
||||
|
||||
void Lgc_Core_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_GetTimeText(), ActionText, PortName, Mid_GetHexText(Packet));
|
||||
if (!ExplainText.isEmpty())
|
||||
{
|
||||
Text.append(QLatin1Char('\n'));
|
||||
Text.append(ExplainText);
|
||||
}
|
||||
Lgc_Core_AppendLog(p_State, Text);
|
||||
}
|
||||
|
||||
void Lgc_Core_ClearAllKeyStates(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
p_State->IsVisibleKeyStateValid = false;
|
||||
p_State->VisibleUsageList.clear();
|
||||
|
||||
p_State->IsPhysicalKeyStateValid = false;
|
||||
p_State->PhysicalUsageList.clear();
|
||||
p_State->LastPhysicalUsageList.clear();
|
||||
}
|
||||
|
||||
void Lgc_Core_CloseAllPorts(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
Dri_Ble_Close(&p_State->DriBlePort);
|
||||
Dri_NkroRaw_Close(&p_State->DriNkroPort);
|
||||
Dri_Consumer_Close(&p_State->DriConsumerPort);
|
||||
Dri_Vendor_Close(&p_State->DriVendorPort);
|
||||
}
|
||||
|
||||
bool Lgc_Core_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;
|
||||
const Lgc_Core_Enum_SendTransport OldSendTransport = p_State->ActiveSendTransport;
|
||||
|
||||
p_State->IsSystemNumLockOn = (GetKeyState(VK_NUMLOCK) & 0x0001) != 0;
|
||||
p_State->IsConnected = p_State->DriVendorPort.ReadPort.IsOpened || p_State->DriBlePort.IsConnected;
|
||||
Lgc_Core_NormalizeSendTransport(p_State);
|
||||
|
||||
QStringList Lines;
|
||||
if (p_State->DriVendorPort.ReadPort.IsOpened)
|
||||
{
|
||||
Lines.append(QStringLiteral("已连接 USB Vendor 接口。"));
|
||||
}
|
||||
if (!p_State->DriBlePort.TextEndpointSummary.isEmpty())
|
||||
{
|
||||
Lines.append(p_State->DriBlePort.TextEndpointSummary);
|
||||
}
|
||||
if (Lines.isEmpty())
|
||||
{
|
||||
Lines.append(QStringLiteral("未连接到目标设备。"));
|
||||
}
|
||||
|
||||
p_State->TextConnection = Lines.join(QLatin1Char('\n'));
|
||||
|
||||
return (OldNumLock != p_State->IsSystemNumLockOn) ||
|
||||
(OldConnected != p_State->IsConnected) ||
|
||||
(OldConnection != p_State->TextConnection) ||
|
||||
(OldSendTransport != p_State->ActiveSendTransport);
|
||||
}
|
||||
|
||||
void Lgc_Core_HandleNkroPacket(Lgc_Core_Struct_State* p_State, const Mid_Struct_RawPacket& Packet)
|
||||
{
|
||||
Lgc_Core_UpdateSendTransportByPacket(p_State, Packet.Source);
|
||||
|
||||
QString ExplainText = QStringLiteral("NKRO");
|
||||
if (!Packet.ByteArray.isEmpty() &&
|
||||
(static_cast<quint8>(Packet.ByteArray.at(0)) == Mid_Enum_ReportId_Nkro) &&
|
||||
(Packet.ByteArray.size() == MID_CONST_PACKET_SIZE_NKRO))
|
||||
{
|
||||
const quint8 Modifier = static_cast<quint8>(Packet.ByteArray.at(1));
|
||||
const QByteArray UsageBitmap = Packet.ByteArray.mid(2, MID_CONST_USAGE_BITMAP_SIZE);
|
||||
QVector<quint16> UsageList;
|
||||
QStringList UsageTextList;
|
||||
Lgc_Core_CollectKeyboardUsage(UsageBitmap, &UsageList, &UsageTextList);
|
||||
|
||||
p_State->IsVisibleKeyStateValid = true;
|
||||
p_State->VisibleUsageList = UsageList;
|
||||
ExplainText = QStringLiteral("NKRO %1 / %2")
|
||||
.arg(Mid_GetModifierText(Modifier),
|
||||
UsageTextList.isEmpty() ? QStringLiteral("无按键") : UsageTextList.join(QStringLiteral(", ")));
|
||||
}
|
||||
Lgc_Core_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, ExplainText);
|
||||
}
|
||||
|
||||
void Lgc_Core_HandleConsumerPacket(Lgc_Core_Struct_State* p_State, const Mid_Struct_RawPacket& Packet)
|
||||
{
|
||||
Lgc_Core_UpdateSendTransportByPacket(p_State, Packet.Source);
|
||||
|
||||
QString ExplainText = QStringLiteral("Consumer");
|
||||
if (!Packet.ByteArray.isEmpty() &&
|
||||
(static_cast<quint8>(Packet.ByteArray.at(0)) == Mid_Enum_ReportId_Consumer) &&
|
||||
(Packet.ByteArray.size() == MID_CONST_PACKET_SIZE_CONSUMER))
|
||||
{
|
||||
const quint16 Usage =
|
||||
static_cast<quint8>(Packet.ByteArray.at(1)) |
|
||||
(static_cast<quint16>(static_cast<quint8>(Packet.ByteArray.at(2))) << 8);
|
||||
ExplainText = QStringLiteral("Consumer %1").arg(Mid_GetConsumerUsageText(Usage));
|
||||
}
|
||||
Lgc_Core_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, ExplainText);
|
||||
}
|
||||
|
||||
void Lgc_Core_HandleVendorPacket(Lgc_Core_Struct_State* p_State, const Mid_Struct_RawPacket& Packet)
|
||||
{
|
||||
Lgc_Core_UpdateSendTransportByPacket(p_State, Packet.Source);
|
||||
|
||||
QString ExplainText = QStringLiteral("Vendor");
|
||||
if (Packet.ByteArray.isEmpty())
|
||||
{
|
||||
Lgc_Core_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, ExplainText);
|
||||
return;
|
||||
}
|
||||
|
||||
const quint8 ReportId = static_cast<quint8>(Packet.ByteArray.at(0));
|
||||
if ((ReportId == Mid_Enum_ReportId_Vendor) && (Packet.ByteArray.size() == MID_CONST_PACKET_SIZE_VENDOR))
|
||||
{
|
||||
const quint8 Modifier = static_cast<quint8>(Packet.ByteArray.at(1));
|
||||
const QByteArray UsageBitmap = Packet.ByteArray.mid(2, MID_CONST_USAGE_BITMAP_SIZE);
|
||||
QVector<quint16> UsageList;
|
||||
QStringList UsageTextList;
|
||||
Lgc_Core_CollectKeyboardUsage(UsageBitmap, &UsageList, &UsageTextList);
|
||||
p_State->IsPhysicalKeyStateValid = true;
|
||||
p_State->PhysicalUsageList = UsageList;
|
||||
ExplainText = QStringLiteral("Vendor %1 / %2")
|
||||
.arg(Mid_GetModifierText(Modifier),
|
||||
UsageTextList.isEmpty() ? QStringLiteral("无按键") : UsageTextList.join(QStringLiteral(", ")));
|
||||
}
|
||||
else if ((ReportId == Mid_Enum_ReportId_VendorCommand) && (Packet.ByteArray.size() >= 2))
|
||||
{
|
||||
ExplainText = QStringLiteral("VendorCmd 0x%1")
|
||||
.arg(static_cast<quint8>(Packet.ByteArray.at(1)), 2, 16, QLatin1Char('0'))
|
||||
.toUpper();
|
||||
}
|
||||
Lgc_Core_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, ExplainText);
|
||||
}
|
||||
|
||||
void Lgc_Core_HandleBlePacket(Lgc_Core_Struct_State* p_State, const Mid_Struct_RawPacket& Packet)
|
||||
{
|
||||
Lgc_Core_UpdateSendTransportByPacket(p_State, Packet.Source);
|
||||
|
||||
if (Lgc_Core_HandleBleHidPacket(p_State, Packet))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Packet.Source != Mid_Enum_RawPacketSource_BleGatt)
|
||||
{
|
||||
Lgc_Core_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, QStringLiteral("BLE"));
|
||||
return;
|
||||
}
|
||||
|
||||
const QString ExplainText = Packet.ByteArray.isEmpty()
|
||||
? QStringLiteral("BLE")
|
||||
: QStringLiteral("BLE %1").arg(Mid_GetBleOpcodeText(static_cast<quint8>(Packet.ByteArray.at(0))));
|
||||
Lgc_Core_AppendPacketLog(p_State, QStringLiteral("收到"), Packet.PortName, Packet.ByteArray, ExplainText);
|
||||
}
|
||||
|
||||
bool Lgc_Core_HandleFunctionButtons(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
if (!p_State->IsPhysicalKeyStateValid)
|
||||
{
|
||||
p_State->LastPhysicalUsageList.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_State->IsFunctionSequenceRecording)
|
||||
{
|
||||
p_State->LastPhysicalUsageList = p_State->PhysicalUsageList;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsChanged = false;
|
||||
for (quint16 Usage : p_State->PhysicalUsageList)
|
||||
{
|
||||
if (p_State->LastPhysicalUsageList.contains(Usage) ||
|
||||
!Lgc_FunctionButton_HasUsageFeature(p_State->FunctionButtonConfig, Usage))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QString TextStatus;
|
||||
if (!Lgc_FunctionButton_RunBinding(p_State, Usage, &TextStatus) || TextStatus.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
p_State->TextFunctionStatus = TextStatus;
|
||||
Lgc_Core_AppendStatusLog(p_State, TextStatus);
|
||||
IsChanged = true;
|
||||
}
|
||||
|
||||
p_State->LastPhysicalUsageList = p_State->PhysicalUsageList;
|
||||
return IsChanged;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user