部件驱动接口模型设计

1. 概述

部件驱动接口模型是Component Drivers项目的核心架构设计,采用"配置驱动+代码生成"的设计理念,通过DDS(Device Description Standard)配置文件自动生成接口层代码和DBus设备树接口,实现了接口定义与实现的彻底分离,极大提升了开发效率和系统可扩展性。

1.1 核心特性

  • DDS配置驱动: 通过标准化的JSON配置文件定义设备接口和对象模型
  • 自动代码生成: 从DDS配置自动生成C++接口头文件和反射代码
  • 接口与实现分离: 生成的接口代码与厂商实现完全解耦
  • 多层抽象: 支持接口层、设备对象层、驱动实现层的清晰分层
  • 反射机制: 通过MC_REFLECT实现运行时属性访问和序列化

1.2 技术优势

优势说明价值
开发效率提升接口代码自动生成,无需手写减少70%以上的接口代码编写工作
标准化接口统一的接口定义规范确保多厂商设备接口一致性
易于扩展新增接口只需修改DDS配置快速支持新设备类型
跨进程访问自动生成DBus接口支持进程间设备管理
类型安全编译期类型检查减少运行时错误
维护性强接口定义集中管理接口变更影响可控

2. 设计目标

  • 提供统一的设备接口定义和管理机制
  • 实现接口定义与实现的完全分离
  • 支持从配置文件自动生成接口代码
  • 支持多厂商、多型号设备的统一管理
  • 提供基于反射的动态属性访问能力
  • 实现设备对象的层次化组织和管理

3. 整体架构

3.1 三层架构模型

3.2 数据流向

4. DDS配置机制

4.1 DDS配置文件结构

DDS (Device Description Standard) 配置文件采用JSON格式,定义了设备的完整接口模型:

json
{
    "Schema": "dds-v1",
    "Type": "Component",
    "DeviceCategory": "PCIeNicCard",
    "ID": "N/A",
    "Objects": {
        "PCIeNicCard": {
            "Path": "/bmc/dev/Systems/:SystemId/PCIeNicCard/:Id",
            "Interfaces": [
                "bmc.dev.PCIeDevice",
                "bmc.dev.PCIeDevice.PCIeFunction",
                "bmc.dev.PCIeDevice.Status",
                "bmc.dev.PCIeDevice.Oem",
                "bmc.dev.PCIeCard",
                "bmc.dev.PCIeCard.Oem",
                "bmc.dev.PCIeCard.Metrics",
                "bmc.dev.Board",
                "bmc.dev.NetworkAdapter",
                "bmc.dev.PCIeDevice.Bandwidth",
                "bmc.dev.Cooling",
                "bmc.dev.NetworkAdapter.FaultStatus",
                "bmc.dev.NetworkAdapter.LogCollection",
                "bmc.dev.NetworkAdapter.Oem"
            ]
        },
        "NicPort": {
            "Path": ":Parent/NicPort/:Id",
            "Interfaces": [
                "bmc.dev.NetworkPort",
                "bmc.dev.NetworkPort.LinkInfo",
                "bmc.dev.NetworkPort.DataCenterBridging",
                "bmc.dev.NetworkPort.LLDPReceive",
                "bmc.dev.NetworkPort.Metrics"
            ]
        },
        "OpticalTransceiver": {
            "Path": ":Parent/OpticalTransceiver",
            "Interfaces": [
                "bmc.dev.OpticalModule",
                "bmc.dev.OpticalModule.Status",
                "bmc.dev.OpticalModule.TemperatureCelsius",
                "bmc.dev.OpticalModule.Voltage",
                "bmc.dev.OpticalModule.Power",
                "bmc.dev.OpticalModule.Current",
                "bmc.dev.OpticalModule.Diagnose"
            ]
        }
    }
}

4.2 DDS配置元素说明

字段说明示例作用
SchemaDDS版本标识"dds-v1"定义配置文件格式版本
Type设备类型"Component"标识设备大类
DeviceCategory设备类别"PCIeNicCard"具体设备类别名称
Objects设备对象集合{...}定义所有设备对象及其接口
Path对象路径模式"/bmc/dev/..."设备在系统中的路径规则
Interfaces接口列表[...]对象支持的所有接口

4.3 接口定义配置

每个接口通过独立的JSON文件定义其属性和方法:

json
{
    "name": "PCIeDevice",
    "namespace": "bmc.dev",
    "description": "PCIe设备基础接口",
    "properties": [
        {
            "name": "DeviceName",
            "type": "string",
            "description": "设备资源名称",
            "writable": true
        },
        {
            "name": "Location",
            "type": "string",
            "description": "当前PCIe的物理位置",
            "writable": true
        },
        {
            "name": "Slot",
            "type": "uint8_t",
            "description": "PCIe设备的物理槽位号",
            "writable": true
        },
        {
            "name": "SocketId",
            "type": "uint8_t",
            "description": "PCIe设备所属CPU ID",
            "writable": true
        },
        {
            "name": "Bus",
            "type": "uint8_t",
            "description": "PCIe Root Port的总线号",
            "writable": true
        },
        {
            "name": "Device",
            "type": "uint8_t",
            "description": "PCIe Root Port的设备号",
            "writable": true
        },
        {
            "name": "Function",
            "type": "uint8_t",
            "description": "PCIe Root Port的功能号",
            "writable": true
        }
    ],
    "methods": [
        {
            "name": "SetRootBDF",
            "description": "设置根设备BDF",
            "returnType": "bool",
            "parameters": [
                {"name": "bus", "type": "uint8_t"},
                {"name": "device", "type": "uint8_t"},
                {"name": "function", "type": "uint8_t"}
            ]
        }
    ]
}

4.4 路径模式规则

路径模式支持以下特殊语法:

语法说明示例
:参数名路径参数占位符/Systems/:SystemId/PCIeNicCard/:Id
${参数名}属性引用${DeviceName}
:Parent父对象路径引用:Parent/NicPort/:Id

5. 接口代码自动生成

5.1 代码生成流程

5.2 生成的C++接口类

自动生成的C++接口类位于dev::gen命名空间:

cpp
// 自动生成文件: gen/include/device_tree/interface/PCIeDevice.h
#ifndef GEN_PCIe_DEVICE_INTERFACE_H
#define GEN_PCIe_DEVICE_INTERFACE_H

#include <device_tree/base.h>

namespace dev::gen {

/**
 * @brief PCIe设备基础接口
 *
 * 此接口由DDS配置自动生成,定义了PCIe设备的标准属性和方法。
 * 厂商实现应继承此接口并实现具体逻辑。
 */
class MC_API PCIeDevice : public mc::engine::interface<PCIeDevice> {
public:
    MC_INTERFACE("bmc.dev.PCIeDevice")

    property<std::string> DeviceName;        ///< 设备资源名称
    property<std::string> Location;          ///< 当前PCIe的物理位置
    property<uint8_t>     Slot;              ///< PCIe设备的物理槽位号
    property<uint8_t>     SocketId;          ///< PCIe设备所属CPU ID
    property<uint8_t>     SystemId;          ///< PCIe设备所属系统ID
    property<uint8_t>     Bus;               ///< PCIe Root Port的总线号
    property<uint8_t>     Device;            ///< PCIe Root Port的设备号
    property<uint8_t>     Function;          ///< PCIe Root Port的功能号
    property<std::string> SlotType;          ///< PCIe设备所在槽位的类型
    property<std::string> DeviceType;        ///< PCIe设备类型
    property<std::string> Model;             ///< PCIe标卡产品型号
    property<std::string> Manufacturer;      ///< 厂商
    property<std::string> PartNumber;        ///< 部件编码
    property<std::string> SerialNumber;      ///< 序列号
    property<std::string> FirmwareVersion;   ///< PCIe标卡的固件版本号
    property<uint8_t>     MaxPCIeType;       ///< 最大支持的PCIe接口规格
    property<uint8_t>     PCIeType;          ///< 实际的PCIe接口规格
    property<uint8_t>     MaxLanes;          ///< 支持的最大通道数
    property<uint8_t>     LaneInUse;         ///< 实际使用的通道数

    virtual bool SetRootBDF(uint8_t bus, uint8_t device, uint8_t function) = 0;
};
} // namespace dev::gen

#endif // GEN_PCIe_DEVICE_INTERFACE_H

说明:以上内容与 gen/include/device_tree/interface/PCIeDevice.h 完全一致。接口基类为 mc::engine::interface<PCIeDevice>(单模板参数),命名空间为 dev::gen,头文件包含 device_tree/base.h

5.3 接口反射注册

运行时属性访问通过反射机制实现。与生成的接口头文件不同,反射注册是在厂商接口实现(.cpp)中通过 MC_REFLECT(dev::Xxx) 宏完成,并不单独生成 _reflect.h 文件。示例(与库中 drivers/pcie_nic_card/hisi/interface/pcie_device.cpp 一致):

cpp
// 厂商接口实现文件: drivers/pcie_nic_card/hisi/interface/pcie_device.cpp (节选)
namespace dev {

// 反射注册:将实现类的属性与 D-Bus 接口关联
MC_REFLECT(dev::PCIeDevice)

} // namespace dev

反射注册在接口实现源文件中定义,其他厂商接口(PCIeCardNetworkAdapterCoolingBoardFru 等)均在各自的 .cpp 中以相同方式调用 MC_REFLECT(dev::Xxx) 完成注册。

5.4 生成文件组织结构

gen/
└── include/
    └── device_tree/
        └── interface/                # 生成的接口类(全部为 dev::gen 命名空间)
            ├── PCIeDevice.h          # PCIe设备接口
            ├── NetworkAdapter.h      # 网络适配器接口
            ├── NetworkPort.h         # 网络端口接口
            └── ...                   # 其他接口

6. 接口实现机制

6.1 厂商接口实现

厂商通过继承生成的接口基类实现具体逻辑:

cpp
// 厂商实现文件: drivers/pcie_nic_card/hisi/interface/pcie_device.h
#ifndef PCIE_DEVICE_INTERFACE_H
#define PCIE_DEVICE_INTERFACE_H

#include <mc/engine/service.h>
#include <mc/timer.h>

#include <device_tree/interface/PCIeDevice.h>
#include <ncsi_over_mctp/ncsi_over_mctp_huawei.h>
#include <smbus/smbus.h>

namespace dev {

using smbus_obj_ptr = mc::shared_ptr<smbus>;

/**
 * @brief PCIe设备接口的海思厂商实现
 *
 * 继承 auto-generated 的 dev::gen::PCIeDevice 基类。
 * 厂商实现类需以 mc::engine::interface<实现类, 基类> 双模板参数形式继承,
 * 使接口同时具备厂商实现与生成基类的双重类型信息。
 */
class MC_API PCIeDevice : public mc::engine::interface<PCIeDevice, gen::PCIeDevice> {
public:
    PCIeDevice()  = default;
    ~PCIeDevice() = default;

public:
    // 实现基类虚方法
    bool SetRootBDF(uint8_t bus, uint8_t device, uint8_t function) override;

public:
    void set_smbus_obj(smbus_obj_ptr smbus_obj);
    bool set_slot_by_smbus(uint8_t slot);

private:
    smbus_obj_ptr m_smbus_obj;

public:
    void replace_dynamic_property(mc::mutable_dict& object, const mc::dict& connector);
};

} // namespace dev

#endif // PCIE_DEVICE_INTERFACE_H

实现文件(节选):

cpp
// 厂商实现文件: drivers/pcie_nic_card/hisi/interface/pcie_device.cpp (节选)
namespace dev {

bool PCIeDevice::SetRootBDF(uint8_t bus, uint8_t device, uint8_t function)
{
    if (bus == 0 && device == 0 && function == 0) {
        std::cerr << "Error: Invalid BDF values" << std::endl;
        return false;
    }
    Bus      = bus;
    Device   = device;
    Function = function;

    return true;
}

void PCIeDevice::set_smbus_obj(smbus_obj_ptr smbus_obj)
{
    m_smbus_obj = smbus_obj;
}

// 反射注册:单参数形式,在 .cpp 中完成
MC_REFLECT(dev::PCIeDevice)

} // namespace dev

说明:

  1. 厂商实现类用 双模板参数 mc::engine::interface<PCIeDevice, gen::PCIeDevice> 继承,而非直接 : public gen::PCIeDevice
  2. 反射注册为 单参数 MC_REFLECT(dev::PCIeDevice),在 .cpp 中完成,无 3 参数形式。
  3. 当前 dev::PCIeDevice 不包含 NCSI 定时任务成员,也不声明 pcie_device_bdf_changed 信号;该信号声明于 dev::PCIeDevice_PCIeFunction(见 interface/pcie_device/pcie_function.h)。NCSI 更新任务由具体网卡设备对象(如 hi182x_card)及各业务接口发起。

6.2 设备对象组合接口

设备对象通过组合多个接口实现复杂功能:

cpp
// 设备对象文件: drivers/pcie_nic_card/hisi/hi182x/hi182x_card.h
#ifndef HI182X_CARD_H
#define HI182X_CARD_H

#include <imu/imu.h>
#include <mc/engine.h>
#include <mc/timer.h>
#include <mctp/mctp.h>
#include <ncsi_over_mctp/ncsi_over_mctp_huawei.h>
#include <smbus/smbus.h>

#include "hi182x_port.h"
#include "interface/board.h"
#include "interface/cooling.h"
#include "interface/fru.h"
#include "interface/network_adapter.h"
// ... 其余接口头文件

namespace dev {
using ncsi_over_mctp_hw_ptr = std::shared_ptr<ncsi_over_mctp_huawei>;
using smbus_obj_ptr         = mc::shared_ptr<smbus>;
using imu_ptr               = std::shared_ptr<imu>;

class hi182x_card : public mc::engine::object<hi182x_card> {
public:
    // MC_OBJECT宏定义:类名 / 设备类型名 / 路径模式 / 支持的接口列表
    MC_OBJECT(
        hi182x_card, "PCIeNicCard", "/bmc/dev/Systems/1/PCIeNicCard/${object_name}",
        (PCIeDevice)(PCIeDevice_PCIeFunction)(PCIeDevice_Oem)(PCIeDevice_Status)(PCIeCard)(PCIeCard_Oem)(PCIeCard_Metrics)(NetworkAdapter)(NetworkAdapter_FaultStatus)(Cooling)(NetworkAdapter_Oem)(Board)(PCIeDevice_Bandwidth)(NetworkAdapter_LogCollection)(Fru))

    hi182x_card();
    ~hi182x_card();
    // 生命周期方法(非虚,不带 override)
    bool start();
    bool stop();
    bool init(mc::mutable_dict& csr_object, const mc::dict& connector);
    void init_network_ports();
    void replace_dynamic_property(mc::mutable_dict& object, const mc::dict& connector);

    // === 接口实例(组合模式) ===
    NetworkAdapter_Oem           m_network_adapter_oem;
    PCIeDevice                   m_pcie_device;
    PCIeDevice_PCIeFunction      m_pcie_device_pcie_function;
    PCIeDevice_Oem               m_pcie_device_oem;
    PCIeDevice_Status            m_pcie_device_status;
    PCIeCard                     m_pcie_card;
    PCIeCard_Oem                 m_pcie_card_oem;
    PCIeCard_Metrics             m_pcie_card_metrics;
    Cooling                      m_cooling;
    NetworkAdapter               m_network_adapter;
    NetworkAdapter_FaultStatus   m_network_adapter_fault_status;
    Board                        m_board;
    PCIeDevice_Bandwidth         m_pcie_device_bandwidth;
    NetworkAdapter_LogCollection m_network_adapter_log_collection;
    Fru                          m_fru;
    uint8_t                      m_system_id;

private:
    std::vector<hi182x_port*> m_network_ports;

    // === 协议管理 ===
    bool                  start_ncsi_protocol();
    void                  stop_ncsi_update_task();
    bool                  start_smbus_protocol();
    bool                  init_smbus_protocol();
    bool                  init_imu_protocol();
    bool                  start_protocol();
    ref_chip_ptr          m_ref_chip;
    smbus_obj_ptr         m_smbus_obj;
    imu_ptr               m_imu_obj;
    ncsi_over_mctp_hw_ptr m_ncsi_over_mctp_huawei;
    mc::milliseconds      m_interval       = mc::milliseconds(5000);
    mc::milliseconds      m_smbus_interval = mc::milliseconds(5000);
    mc::shared_ptr<mctp>  m_mctp_object;
};

} // namespace dev

// MC_REFLECT定义:建立接口成员与 D-Bus 接口名的映射
MC_REFLECT(dev::hi182x_card,
    ((m_system_id, "SystemId"))((m_pcie_device, "bmc.dev.PCIeDevice"))
    ((m_pcie_device_pcie_function, "bmc.dev.PCIeDevice.PCIeFunction"))
    ((m_pcie_device_oem, "bmc.dev.PCIeDevice.Oem"))
    ((m_pcie_device_status, "bmc.dev.PCIeDevice.Status"))
    ((m_pcie_card, "bmc.dev.PCIeCard"))((m_pcie_card_oem, "bmc.dev.PCIeCard.Oem"))
    ((m_pcie_card_metrics, "bmc.dev.PCIeCard.Metrics"))
    ((m_network_adapter, "bmc.dev.NetworkAdapter"))
    ((m_network_adapter_fault_status, "bmc.dev.NetworkAdapter.FaultStatus"))
    ((m_cooling, "bmc.dev.Cooling"))((m_network_adapter_oem, "bmc.dev.NetworkAdapter.Oem"))
    ((m_board, "bmc.dev.Board"))((m_pcie_device_bandwidth, "bmc.dev.PCIeDevice.Bandwidth"))
    ((m_fru, "bmc.dev.Fru"))
    ((m_network_adapter_log_collection, "bmc.dev.NetworkAdapter.LogCollection")))

#endif // HI182X_CARD_H

子设备识别(节选自 init_network_ports(),与库中一致)

cpp
// 通过对象名前缀识别设备类型,使用 dynamic_cast 并校验空指针
for (auto& object : objects) {
    std::string sub_name = object->get_name();
    if (sub_name.substr(0, sub_name.find_first_of("_")) == "NicPort") {
        auto* port = dynamic_cast<hi182x_port*>(object.get());
        if (port == nullptr) {
            elog("hi182x_card child ${name} is not hi182x_port, skip", ("name", sub_name));
            continue;
        }
        ilog("hi182x_card init network port ${name}", ("name", sub_name));
        m_network_ports.push_back(port);
    }
}

6.3 接口层次关系

7. 完整开发流程示例

7.1 步骤1: 编写DDS配置文件

json
// dds/PCIeGpuCard.dds.json
{
    "Schema": "dds-v1",
    "Type": "Component",
    "DeviceCategory": "PCIeGpuCard",
    "ID": "N/A",
    "Objects": {
        "PCIeGpuCard": {
            "Path": "/bmc/dev/Systems/:SystemId/PCIeGpuCard/:Id",
            "Interfaces": [
                "bmc.dev.PCIeDevice",
                "bmc.dev.PCIeCard",
                "bmc.dev.Gpu",
                "bmc.dev.Board"
            ]
        },
        "GpuMemory": {
            "Path": ":Parent/Memory/:Id",
            "Interfaces": [
                "bmc.dev.Memory",
                "bmc.dev.Memory.Metrics"
            ]
        }
    }
}

7.2 步骤2: 运行代码生成器

bash
# 生成接口代码
./tools/dds_codegen.py \
    --input dds/PCIeGpuCard.dds.json \
    --output-cpp gen/include/device_tree/

# 生成输出(仅接口头文件,无 _reflect.h;反射在接口 .cpp 中注册):
# gen/include/device_tree/interface/Gpu.h
# gen/include/device_tree/interface/Memory.h

7.3 步骤3: 实现厂商接口

cpp
// drivers/pcie_gpu_card/nvidia/interface/gpu.h
#ifndef NVIDIA_INTERFACE_GPU_H
#define NVIDIA_INTERFACE_GPU_H

#include <device_tree/interface/Gpu.h>

namespace dev {

/**
 * @brief GPU接口的NVIDIA厂商实现
 */
class Gpu : public mc::engine::interface<Gpu, gen::Gpu> {
public:
    // 实现基类虚方法
    bool Initialize() override {
        // NVIDIA特定的初始化逻辑
        return init_nvidia_gpu();
    }

    bool GetStatus() override {
        // 通过NVIDIA驱动获取GPU状态
        return query_nvidia_status();
    }

private:
    bool init_nvidia_gpu();
    bool query_nvidia_status();
};

} // namespace dev

#endif // NVIDIA_INTERFACE_GPU_H

7.4 步骤4: 实现设备对象

cpp
// drivers/pcie_gpu_card/nvidia/tesla_t4/tesla_t4_card.h
#ifndef NVIDIA_TESLA_T4_CARD_H
#define NVIDIA_TESLA_T4_CARD_H

#include <mc/engine/object.h>
#include "drivers/pcie_gpu_card/nvidia/interface/gpu.h"
#include "drivers/pcie_gpu_card/nvidia/interface/pcie_device.h"

namespace dev {

class tesla_t4_card : public mc::engine::object<tesla_t4_card> {
public:
    MC_OBJECT(
        tesla_t4_card,
        "PCIeGpuCard",
        "/bmc/dev/Systems/1/PCIeGpuCard/${object_name}",
        (PCIeDevice)(PCIeCard)(Board))

    bool init(mc::mutable_dict& csr_object, const mc::dict& connector);
    bool start();
    bool stop();

    // 接口实例
    dev::PCIeDevice m_pcie_device;
    dev::PCIeCard m_pcie_card;
    dev::Gpu m_gpu;
    dev::Board m_board;
};

} // namespace dev

MC_REFLECT(dev::tesla_t4_card,
    ((m_pcie_device, "bmc.dev.PCIeDevice"))
    ((m_pcie_card, "bmc.dev.PCIeCard"))
    ((m_gpu, "bmc.dev.Gpu"))
    ((m_board, "bmc.dev.Board"))
)

#endif // NVIDIA_TESLA_T4_CARD_H

7.5 步骤5: 实现ABI导出

cpp
// drivers/pcie_gpu_card/nvidia/tesla_t4/tesla_t4_abi.cpp
#include <devmon/driver_abi.h>
#include "tesla_t4_card.h"

extern "C" {

driver_handle_t create_tesla_t4_card(void* service, const char* name) {
    try {
        if (service == nullptr || name == nullptr) {
            return nullptr;
        }

        auto* device = new dev::tesla_t4_card();
        device->set_service(static_cast<mc::engine::service*>(service));
        device->set_object_name(name);
        return (void*)device;
    } catch (const std::exception& e) {
        elog("Error creating tesla_t4_card: ${error}", ("error", e.what()));
        return nullptr;
    }
}

status_t init_tesla_t4_card(driver_handle_t device, void* csr_object, void* connector) {
    if (device == nullptr || csr_object == nullptr || connector == nullptr) {
        return STATUS_ERROR;
    }

    auto* device_object = static_cast<dev::tesla_t4_card*>(device);
    auto* csr_object_ptr = static_cast<mc::mutable_dict*>(csr_object);
    auto* connector_ptr = static_cast<mc::dict*>(connector);

    bool ret = device_object->init(*csr_object_ptr, *connector_ptr);
    return ret ? STATUS_OK : STATUS_ERROR;
}

status_t start_tesla_t4_card(driver_handle_t device) {
    if (device == nullptr) {
        return STATUS_ERROR;
    }
    auto* device_object = static_cast<dev::tesla_t4_card*>(device);
    bool ret = device_object->start();
    return ret ? STATUS_OK : STATUS_ERROR;
}

status_t stop_tesla_t4_card(driver_handle_t device) {
    if (device == nullptr) {
        return STATUS_ERROR;
    }
    auto* device_object = static_cast<dev::tesla_t4_card*>(device);
    bool ret = device_object->stop();
    return ret ? STATUS_OK : STATUS_ERROR;
}

device_driver_t tesla_t4_card_driver = {
    .device_name = "PCIeGpuCard",
    .ctor = create_tesla_t4_card,
    .init = init_tesla_t4_card,
    .start = start_tesla_t4_card,
    .stop = stop_tesla_t4_card
};

status_t register_device_driver(device_driver_t** device_driver, uint8_t* count) {
    *device_driver = &tesla_t4_card_driver;
    *count = 1;
    return STATUS_OK;
}

} // extern "C"

7.6 步骤6: 编译和测试

bash
# 配置构建
meson setup builddir

# 编译驱动库
meson compile -C builddir

# 运行测试
meson test -C builddir

# 安装驱动
meson install -C builddir

8. 最佳实践

8.1 DDS配置设计原则

原则说明示例
单一职责每个接口专注单一功能域NetworkPort.LinkInfo只负责链路信息
接口组合通过组合而非继承扩展功能PCIeNicCard组合PCIeDevice+NetworkAdapter
路径规范使用层次化路径表示设备关系/Systems/:SystemId/PCIeNicCard/:Id
属性命名使用大驼峰命名法保持一致DeviceName, VendorId, NetworkPortCount
只读/可写明确标识属性的访问权限VendorId只读, DeviceName可写

8.2 接口实现规范

cpp
// ✅ 推荐:清晰的接口实现
class PCIeDevice : public mc::engine::interface<PCIeDevice, gen::PCIeDevice> {
public:
    // 1. 实现所有虚方法
    bool SetRootBDF(uint8_t bus, uint8_t device, uint8_t function) override {
        // 参数验证
        if (!validate_bdf(bus, device, function)) {
            return false;
        }

        // 更新生成基类中的属性
        Bus      = bus;
        Device   = device;
        Function = function;

        return true;
    }

private:
    // 2. 使用私有方法封装复杂逻辑
    bool validate_bdf(uint8_t bus, uint8_t device, uint8_t function) {
        return !(bus == 0 && device == 0 && function == 0);
    }
};

// ❌ 不推荐:不完整的实现
class PCIeDevice : public mc::engine::interface<PCIeDevice, gen::PCIeDevice> {
public:
    // 缺少虚方法实现,导致编译错误
    // 缺少日志记录
    // 缺少错误处理
};

8.3 设备对象设计模式

cpp
// ✅ 推荐:标准的设备对象模式
class hi182x_card : public mc::engine::object<hi182x_card> {
public:
    // 1. 使用MC_OBJECT定义对象元数据
    MC_OBJECT(hi182x_card, "PCIeNicCard",
              "/bmc/dev/Systems/1/PCIeNicCard/${object_name}",
              (PCIeDevice)(NetworkAdapter)(Board))

    // 2. 实现标准生命周期方法
    bool init(mc::mutable_dict& csr_object, const mc::dict& connector) {
        // 初始化逻辑
        return true;
    }

    bool start() {
        // 启动逻辑
        return true;
    }

    bool stop() {
        // 停止逻辑
        return true;
    }

    // 3. 声明接口实例
    dev::PCIeDevice m_pcie_device;
    dev::NetworkAdapter m_network_adapter;
    dev::Board m_board;

private:
    // 4. 私有成员和辅助方法
    void init_ports();
    bool start_protocol();
};

// 5. 定义反射映射
MC_REFLECT(dev::hi182x_card,
    ((m_pcie_device, "bmc.dev.PCIeDevice"))
    ((m_network_adapter, "bmc.dev.NetworkAdapter"))
    ((m_board, "bmc.dev.Board"))
)

8.4 性能优化建议

cpp
// 1. 优先使用属性提供的批量/只读访问接口
//    属性值通过 .get_value() 一次读取,避免重复反序列化
std::string model = m_pcie_device.Model.get_value().as<std::string>();

// 2. 缓存频繁访问的属性(按实际存在的属性为准,此处以 DeviceType 为例)
class PCIeDevice {
private:
    std::string               m_cached_device_type;
    bool                      m_device_type_cached = false;

public:
    const std::string& get_device_type() {
        if (!m_device_type_cached) {
            m_cached_device_type = DeviceType.get_value().as<std::string>();
            m_device_type_cached = true;
        }
        return m_cached_device_type;
    }
};

9. 总结

部件驱动接口模型通过DDS配置驱动的设计理念,实现了设备驱动开发的标准化和自动化:

9.1 核心优势

  1. 配置驱动开发: DDS配置文件定义设备接口和对象模型
  2. 自动代码生成: 从配置自动生成C++接口和反射代码
  3. 接口实现分离: 生成的接口代码与厂商实现完全解耦
  4. 类型安全: 编译期类型检查,减少运行时错误
  5. 易于扩展: 新增接口只需修改DDS配置

9.2 开发流程

DDS配置 → 代码生成 → 接口实现 → 设备对象 → ABI导出 → 编译测试

9.3 适用场景

  • 需要统一管理多种设备类型的系统
  • 需要支持多厂商设备的平台
  • 需要快速开发新设备驱动的项目
  • 需要接口标准化的设备管理系统

通过遵循本文档的设计原则和最佳实践,开发者可以高效地开发出高质量、可维护的设备驱动程序,构建强大的设备管理系统。