Push layered Qt host source files
This commit is contained in:
623
DRI/Dri_Cdc.cpp
Normal file
623
DRI/Dri_Cdc.cpp
Normal file
@@ -0,0 +1,623 @@
|
||||
#include "DRI/Dri_Cdc.h"
|
||||
|
||||
#include "COM/Com_Protocol.h"
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QQueue>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
|
||||
struct Dri_Cdc_Struct_Candidate
|
||||
{
|
||||
QSerialPort* p_SerialPort = nullptr;
|
||||
QString PortName;
|
||||
QString EndpointId;
|
||||
QString SystemLocation;
|
||||
QByteArray PendingBytes;
|
||||
QQueue<Com_Struct_RawPacket> PacketQueue;
|
||||
};
|
||||
|
||||
struct Dri_Cdc_Struct_Context
|
||||
{
|
||||
QVector<Dri_Cdc_Struct_Candidate> CandidateList;
|
||||
int ActiveCandidateIndex = -1;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
QString Dri_Cdc_FormatPortLabel(const QSerialPortInfo& PortInfo)
|
||||
{
|
||||
const QString Description = PortInfo.description().trimmed();
|
||||
return Description.isEmpty()
|
||||
? QStringLiteral("USB CDC (%1)").arg(PortInfo.portName())
|
||||
: QStringLiteral("USB CDC (%1 - %2)").arg(PortInfo.portName(), Description);
|
||||
}
|
||||
|
||||
QString Dri_Cdc_BuildEndpointId(const QSerialPortInfo& PortInfo)
|
||||
{
|
||||
const QString SystemLocation = QDir::cleanPath(PortInfo.systemLocation());
|
||||
if (!SystemLocation.isEmpty())
|
||||
{
|
||||
return SystemLocation;
|
||||
}
|
||||
|
||||
return PortInfo.portName().trimmed();
|
||||
}
|
||||
|
||||
bool Dri_Cdc_IsPortStillPresent(const Dri_Cdc_Struct_Candidate& Candidate)
|
||||
{
|
||||
for (const QSerialPortInfo& PortInfo : QSerialPortInfo::availablePorts())
|
||||
{
|
||||
if (!Candidate.SystemLocation.isEmpty() &&
|
||||
(QDir::cleanPath(PortInfo.systemLocation())
|
||||
.compare(Candidate.SystemLocation, Qt::CaseInsensitive) == 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Dri_Cdc_DeleteCandidate(Dri_Cdc_Struct_Candidate* p_Candidate)
|
||||
{
|
||||
if (p_Candidate == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_Candidate->p_SerialPort != nullptr) && p_Candidate->p_SerialPort->isOpen())
|
||||
{
|
||||
p_Candidate->p_SerialPort->setDataTerminalReady(false);
|
||||
p_Candidate->p_SerialPort->close();
|
||||
}
|
||||
|
||||
delete p_Candidate->p_SerialPort;
|
||||
p_Candidate->p_SerialPort = nullptr;
|
||||
p_Candidate->PendingBytes.clear();
|
||||
p_Candidate->PacketQueue.clear();
|
||||
}
|
||||
|
||||
void Dri_Cdc_DeleteContext(Dri_Cdc_Struct_Context* p_Context)
|
||||
{
|
||||
if (p_Context == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int Index = 0; Index < p_Context->CandidateList.size(); ++Index)
|
||||
{
|
||||
Dri_Cdc_DeleteCandidate(&p_Context->CandidateList[Index]);
|
||||
}
|
||||
|
||||
delete p_Context;
|
||||
}
|
||||
|
||||
int Dri_Cdc_FindCandidateIndex(
|
||||
const Dri_Cdc_Struct_Context* p_Context,
|
||||
const QString& EndpointId)
|
||||
{
|
||||
if ((p_Context == nullptr) || EndpointId.trimmed().isEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int Index = 0; Index < p_Context->CandidateList.size(); ++Index)
|
||||
{
|
||||
const Dri_Cdc_Struct_Candidate& Candidate = p_Context->CandidateList.at(Index);
|
||||
if (Candidate.EndpointId.compare(EndpointId, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return Index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Dri_Cdc_RefreshPortSummary(
|
||||
Dri_Cdc_Struct_Port* p_Port,
|
||||
Dri_Cdc_Struct_Context* p_Context)
|
||||
{
|
||||
if ((p_Port == nullptr) || (p_Context == nullptr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_Context->ActiveCandidateIndex >= 0) &&
|
||||
((p_Context->ActiveCandidateIndex >= p_Context->CandidateList.size()) ||
|
||||
(p_Context->CandidateList.at(p_Context->ActiveCandidateIndex).p_SerialPort == nullptr) ||
|
||||
!p_Context->CandidateList.at(p_Context->ActiveCandidateIndex).p_SerialPort->isOpen()))
|
||||
{
|
||||
p_Context->ActiveCandidateIndex = -1;
|
||||
}
|
||||
|
||||
QStringList OpenedPortList;
|
||||
for (const Dri_Cdc_Struct_Candidate& Candidate : p_Context->CandidateList)
|
||||
{
|
||||
if ((Candidate.p_SerialPort != nullptr) && Candidate.p_SerialPort->isOpen())
|
||||
{
|
||||
OpenedPortList.append(Candidate.PortName);
|
||||
}
|
||||
}
|
||||
|
||||
if (OpenedPortList.isEmpty())
|
||||
{
|
||||
p_Port->IsOpened = false;
|
||||
p_Port->PortName.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
p_Port->IsOpened = true;
|
||||
if (p_Context->ActiveCandidateIndex >= 0)
|
||||
{
|
||||
p_Port->PortName =
|
||||
p_Context->CandidateList.at(p_Context->ActiveCandidateIndex).PortName;
|
||||
return;
|
||||
}
|
||||
|
||||
p_Port->PortName = OpenedPortList.size() == 1
|
||||
? OpenedPortList.first()
|
||||
: QStringLiteral("USB CDC candidates (%1)").arg(OpenedPortList.join(QStringLiteral(", ")));
|
||||
}
|
||||
|
||||
bool Dri_Cdc_WritePacket(
|
||||
Dri_Cdc_Struct_Candidate* p_Candidate,
|
||||
const QByteArray& PacketBody)
|
||||
{
|
||||
if ((p_Candidate == nullptr) ||
|
||||
(p_Candidate->p_SerialPort == nullptr) ||
|
||||
!p_Candidate->p_SerialPort->isOpen())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const qint64 BytesWritten = p_Candidate->p_SerialPort->write(PacketBody);
|
||||
if (BytesWritten != PacketBody.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
p_Candidate->p_SerialPort->flush();
|
||||
return p_Candidate->p_SerialPort->waitForBytesWritten(100);
|
||||
}
|
||||
|
||||
void Dri_Cdc_EnqueuePacket(
|
||||
Dri_Cdc_Struct_Candidate* p_Candidate,
|
||||
const QByteArray& PacketBody,
|
||||
Com_Enum_ProtocolType Type)
|
||||
{
|
||||
if ((p_Candidate == nullptr) || PacketBody.isEmpty() ||
|
||||
(Type == Com_Enum_ProtocolType_None))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Struct_RawPacket Packet;
|
||||
Packet.IsValid = true;
|
||||
Packet.Source = Com_Enum_RawPacketSource_UsbCdc;
|
||||
Packet.ProtocolType = Type;
|
||||
Packet.ByteArray = PacketBody;
|
||||
Packet.PortName = p_Candidate->PortName;
|
||||
Packet.EndpointId = p_Candidate->EndpointId;
|
||||
p_Candidate->PacketQueue.enqueue(Packet);
|
||||
}
|
||||
|
||||
void Dri_Cdc_BufferIncomingBytes(
|
||||
Dri_Cdc_Struct_Candidate* p_Candidate,
|
||||
const QByteArray& IncomingBytes)
|
||||
{
|
||||
if ((p_Candidate == nullptr) || IncomingBytes.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p_Candidate->PendingBytes.append(IncomingBytes);
|
||||
|
||||
while (true)
|
||||
{
|
||||
QByteArray PacketBody;
|
||||
Com_Enum_ProtocolType Type = Com_Enum_ProtocolType_None;
|
||||
if (!Com_Protocol_TryTakePacket(&p_Candidate->PendingBytes, &PacketBody, &Type))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Dri_Cdc_EnqueuePacket(p_Candidate, PacketBody, Type);
|
||||
}
|
||||
}
|
||||
|
||||
bool Dri_Cdc_DequeuePacket(
|
||||
Dri_Cdc_Struct_Candidate* p_Candidate,
|
||||
Com_Struct_RawPacket* p_Packet,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
if ((p_Candidate == nullptr) || (p_Packet == nullptr) || p_Candidate->PacketQueue.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*p_Packet = p_Candidate->PacketQueue.dequeue();
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus =
|
||||
QStringLiteral("%1 RX %2")
|
||||
.arg(
|
||||
p_Candidate->PortName,
|
||||
QString::fromLatin1(p_Packet->ByteArray.toHex(' ').toUpper()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Dri_Cdc_Close(Dri_Cdc_Struct_Port* p_Port)
|
||||
{
|
||||
Dri_Cdc_DeleteContext(p_Port->p_Context);
|
||||
*p_Port = Dri_Cdc_Struct_Port();
|
||||
}
|
||||
|
||||
bool Dri_Cdc_Init(
|
||||
Dri_Cdc_Struct_Port* p_Port,
|
||||
const Com_Struct_DeviceConfig& DeviceConfig,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
Dri_Cdc_Close(p_Port);
|
||||
|
||||
const QVector<QSerialPortInfo> PortInfoList = QSerialPortInfo::availablePorts().toVector();
|
||||
if (PortInfoList.isEmpty())
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("No USB CDC port is available.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* p_Context = new Dri_Cdc_Struct_Context();
|
||||
QStringList ErrorList;
|
||||
for (const QSerialPortInfo& PortInfo : PortInfoList)
|
||||
{
|
||||
Dri_Cdc_Struct_Candidate Candidate;
|
||||
Candidate.p_SerialPort = new QSerialPort(PortInfo);
|
||||
Candidate.PortName = Dri_Cdc_FormatPortLabel(PortInfo);
|
||||
Candidate.EndpointId = Dri_Cdc_BuildEndpointId(PortInfo);
|
||||
Candidate.SystemLocation = QDir::cleanPath(PortInfo.systemLocation());
|
||||
|
||||
Candidate.p_SerialPort->setBaudRate(QSerialPort::Baud115200);
|
||||
Candidate.p_SerialPort->setDataBits(QSerialPort::Data8);
|
||||
Candidate.p_SerialPort->setParity(QSerialPort::NoParity);
|
||||
Candidate.p_SerialPort->setStopBits(QSerialPort::OneStop);
|
||||
Candidate.p_SerialPort->setFlowControl(QSerialPort::NoFlowControl);
|
||||
|
||||
if (!Candidate.p_SerialPort->open(QIODevice::ReadWrite))
|
||||
{
|
||||
ErrorList.append(
|
||||
QStringLiteral("%1: %2")
|
||||
.arg(PortInfo.portName(), Candidate.p_SerialPort->errorString()));
|
||||
Dri_Cdc_DeleteCandidate(&Candidate);
|
||||
continue;
|
||||
}
|
||||
|
||||
Candidate.p_SerialPort->setDataTerminalReady(true);
|
||||
p_Context->CandidateList.append(Candidate);
|
||||
}
|
||||
|
||||
if (p_Context->CandidateList.isEmpty())
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = ErrorList.isEmpty()
|
||||
? QStringLiteral("USB CDC ports were found, but all opens failed.")
|
||||
: QStringLiteral("USB CDC open failed: %1").arg(ErrorList.join(QStringLiteral(" | ")));
|
||||
}
|
||||
Dri_Cdc_DeleteContext(p_Context);
|
||||
return false;
|
||||
}
|
||||
|
||||
p_Port->p_Context = p_Context;
|
||||
Dri_Cdc_RefreshPortSummary(p_Port, p_Context);
|
||||
Q_UNUSED(DeviceConfig);
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("%1 connected.").arg(p_Port->PortName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dri_Cdc_Read(
|
||||
Dri_Cdc_Struct_Port* p_Port,
|
||||
Com_Struct_RawPacket* p_Packet,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
*p_Packet = Com_Struct_RawPacket();
|
||||
p_Packet->Source = Com_Enum_RawPacketSource_UsbCdc;
|
||||
p_Packet->PortName = p_Port->PortName;
|
||||
|
||||
Dri_Cdc_Struct_Context* p_Context = p_Port->p_Context;
|
||||
if (!p_Port->IsOpened || (p_Context == nullptr) || p_Context->CandidateList.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const int StartIndex =
|
||||
p_Context->ActiveCandidateIndex >= 0 ? p_Context->ActiveCandidateIndex : 0;
|
||||
const int EndIndex =
|
||||
p_Context->ActiveCandidateIndex >= 0
|
||||
? (p_Context->ActiveCandidateIndex + 1)
|
||||
: p_Context->CandidateList.size();
|
||||
|
||||
for (int Index = StartIndex; Index < EndIndex; ++Index)
|
||||
{
|
||||
Dri_Cdc_Struct_Candidate& Candidate = p_Context->CandidateList[Index];
|
||||
if ((Candidate.p_SerialPort == nullptr) || !Candidate.p_SerialPort->isOpen())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Dri_Cdc_IsPortStillPresent(Candidate))
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("%1 disconnected.").arg(Candidate.PortName);
|
||||
}
|
||||
|
||||
Dri_Cdc_DeleteCandidate(&Candidate);
|
||||
if (p_Context->ActiveCandidateIndex == Index)
|
||||
{
|
||||
Dri_Cdc_Close(p_Port);
|
||||
return false;
|
||||
}
|
||||
|
||||
Dri_Cdc_RefreshPortSummary(p_Port, p_Context);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Dri_Cdc_DequeuePacket(&Candidate, p_Packet, p_TextStatus))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const QByteArray IncomingBytes = Candidate.p_SerialPort->readAll();
|
||||
if (IncomingBytes.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Dri_Cdc_BufferIncomingBytes(&Candidate, IncomingBytes);
|
||||
if (Dri_Cdc_DequeuePacket(&Candidate, p_Packet, p_TextStatus))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((p_TextStatus != nullptr) && !Candidate.PendingBytes.isEmpty())
|
||||
{
|
||||
*p_TextStatus =
|
||||
QStringLiteral("%1 has pending protobuf bytes and is waiting for the next CDC chunk.")
|
||||
.arg(Candidate.PortName);
|
||||
}
|
||||
}
|
||||
|
||||
Dri_Cdc_RefreshPortSummary(p_Port, p_Context);
|
||||
if (!p_Port->IsOpened)
|
||||
{
|
||||
Dri_Cdc_Close(p_Port);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Dri_Cdc_LockCandidate(
|
||||
Dri_Cdc_Struct_Port* p_Port,
|
||||
const QString& EndpointId,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
Dri_Cdc_Struct_Context* p_Context = p_Port->p_Context;
|
||||
if (!p_Port->IsOpened || (p_Context == nullptr))
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("USB CDC is not open, so the candidate cannot be locked.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const int ActiveIndex = Dri_Cdc_FindCandidateIndex(p_Context, EndpointId);
|
||||
if (ActiveIndex < 0)
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("The target USB CDC candidate was not found.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((p_Context->CandidateList.at(ActiveIndex).p_SerialPort == nullptr) ||
|
||||
!p_Context->CandidateList.at(ActiveIndex).p_SerialPort->isOpen())
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("The target USB CDC candidate is already closed.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_Context->ActiveCandidateIndex == ActiveIndex)
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus =
|
||||
QStringLiteral("USB CDC already locked to %1.")
|
||||
.arg(p_Context->CandidateList.at(ActiveIndex).PortName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int Index = 0; Index < p_Context->CandidateList.size(); ++Index)
|
||||
{
|
||||
if (Index == ActiveIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Dri_Cdc_DeleteCandidate(&p_Context->CandidateList[Index]);
|
||||
}
|
||||
|
||||
p_Context->ActiveCandidateIndex = ActiveIndex;
|
||||
Dri_Cdc_RefreshPortSummary(p_Port, p_Context);
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("USB CDC locked to %1.").arg(p_Port->PortName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dri_Cdc_DiscardCandidate(
|
||||
Dri_Cdc_Struct_Port* p_Port,
|
||||
const QString& EndpointId,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
Dri_Cdc_Struct_Context* p_Context = p_Port->p_Context;
|
||||
if (!p_Port->IsOpened || (p_Context == nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const int CandidateIndex = Dri_Cdc_FindCandidateIndex(p_Context, EndpointId);
|
||||
if (CandidateIndex < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString PortLabel = p_Context->CandidateList.at(CandidateIndex).PortName;
|
||||
const bool IsActiveCandidate = p_Context->ActiveCandidateIndex == CandidateIndex;
|
||||
Dri_Cdc_DeleteCandidate(&p_Context->CandidateList[CandidateIndex]);
|
||||
|
||||
if (IsActiveCandidate)
|
||||
{
|
||||
Dri_Cdc_Close(p_Port);
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("Discarded the locked USB CDC candidate %1.").arg(PortLabel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Dri_Cdc_RefreshPortSummary(p_Port, p_Context);
|
||||
if (!p_Port->IsOpened)
|
||||
{
|
||||
Dri_Cdc_Close(p_Port);
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("All USB CDC candidates were discarded.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("Discarded USB CDC candidate %1.").arg(PortLabel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dri_Cdc_Write(
|
||||
Dri_Cdc_Struct_Port* p_Port,
|
||||
const QByteArray& PacketBody,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
Dri_Cdc_Struct_Context* p_Context = p_Port->p_Context;
|
||||
if (!p_Port->IsOpened || (p_Context == nullptr) || p_Context->CandidateList.isEmpty())
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("USB CDC is not open. Skip send.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PacketBody.isEmpty())
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("USB CDC packet body is empty.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_Context->ActiveCandidateIndex >= 0)
|
||||
{
|
||||
Dri_Cdc_Struct_Candidate& ActiveCandidate =
|
||||
p_Context->CandidateList[p_Context->ActiveCandidateIndex];
|
||||
if (!Dri_Cdc_WritePacket(&ActiveCandidate, PacketBody))
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus =
|
||||
QStringLiteral("%1 鍐欏叆澶辫触锛?2")
|
||||
.arg(
|
||||
ActiveCandidate.PortName,
|
||||
ActiveCandidate.p_SerialPort == nullptr
|
||||
? QStringLiteral("port already closed")
|
||||
: ActiveCandidate.p_SerialPort->errorString());
|
||||
}
|
||||
|
||||
Dri_Cdc_Close(p_Port);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus =
|
||||
QStringLiteral("%1 TX %2")
|
||||
.arg(
|
||||
ActiveCandidate.PortName,
|
||||
QString::fromLatin1(PacketBody.toHex(' ').toUpper()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int SuccessCount = 0;
|
||||
QStringList SuccessPortList;
|
||||
QStringList ErrorList;
|
||||
for (Dri_Cdc_Struct_Candidate& Candidate : p_Context->CandidateList)
|
||||
{
|
||||
if ((Candidate.p_SerialPort == nullptr) || !Candidate.p_SerialPort->isOpen())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Dri_Cdc_WritePacket(&Candidate, PacketBody))
|
||||
{
|
||||
++SuccessCount;
|
||||
SuccessPortList.append(Candidate.PortName);
|
||||
continue;
|
||||
}
|
||||
|
||||
ErrorList.append(
|
||||
QStringLiteral("%1: %2")
|
||||
.arg(Candidate.PortName, Candidate.p_SerialPort->errorString()));
|
||||
}
|
||||
|
||||
if (SuccessCount > 0)
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus =
|
||||
QStringLiteral("USB CDC 骞挎挱 TX %1锛岀洰鏍囷細%2")
|
||||
.arg(
|
||||
QString::fromLatin1(PacketBody.toHex(' ').toUpper()),
|
||||
SuccessPortList.join(QStringLiteral(", ")));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = ErrorList.isEmpty()
|
||||
? QStringLiteral("USB CDC send failed.")
|
||||
: QStringLiteral("USB CDC 鍙戦€佸け璐ワ細%1").arg(ErrorList.join(QStringLiteral(" | ")));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user