Simplify CDC driver layer

This commit is contained in:
2026-04-11 09:31:49 +08:00
parent c71c26bf8f
commit 14bfeff8a7
3 changed files with 115 additions and 161 deletions

View File

@@ -1,75 +1,15 @@
#include "DRI/Dri_Cdc.h" #include "DRI/Dri_Cdc.h"
#include "COM/Com_Cdc.h"
#include "COM/Com_CdcDecode.h"
#include "COM/Com_CdcEncode.h"
#include <QtCore/QElapsedTimer>
#include <QtCore/QtGlobal>
#include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo> #include <QtSerialPort/QSerialPortInfo>
namespace
{
bool Dri_Cdc_Func_TryReadFrame(
QSerialPort* p_Serial,
QByteArray* p_ReadBuffer,
int TimeoutMs,
Packet* p_Packet)
{
if ((p_Serial == nullptr) || (p_ReadBuffer == nullptr) || (p_Packet == nullptr))
{
return false;
}
if (Com_Cdc_Func_TryTakeFrame(p_ReadBuffer, p_Packet))
{
return true;
}
QElapsedTimer Timer;
Timer.start();
while (Timer.elapsed() < TimeoutMs)
{
const int RemainingMs = TimeoutMs - static_cast<int>(Timer.elapsed());
const int WaitMs = qMin(20, RemainingMs);
if (WaitMs <= 0)
{
break;
}
if (!p_Serial->waitForReadyRead(WaitMs))
{
continue;
}
const QByteArray ReadBytes = p_Serial->readAll();
if (!ReadBytes.isEmpty())
{
p_ReadBuffer->append(ReadBytes);
}
if (Com_Cdc_Func_TryTakeFrame(p_ReadBuffer, p_Packet))
{
return true;
}
}
return false;
}
} // namespace
QVector<Dri_Cdc_Struct_PortInfo> Dri_Cdc_Enum() QVector<Dri_Cdc_Struct_PortInfo> Dri_Cdc_Enum()
{ {
QVector<Dri_Cdc_Struct_PortInfo> PortList; QVector<Dri_Cdc_Struct_PortInfo> PortList;
const QList<QSerialPortInfo> InfoList = QSerialPortInfo::availablePorts(); const QList<QSerialPortInfo> InfoList = QSerialPortInfo::availablePorts();
for (int Index = 0; Index < InfoList.size(); ++Index) for (const QSerialPortInfo& Info : InfoList)
{ {
const QSerialPortInfo& Info = InfoList.at(Index);
Dri_Cdc_Struct_PortInfo PortInfo; Dri_Cdc_Struct_PortInfo PortInfo;
PortInfo.PortName = Info.portName(); PortInfo.PortName = Info.portName();
PortInfo.Description = Info.description(); PortInfo.Description = Info.description();
@@ -80,41 +20,40 @@ QVector<Dri_Cdc_Struct_PortInfo> Dri_Cdc_Enum()
return PortList; return PortList;
} }
void Dri_Cdc_Deinit(Dri_Cdc_Struct_Port* p_Port) void Dri_Cdc_Close(Dri_Cdc_Struct_Port* p_Port)
{ {
if (p_Port == nullptr)
{
return;
}
if (p_Port->p_Port != nullptr) if (p_Port->p_Port != nullptr)
{ {
if (p_Port->p_Port->isOpen()) if (p_Port->p_Port->isOpen())
{ {
p_Port->p_Port->close(); p_Port->p_Port->close();
} }
delete p_Port->p_Port; delete p_Port->p_Port;
} }
*p_Port = Dri_Cdc_Struct_Port(); *p_Port = Dri_Cdc_Struct_Port();
} }
bool Dri_Cdc_Init( bool Dri_Cdc_Open(
Dri_Cdc_Struct_Port* p_Port, Dri_Cdc_Struct_Port* p_Port,
const Dri_Cdc_Struct_InitConfig& Config) const QString& PortName,
const Dri_Cdc_Struct_OpenConfig& Config)
{ {
Dri_Cdc_Deinit(p_Port); if ((p_Port == nullptr) || PortName.trimmed().isEmpty())
const QVector<Dri_Cdc_Struct_PortInfo> PortList = Dri_Cdc_Enum();
if (PortList.isEmpty())
{ {
return false; return false;
} }
Packet_HelloReq HelloReq; Dri_Cdc_Close(p_Port);
const QByteArray HelloReqFrame = Com_Cdc_Func_BuildHelloReq(HelloReq);
for (int Index = 0; Index < PortList.size(); ++Index) QSerialPort* const p_Serial = new QSerialPort();
{ p_Serial->setPortName(PortName);
const Dri_Cdc_Struct_PortInfo& PortInfo = PortList.at(Index);
QSerialPort* p_Serial = new QSerialPort();
p_Serial->setPortName(PortInfo.PortName);
p_Serial->setBaudRate(Config.BaudRate); p_Serial->setBaudRate(Config.BaudRate);
p_Serial->setDataBits(QSerialPort::Data8); p_Serial->setDataBits(QSerialPort::Data8);
p_Serial->setParity(QSerialPort::NoParity); p_Serial->setParity(QSerialPort::NoParity);
@@ -124,86 +63,46 @@ bool Dri_Cdc_Init(
if (!p_Serial->open(QIODevice::ReadWrite)) if (!p_Serial->open(QIODevice::ReadWrite))
{ {
delete p_Serial; delete p_Serial;
continue; return false;
} }
p_Serial->readAll();
if (p_Serial->write(HelloReqFrame) != HelloReqFrame.size())
{
p_Serial->close();
delete p_Serial;
continue;
}
if (!p_Serial->waitForBytesWritten(Config.HandshakeTimeoutMs))
{
p_Serial->close();
delete p_Serial;
continue;
}
QByteArray HandshakeBuffer;
QElapsedTimer Timer;
Timer.start();
while (Timer.elapsed() < Config.HandshakeTimeoutMs)
{
Packet PacketData;
const int RemainingMs =
Config.HandshakeTimeoutMs - static_cast<int>(Timer.elapsed());
if (!Dri_Cdc_Func_TryReadFrame(
p_Serial,
&HandshakeBuffer,
qMin(20, RemainingMs),
&PacketData))
{
continue;
}
if (PacketData.type == Com_Type_HelloRsp)
{
p_Port->p_Port = p_Serial; p_Port->p_Port = p_Serial;
p_Port->IsOpened = true; p_Port->IsOpened = true;
p_Port->PortName = PortInfo.PortName; p_Port->PortName = PortName;
p_Port->ReadBuffer = HandshakeBuffer;
return true; return true;
}
}
p_Serial->close();
delete p_Serial;
}
return false;
} }
bool Dri_Cdc_Read( bool Dri_Cdc_ReadBytes(
Dri_Cdc_Struct_Port* p_Port, Dri_Cdc_Struct_Port* p_Port,
QByteArray& ByteArray) QByteArray* p_ByteArray,
int TimeoutMs)
{ {
ByteArray.clear(); if (p_ByteArray != nullptr)
{
p_ByteArray->clear();
}
if (!p_Port->IsOpened || (p_Port->p_Port == nullptr)) if ((p_Port == nullptr) || (p_ByteArray == nullptr) ||
!p_Port->IsOpened || (p_Port->p_Port == nullptr))
{ {
return false; return false;
} }
Packet PacketData; if (TimeoutMs > 0)
if (Com_Cdc_Func_TryTakeFrame(&p_Port->ReadBuffer, &PacketData) ||
Dri_Cdc_Func_TryReadFrame(p_Port->p_Port, &p_Port->ReadBuffer, 50, &PacketData))
{ {
ByteArray = Com_Cdc_Func_BuildFrame(PacketData); p_Port->p_Port->waitForReadyRead(TimeoutMs);
return !ByteArray.isEmpty();
} }
return false; *p_ByteArray = p_Port->p_Port->readAll();
return !p_ByteArray->isEmpty();
} }
bool Dri_Cdc_Write( bool Dri_Cdc_WriteBytes(
Dri_Cdc_Struct_Port* p_Port, Dri_Cdc_Struct_Port* p_Port,
const QByteArray& ByteArray) const QByteArray& ByteArray,
int TimeoutMs)
{ {
if (!p_Port->IsOpened || (p_Port->p_Port == nullptr)) if ((p_Port == nullptr) || !p_Port->IsOpened || (p_Port->p_Port == nullptr))
{ {
return false; return false;
} }
@@ -218,10 +117,5 @@ bool Dri_Cdc_Write(
return false; return false;
} }
if (!p_Port->p_Port->waitForBytesWritten(200)) return p_Port->p_Port->waitForBytesWritten(TimeoutMs);
{
return false;
}
return true;
} }

View File

@@ -13,10 +13,9 @@ struct Dri_Cdc_Struct_PortInfo
QString Manufacturer; QString Manufacturer;
}; };
struct Dri_Cdc_Struct_InitConfig struct Dri_Cdc_Struct_OpenConfig
{ {
qint32 BaudRate = 115200; qint32 BaudRate = 115200;
int HandshakeTimeoutMs = 200;
}; };
struct Dri_Cdc_Struct_Port struct Dri_Cdc_Struct_Port
@@ -24,17 +23,19 @@ struct Dri_Cdc_Struct_Port
QSerialPort* p_Port = nullptr; QSerialPort* p_Port = nullptr;
bool IsOpened = false; bool IsOpened = false;
QString PortName; QString PortName;
QByteArray ReadBuffer;
}; };
QVector<Dri_Cdc_Struct_PortInfo> Dri_Cdc_Enum(); QVector<Dri_Cdc_Struct_PortInfo> Dri_Cdc_Enum();
void Dri_Cdc_Deinit(Dri_Cdc_Struct_Port* p_Port); void Dri_Cdc_Close(Dri_Cdc_Struct_Port* p_Port);
bool Dri_Cdc_Init( bool Dri_Cdc_Open(
Dri_Cdc_Struct_Port* p_Port, Dri_Cdc_Struct_Port* p_Port,
const Dri_Cdc_Struct_InitConfig& Config); const QString& PortName,
bool Dri_Cdc_Read( const Dri_Cdc_Struct_OpenConfig& Config);
bool Dri_Cdc_ReadBytes(
Dri_Cdc_Struct_Port* p_Port, Dri_Cdc_Struct_Port* p_Port,
QByteArray& ByteArray); QByteArray* p_ByteArray,
bool Dri_Cdc_Write( int TimeoutMs);
bool Dri_Cdc_WriteBytes(
Dri_Cdc_Struct_Port* p_Port, Dri_Cdc_Struct_Port* p_Port,
const QByteArray& ByteArray); const QByteArray& ByteArray,
int TimeoutMs);

59
docs/host_dri_rebuild.md Normal file
View File

@@ -0,0 +1,59 @@
# Host DRI Rebuild
## Goal
Keep the device runtime layer small and transport-only.
The DRI layer should:
- enumerate endpoints
- open and close connections
- read raw bytes
- write raw bytes
The DRI layer should not:
- parse frames
- manage protocol state
- decide handshake success
## Completed Nodes
### Node 1: GATT placeholder
Files:
- `KeyBorad/KeyBorad/DRI/GATT/Dri_Gatt.h`
- `KeyBorad/KeyBorad/DRI/GATT/Dri_Gatt.cpp`
Design notes:
- reserves the BLE transport position early
- keeps the implementation small for now
- avoids mixing GATT transport with logic concerns
### Node 2: CDC transport cleanup
Files updated in this step:
- `KeyBorad/KeyBorad/DRI/Dri_Cdc.h`
- `KeyBorad/KeyBorad/DRI/Dri_Cdc.cpp`
Design notes:
- remove frame parsing from the driver
- remove handshake ownership from the driver
- keep only enumerate/open/close/read-bytes/write-bytes
Implemented behavior:
- list ports with `Dri_Cdc_Enum()`
- open one port with `Dri_Cdc_Open()`
- close one port with `Dri_Cdc_Close()`
- read raw bytes with timeout
- write raw bytes with timeout
## Next DRI nodes
- implement real GATT discovery and notify/write path
- provide one simple connection summary for logic layer