first push
This commit is contained in:
320
LOGIC/Lgc_Core_Control.cpp
Normal file
320
LOGIC/Lgc_Core_Control.cpp
Normal file
@@ -0,0 +1,320 @@
|
||||
#include "LOGIC/Lgc_Core_Private.h"
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QTimeZone>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct Lgc_Core_Struct_ThemeColor
|
||||
{
|
||||
quint8 Red;
|
||||
quint8 Green;
|
||||
quint8 Blue;
|
||||
};
|
||||
|
||||
QString Lgc_Core_FormatThemeColor(quint8 Red, quint8 Green, quint8 Blue)
|
||||
{
|
||||
return QStringLiteral("%1 %2 %3")
|
||||
.arg(Red, 2, 16, QLatin1Char('0'))
|
||||
.arg(Green, 2, 16, QLatin1Char('0'))
|
||||
.arg(Blue, 2, 16, QLatin1Char('0'))
|
||||
.toUpper();
|
||||
}
|
||||
|
||||
Lgc_Core_Struct_ThemeColor Lgc_Core_GetNextThemeColor(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
p_State->IsAltThemeEnabled = !p_State->IsAltThemeEnabled;
|
||||
|
||||
if (p_State->IsAltThemeEnabled)
|
||||
{
|
||||
return { 0xF7, 0x25, 0x85 };
|
||||
}
|
||||
|
||||
return { 0x4C, 0xC9, 0xF0 };
|
||||
}
|
||||
|
||||
bool Lgc_Core_IsUsageInRange(quint16 Usage)
|
||||
{
|
||||
return Usage <= MID_CONST_KEYBOARD_USAGE_MAX;
|
||||
}
|
||||
|
||||
bool Lgc_Core_IsUsageEnabled(const QByteArray& Bitmap, quint16 Usage)
|
||||
{
|
||||
if (!Lgc_Core_IsUsageInRange(Usage) || (Bitmap.size() < MID_CONST_USAGE_BITMAP_SIZE))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const int ByteIndex = Usage / 8;
|
||||
const quint8 BitMask = static_cast<quint8>(1U << (Usage % 8));
|
||||
const quint8 ByteValue = static_cast<quint8>(Bitmap.at(ByteIndex));
|
||||
return (ByteValue & BitMask) != 0;
|
||||
}
|
||||
|
||||
void Lgc_Core_SetUsageEnabled(QByteArray* p_Bitmap, quint16 Usage, bool IsEnabled)
|
||||
{
|
||||
if (!Lgc_Core_IsUsageInRange(Usage))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_Bitmap->size() < MID_CONST_USAGE_BITMAP_SIZE)
|
||||
{
|
||||
Lgc_Core_FillMaskAllEnabled(p_Bitmap);
|
||||
}
|
||||
|
||||
const int ByteIndex = Usage / 8;
|
||||
const quint8 BitMask = static_cast<quint8>(1U << (Usage % 8));
|
||||
quint8 ByteValue = static_cast<quint8>(p_Bitmap->at(ByteIndex));
|
||||
|
||||
if (IsEnabled)
|
||||
{
|
||||
ByteValue = static_cast<quint8>(ByteValue | BitMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteValue = static_cast<quint8>(ByteValue & ~BitMask);
|
||||
}
|
||||
|
||||
(*p_Bitmap)[ByteIndex] = static_cast<char>(ByteValue);
|
||||
}
|
||||
|
||||
void Lgc_Core_RebuildKeyboardMask(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
if (p_State->FunctionMaskBitmap.size() < MID_CONST_USAGE_BITMAP_SIZE)
|
||||
{
|
||||
Lgc_Core_FillMaskAllEnabled(&p_State->FunctionMaskBitmap);
|
||||
}
|
||||
|
||||
p_State->KeyboardMaskBitmap.resize(MID_CONST_USAGE_BITMAP_SIZE);
|
||||
for (int Index = 0; Index < MID_CONST_USAGE_BITMAP_SIZE; ++Index)
|
||||
{
|
||||
p_State->KeyboardMaskBitmap[Index] = p_State->FunctionMaskBitmap.at(Index);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray Lgc_Core_BuildMaskPacket(const Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
QByteArray Packet(MID_CONST_PACKET_SIZE_VENDOR, 0);
|
||||
Packet[0] = static_cast<char>(Mid_Enum_ReportId_Vendor);
|
||||
for (int Index = 0; (Index < MID_CONST_USAGE_BITMAP_SIZE) && (Index < p_State->KeyboardMaskBitmap.size()); ++Index)
|
||||
{
|
||||
Packet[Index + 2] = p_State->KeyboardMaskBitmap.at(Index);
|
||||
}
|
||||
return Packet;
|
||||
}
|
||||
|
||||
QByteArray Lgc_Core_BuildCommandPacket(quint8 CommandId, const QByteArray& Payload)
|
||||
{
|
||||
QByteArray Packet(MID_CONST_PACKET_SIZE_VENDOR_COMMAND, 0);
|
||||
Packet[0] = static_cast<char>(Mid_Enum_ReportId_VendorCommand);
|
||||
Packet[1] = static_cast<char>(CommandId);
|
||||
for (int Index = 0; (Index < MID_CONST_PACKET_SIZE_VENDOR_COMMAND_DATA) && (Index < Payload.size()); ++Index)
|
||||
{
|
||||
Packet[Index + 2] = Payload.at(Index);
|
||||
}
|
||||
return Packet;
|
||||
}
|
||||
|
||||
bool Lgc_Core_SendPacket(
|
||||
Lgc_Core_Struct_State* p_State,
|
||||
const QByteArray& Packet,
|
||||
const QString& ExplainText)
|
||||
{
|
||||
QString RouteText;
|
||||
QString TextStatus;
|
||||
const auto AppendStatus = [&TextStatus](const QString& StatusText)
|
||||
{
|
||||
if (StatusText.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TextStatus.isEmpty())
|
||||
{
|
||||
TextStatus.append(QLatin1Char('\n'));
|
||||
}
|
||||
TextStatus.append(StatusText);
|
||||
};
|
||||
const auto AppendRoute = [&RouteText](const QString& RouteName)
|
||||
{
|
||||
if (RouteName.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RouteText.isEmpty())
|
||||
{
|
||||
RouteText.append(QStringLiteral(" -> "));
|
||||
}
|
||||
RouteText.append(RouteName);
|
||||
};
|
||||
const auto TrySendUsb = [&]() -> bool
|
||||
{
|
||||
if (!p_State->DriVendorPort.ReadPort.IsOpened)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QString UsbStatus;
|
||||
const QString RouteName = p_State->DriVendorPort.ReadPort.PortName;
|
||||
if (Dri_Vendor_Write(&p_State->DriVendorPort, Packet, &UsbStatus))
|
||||
{
|
||||
Lgc_Core_AppendPacketLog(
|
||||
p_State,
|
||||
QStringLiteral("发送"),
|
||||
RouteName,
|
||||
Packet,
|
||||
ExplainText);
|
||||
Lgc_Core_AppendStatusLog(p_State, UsbStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
AppendRoute(RouteName);
|
||||
AppendStatus(UsbStatus);
|
||||
return false;
|
||||
};
|
||||
const auto TrySendBle = [&]() -> bool
|
||||
{
|
||||
if (!p_State->DriBlePort.IsConnected)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QString BleStatus;
|
||||
if (Dri_Ble_Write(&p_State->DriBlePort, Packet, &BleStatus))
|
||||
{
|
||||
Lgc_Core_AppendPacketLog(
|
||||
p_State,
|
||||
QStringLiteral("发送"),
|
||||
QStringLiteral("Bluetooth/HID Vendor"),
|
||||
Packet,
|
||||
ExplainText);
|
||||
Lgc_Core_AppendStatusLog(p_State, BleStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
AppendRoute(QStringLiteral("Bluetooth/HID Vendor"));
|
||||
AppendStatus(BleStatus);
|
||||
return false;
|
||||
};
|
||||
|
||||
if (p_State->DriBlePort.IsConnected)
|
||||
{
|
||||
if (TrySendBle() || TrySendUsb())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (TrySendUsb())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (RouteText.isEmpty())
|
||||
{
|
||||
RouteText = QStringLiteral("Vendor");
|
||||
}
|
||||
if (TextStatus.isEmpty())
|
||||
{
|
||||
TextStatus = QStringLiteral("No connected USB/Bluetooth device was found.");
|
||||
}
|
||||
|
||||
Lgc_Core_AppendPacketLog(
|
||||
p_State,
|
||||
QStringLiteral("发送失败"),
|
||||
RouteText,
|
||||
Packet,
|
||||
ExplainText);
|
||||
Lgc_Core_AppendStatusLog(p_State, TextStatus);
|
||||
return false;
|
||||
}
|
||||
|
||||
qint64 Lgc_Core_GetBeijingTimestampMs()
|
||||
{
|
||||
return QDateTime::currentDateTimeUtc()
|
||||
.toTimeZone(QTimeZone("Asia/Shanghai"))
|
||||
.toMSecsSinceEpoch() + (8LL * 60LL * 60LL * 1000LL);
|
||||
}
|
||||
|
||||
QString Lgc_Core_GetBeijingTimeText(qint64 TimestampMs)
|
||||
{
|
||||
const QTimeZone BeijingTimeZone("Asia/Shanghai");
|
||||
return QDateTime::fromMSecsSinceEpoch(TimestampMs, Qt::UTC)
|
||||
.toTimeZone(BeijingTimeZone)
|
||||
.toString(QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Lgc_Core_FillMaskAllEnabled(QByteArray* p_UsageBitmap)
|
||||
{
|
||||
*p_UsageBitmap = QByteArray(MID_CONST_USAGE_BITMAP_SIZE, static_cast<char>(0xFF));
|
||||
}
|
||||
|
||||
bool Lgc_Core_SendCurrentMask(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
Lgc_Core_RebuildKeyboardMask(p_State);
|
||||
return Lgc_Core_SendPacket(
|
||||
p_State,
|
||||
Lgc_Core_BuildMaskPacket(p_State),
|
||||
QStringLiteral("0x04 键盘掩码同步"));
|
||||
}
|
||||
|
||||
bool Lgc_Core_ApplyFunctionConfig(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
Lgc_Core_FillMaskAllEnabled(&p_State->FunctionMaskBitmap);
|
||||
|
||||
const QVector<quint16> UsageList = Lgc_FunctionButton_GetConfigurableUsages();
|
||||
for (quint16 Usage : UsageList)
|
||||
{
|
||||
if (Lgc_FunctionButton_HasUsageFeature(p_State->FunctionButtonConfig, Usage))
|
||||
{
|
||||
Lgc_Core_SetUsageEnabled(&p_State->FunctionMaskBitmap, Usage, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (p_State->IsStarted &&
|
||||
(p_State->DriVendorPort.ReadPort.IsOpened || p_State->DriBlePort.IsConnected))
|
||||
{
|
||||
Lgc_Core_SendCurrentMask(p_State);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Lgc_Core_SendTimeSync(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
const qint64 TimestampMs = Lgc_Core_GetBeijingTimestampMs();
|
||||
QByteArray Payload(MID_CONST_PACKET_SIZE_VENDOR_COMMAND_DATA, 0);
|
||||
for (int Index = 0; Index < MID_CONST_PACKET_SIZE_VENDOR_COMMAND_DATA; ++Index)
|
||||
{
|
||||
Payload[Index] = static_cast<char>((static_cast<quint64>(TimestampMs) >> (Index * 8)) & 0xFF);
|
||||
}
|
||||
|
||||
return Lgc_Core_SendPacket(
|
||||
p_State,
|
||||
Lgc_Core_BuildCommandPacket(0x02, Payload),
|
||||
QStringLiteral("0x05 0x02 时间同步(北京时间毫秒值:%1,北京时间:%2)")
|
||||
.arg(QString::number(TimestampMs), Lgc_Core_GetBeijingTimeText(TimestampMs)));
|
||||
}
|
||||
|
||||
bool Lgc_Core_SendThemeSwitch(Lgc_Core_Struct_State* p_State)
|
||||
{
|
||||
const Lgc_Core_Struct_ThemeColor ThemeColor = Lgc_Core_GetNextThemeColor(p_State);
|
||||
QByteArray Payload(MID_CONST_PACKET_SIZE_VENDOR_COMMAND_DATA, 0);
|
||||
Payload[0] = static_cast<char>(ThemeColor.Red);
|
||||
Payload[1] = static_cast<char>(ThemeColor.Green);
|
||||
Payload[2] = static_cast<char>(ThemeColor.Blue);
|
||||
|
||||
return Lgc_Core_SendPacket(
|
||||
p_State,
|
||||
Lgc_Core_BuildCommandPacket(0x01, Payload),
|
||||
QStringLiteral("0x05 0x01 theme switch (RGB:%1)")
|
||||
.arg(Lgc_Core_FormatThemeColor(
|
||||
ThemeColor.Red,
|
||||
ThemeColor.Green,
|
||||
ThemeColor.Blue)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user