Simplify CDC driver layer
This commit is contained in:
@@ -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();
|
bool Dri_Cdc_ReadBytes(
|
||||||
delete p_Serial;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dri_Cdc_Read(
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
59
docs/host_dri_rebuild.md
Normal 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
|
||||||
Reference in New Issue
Block a user