This commit is contained in:
flower_linux
2026-03-12 14:56:53 +08:00
parent 22ee28f33b
commit 9a2224f185
62 changed files with 1597 additions and 505 deletions

View File

@@ -0,0 +1,67 @@
#pragma once
#include <array>
#include <QString>
namespace softbus::hardware::drivers::serial::capabilities
{
struct SerialDefaults
{
int baudRate = 115200;
int dataBits = 8;
const char* parity = "none";
int stopBits = 1;
const char* flowControl = "none";
};
inline constexpr SerialDefaults kDefaults{};
inline constexpr std::array<int, 5> kBaudRates{9600, 19200, 38400, 57600, 115200};
inline constexpr std::array<int, 4> kDataBits{5, 6, 7, 8};
inline constexpr std::array<const char*, 3> kParity{"none", "even", "odd"};
inline constexpr std::array<int, 2> kStopBits{1, 2};
inline constexpr std::array<const char*, 3> kFlowControl{"none", "hardware", "software"};
inline bool isValidBaud(int v)
{
for (int b : kBaudRates) {
if (b == v) return true;
}
return false;
}
inline bool isValidDataBits(int v)
{
for (int b : kDataBits) {
if (b == v) return true;
}
return false;
}
inline bool isValidParity(const QString& s)
{
for (const char* p : kParity) {
if (s == QLatin1String(p)) return true;
}
return false;
}
inline bool isValidStopBits(int v)
{
for (int b : kStopBits) {
if (b == v) return true;
}
return false;
}
inline bool isValidFlowControl(const QString& s)
{
for (const char* f : kFlowControl) {
if (s == QLatin1String(f)) return true;
}
return false;
}
} // namespace softbus::hardware::drivers::serial::capabilities

View File

@@ -0,0 +1,138 @@
#include "hardware/drivers/serial/SerialQtDriver.h"
#include <QByteArray>
#include "utils/logs/logging.h"
namespace softbus::hardware::drivers::serial
{
SerialQtDriver::SerialQtDriver(QObject* parent)
: QObject(parent),
m_port(this)
{
connect(&m_port, &QSerialPort::readyRead, this, &SerialQtDriver::handleReadyRead);
connect(&m_port, &QSerialPort::errorOccurred, this, &SerialQtDriver::handleError);
}
SerialQtDriver::~SerialQtDriver()
{
Close();
}
bool SerialQtDriver::Open(const std::string& endpoint)
{
if (m_port.isOpen()) {
return true;
}
m_port.setPortName(QString::fromStdString(endpoint));
if (!m_port.open(QIODevice::ReadWrite)) {
if (m_errorCallback) {
m_errorCallback(m_port.errorString().toStdString());
}
LOG_WARNING() << "SerialQtDriver: failed to open port" << m_port.portName() << ":" << m_port.errorString();
return false;
}
LOG_DEBUG() << "SerialQtDriver: opened port" << m_port.portName();
return true;
}
void SerialQtDriver::Close()
{
if (m_port.isOpen()) {
const QString name = m_port.portName();
m_port.close();
LOG_DEBUG() << "SerialQtDriver: closed port" << name;
}
}
bool SerialQtDriver::Write(const std::vector<std::uint8_t>& data)
{
if (!m_port.isOpen()) {
return false;
}
const QByteArray bytes(reinterpret_cast<const char*>(data.data()), static_cast<int>(data.size()));
const qint64 written = m_port.write(bytes);
if (written != bytes.size()) {
LOG_WARNING() << "SerialQtDriver: partial write on" << m_port.portName() << "written" << written << "of"
<< bytes.size();
return false;
}
return true;
}
void SerialQtDriver::SetReadCallback(ReadCallback cb)
{
m_readCallback = std::move(cb);
}
void SerialQtDriver::SetErrorCallback(ErrorCallback cb)
{
m_errorCallback = std::move(cb);
}
void SerialQtDriver::SetBaudRate(QSerialPort::BaudRate baud)
{
m_port.setBaudRate(baud);
}
void SerialQtDriver::SetDataBits(QSerialPort::DataBits bits)
{
m_port.setDataBits(bits);
}
void SerialQtDriver::SetParity(QSerialPort::Parity parity)
{
m_port.setParity(parity);
}
void SerialQtDriver::SetStopBits(QSerialPort::StopBits stopBits)
{
m_port.setStopBits(stopBits);
}
void SerialQtDriver::SetFlowControl(QSerialPort::FlowControl flow)
{
m_port.setFlowControl(flow);
}
void SerialQtDriver::handleReadyRead()
{
if (!m_readCallback) {
const QByteArray data = m_port.readAll();
LOG_DEBUG() << "SerialQtDriver: dropped" << data.size() << "bytes on" << m_port.portName()
<< "because no read callback is set";
return;
}
const QByteArray data = m_port.readAll();
if (data.isEmpty()) {
return;
}
std::vector<std::uint8_t> buffer(reinterpret_cast<const std::uint8_t*>(data.constData()),
reinterpret_cast<const std::uint8_t*>(data.constData()) + data.size());
m_readCallback(buffer);
}
void SerialQtDriver::handleError(QSerialPort::SerialPortError error)
{
if (error == QSerialPort::NoError) {
return;
}
const QString msg =
QStringLiteral("SerialQtDriver error on %1: %2").arg(m_port.portName(), m_port.errorString());
LOG_WARNING() << msg;
if (m_errorCallback) {
m_errorCallback(msg.toStdString());
}
}
} // namespace softbus::hardware::drivers::serial

View File

@@ -0,0 +1,85 @@
#pragma once
#include <QObject>
#include <QSerialPort>
#include <QString>
#include "hardware/interfaces/IStreamDriver.h"
// 这里的串口的唯一标识是串口的端口名,如 /dev/ttyUSB0, can0, tcp://...
// 串口的endpoint是串口的端口名如 /dev/ttyUSB0, can0, tcp://...
// 使用说明:
// 1. 创建一个SerialQtDriver对象
// 2. 调用Open方法打开串口
// 3. 调用Write方法写数据
// 4. 调用SetReadCallback方法设置读回调
// 5. 调用SetErrorCallback方法设置错误回调
// 6. 调用Close方法关闭串口
// 7. 调用SetBaudRate方法设置波特率
// 8. 调用SetDataBits方法设置数据位
// 9. 调用SetParity方法设置校验位
// 10. 调用SetStopBits方法设置停止位
// 11. 调用SetFlowControl方法设置流控制
// eg:
// SerialQtDriver driver;
// driver.Open("/dev/ttyUSB0");
// driver.Write({0x01, 0x02, 0x03});
// driver.SetReadCallback([](const std::vector<std::uint8_t>& data) {
// std::cout << "read data: " << data << std::endl;
// });
// driver.SetErrorCallback([](const std::string& error) {
// std::cout << "error: " << error << std::endl;
// });
// driver.Close();
// 12. 调用SetBaudRate方法设置波特率
// 13. 调用SetDataBits方法设置数据位
// 14. 调用SetParity方法设置校验位
// 15. 调用SetStopBits方法设置停止位
// 16. 调用SetFlowControl方法设置流控制
// eg:
// driver.SetBaudRate(QSerialPort::Baud115200);
// driver.SetDataBits(QSerialPort::Data8);
// driver.SetParity(QSerialPort::NoParity);
// driver.SetStopBits(QSerialPort::OneStop);
// driver.SetFlowControl(QSerialPort::NoFlowControl);
// driver.Close();
namespace softbus::hardware::drivers::serial
{
// 基于 Qt 的串口驱动实现:只负责串口 open/read/write不包含设备注册、数据库或协议逻辑
class SerialQtDriver : public QObject, public softbus::hardware::interfaces::IStreamDriver
{
Q_OBJECT
public:
explicit SerialQtDriver(QObject* parent = nullptr);
~SerialQtDriver() override;
bool Open(const std::string& endpoint) override;
void Close() override;
bool Write(const std::vector<std::uint8_t>& data) override;
void SetReadCallback(ReadCallback cb) override;
void SetErrorCallback(ErrorCallback cb) override;
// 允许上层配置串口参数(最小集合)
void SetBaudRate(QSerialPort::BaudRate baud);
void SetDataBits(QSerialPort::DataBits bits);
void SetParity(QSerialPort::Parity parity);
void SetStopBits(QSerialPort::StopBits stopBits);
void SetFlowControl(QSerialPort::FlowControl flow);
private slots:
void handleReadyRead();
void handleError(QSerialPort::SerialPortError error);
private:
QSerialPort m_port;
ReadCallback m_readCallback;
ErrorCallback m_errorCallback;
};
} // namespace softbus::hardware::drivers::serial

View File

@@ -0,0 +1,37 @@
#pragma once
#ifdef __cplusplus
#include <functional>
#include <string>
namespace softbus::hardware::interfaces
{
struct DiscoveredDevice
{
std::string id; // 稳定 ID如序列号、路径
std::string endpoint; // 打开所需的 endpoint如 /dev/ttyUSB0, can0, tcp://...
std::string type; // 设备类型serial / can / ethernet / usb 等
};
// 设备发现 / 监控接口:负责发现插拔事件,不负责创建设备或驱动实例
class IDeviceWatcher
{
public:
using DeviceAttachedCallback = std::function<void(const DiscoveredDevice&)>;
using DeviceDetachedCallback = std::function<void(const DiscoveredDevice&)>;
virtual ~IDeviceWatcher() = default;
virtual bool Start() = 0;
virtual void Stop() = 0;
virtual void SetDeviceAttachedCallback(DeviceAttachedCallback cb) = 0;
virtual void SetDeviceDetachedCallback(DeviceDetachedCallback cb) = 0;
};
} // namespace softbus::hardware::interfaces
#endif // __cplusplus

View File

@@ -0,0 +1,41 @@
#pragma once
#ifdef __cplusplus
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
namespace softbus::hardware::interfaces
{
struct Frame
{
std::vector<std::uint8_t> payload;
std::uint32_t id{0}; // 如 CAN ID
std::uint64_t timestamp{0};
};
// 面向帧设备(如 CAN 总线)的统一驱动接口
class IFrameDriver
{
public:
using FrameCallback = std::function<void(const Frame&)>;
using ErrorCallback = std::function<void(const std::string& message)>;
virtual ~IFrameDriver() = default;
virtual bool Open(const std::string& endpoint) = 0;
virtual void Close() = 0;
virtual bool WriteFrame(const Frame& frame) = 0;
virtual void SetFrameCallback(FrameCallback cb) = 0;
virtual void SetErrorCallback(ErrorCallback cb) = 0;
};
} // namespace softbus::hardware::interfaces
#endif // __cplusplus

View File

@@ -0,0 +1,34 @@
#pragma once
#ifdef __cplusplus
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
namespace softbus::hardware::interfaces
{
// 面向字节流设备的统一驱动接口:串口 / TCP / UDP 等
class IStreamDriver
{
public:
using ReadCallback = std::function<void(const std::vector<std::uint8_t>&)>;
using ErrorCallback = std::function<void(const std::string& message)>;
virtual ~IStreamDriver() = default;
virtual bool Open(const std::string& endpoint) = 0;
virtual void Close() = 0;
virtual bool Write(const std::vector<std::uint8_t>& data) = 0;
virtual void SetReadCallback(ReadCallback cb) = 0;
virtual void SetErrorCallback(ErrorCallback cb) = 0;
};
} // namespace softbus::hardware::interfaces
#endif // __cplusplus