Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

6.2 驱动架构设计:分层思想的现实应用

一个问题:SDK的驱动层是怎么组织的?

假设你理解了SDK的整体架构,现在打开传输层的代码目录。

你发现代码分散在多个文件:

  • driver_i2c.cdriver_spi.c
  • hal_gpio.chal_i2c.c
  • device_hsm.c

你可能会困惑:

  • 这些文件是什么关系?
  • 为什么需要这么多层级?
  • 调用顺序是什么?

更深层的问题是:

SDK如何用分层设计实现硬件抽象?这与hsm-lite有什么不同?

与hsm-lite的对比

hsm-lite没有驱动层——密钥和Session都在内存中,不需要与硬件通信。

真实SDK必须解决硬件通信问题:

对比:

hsm-lite(教学简化)
├── C_GenerateKey → 直接生成随机数 → 存到内存数组
├── C_Encrypt → 直接调用xor_encrypt
└── 无硬件通信

真实SDK(生产实现)
├── hsm_generate_key → 组APDU → 封帧 → 发SPI → HSM处理 → 收响应 → 解帧 → 返回结果
└── 每一步都要处理硬件细节

真实SDK需要在应用层和硬件之间插入多层驱动,每层处理一类问题。

三层驱动架构

典型的SDK采用三层驱动架构:

三层驱动架构

┌─────────────────────────────────────────────────┐
│  第一层:总线驱动(bus_driver)                   │
│  职责:管理特定总线类型(I2C/SPI/UART)的通用操作   │
│  存储:全局数组 g_bus_drivers[]                   │
│  特点:一个总线类型对应一个驱动实例                 │
└─────────────────────────────────────────────────┘
                      ↓ 挂载设备
┌─────────────────────────────────────────────────┐
│  第二层:设备驱动(device_driver)                │
│  职责:管理连接到总线上的具体设备                  │
│  存储:总线驱动的 devices[] 数组                  │
│  特点:同一总线上的不同设备有不同驱动实例           │
└─────────────────────────────────────────────────┘
                      ↓ 硬件操作
┌─────────────────────────────────────────────────┐
│  第三层:硬件抽象层(HAL)                        │
│  职责:封装GPIO/I2C/SPI的具体操作                 │
│  存储:设备驱动的函数指针                          │
│  特点:平台相关代码,需要适配                      │
└─────────────────────────────────────────────────┘

数据结构设计

总线驱动结构

typedef struct {
    bus_type_t type;                 // 总线类型:SPI/I2C/UART
    device_driver *devices[MAX_DEVICES];  // 挂载的设备数组
    int (*init)(device_driver *);    // 总线初始化
    int (*open)(device_driver *, uint8_t *, size_t *); // 打开设备(含ATR)
    int (*close)(device_driver *);   // 关闭设备
    int (*transmit)(device_driver *, uint8_t *, size_t);  // 发送
    int (*receive)(device_driver *, uint8_t *, size_t *); // 接收
    void *extra;                     // 扩展数据
} bus_driver;

设备驱动结构

typedef struct {
    bus_type_t type;                 // 设备类型(与总线类型一致)
    uint32_t id;                     // 设备标识
    int (*init)(void *);             // 设备特定初始化
    int (*transmit)(void *, uint8_t *, size_t);  // 设备特定发送
    int (*receive)(void *, uint8_t *, size_t *); // 设备特定接收
    void *config;                    // 设备配置参数
} device_driver;

全局管理

bus_driver *g_bus_drivers[MAX_BUS_TYPES];  // 全局驱动数组
struct {
    bus_driver *bus;
    device_driver *device;
} g_current_driver;                       // 当前选择的驱动

注册/选择/连接流程

注册流程:hsm_register_driver

int hsm_register_driver(bus_type_t type, uint32_t device_id) {
    bus_driver *bus = find_bus_driver(type);
    device_driver *device = find_device_driver(type, device_id);
    
    if (bus == NULL || device == NULL) {
        return HSM_ERR_INVALID_PARAM;
    }
    
    return add_driver_to_global(bus, device);
}

注册后的结构:

全局驱动管理器 g_bus_drivers[4]
├── g_bus_drivers[0] → I2C总线驱动
│   ├── devices[0] → HSM设备
│   ├── devices[1] → NULL
│   └── ...
├── g_bus_drivers[1] → NULL
├── g_bus_drivers[2] → NULL
└── g_bus_drivers[3] → NULL

选择流程:hsm_select_device

int hsm_select_device(bus_type_t type, uint32_t device_id) {
    bus_driver *bus = find_bus_driver(type);
    if (bus == NULL) return HSM_ERR_NOT_FOUND;
    
    device_driver *device = find_device(bus, device_id);
    if (device == NULL) return HSM_ERR_NOT_FOUND;
    
    g_current_driver.bus = bus;
    g_current_driver.device = device;
    
    return HSM_OK;
}

后续操作通过g_current_driver获取当前驱动。

连接流程:hsm_connect

int hsm_connect(uint8_t *atr, size_t *atr_len) {
    bus_driver *bus = g_current_driver.bus;
    device_driver *device = g_current_driver.device;
    
    // 初始化总线
    int ret = bus->init(device);
    if (ret != HSM_OK) return ret;
    
    // 打开设备,获取ATR
    ret = bus->open(device, atr, atr_len);
    if (ret != HSM_OK) return ret;
    
    return HSM_OK;
}

初始化的层层调用

bus->init()会层层向下:

调用链:

hsm_connect
    ↓
bus->init(device)               ← 总线驱动层:driver_i2c_init
    ↓
device->init(device)            ← 设备驱动层:hal_i2c_device_init
    ↓
hal_gpio_init()                 ← 硬件抽象层:GPIO初始化
hal_i2c_config()                ← 硬件抽象层:I2C配置
    ↓
open("/dev/i2c-1", O_RDWR)      ← 打开设备文件
ioctl(fd, I2C_SLAVE, addr)      ← 设置从设备地址
ioctl(fd, I2C_TIMEOUT, timeout) ← 设置超时

完整调用示例

// 步骤1:注册驱动
int ret = hsm_register_driver(BUS_I2C, DEVICE_HSM_0);
if (ret != HSM_OK) {
    return ret;
}

// 步骤2:选择设备
ret = hsm_select_device(BUS_I2C, DEVICE_HSM_0);
if (ret != HSM_OK) {
    return ret;
}

// 步骤3:连接设备
uint8_t atr[32];
size_t atr_len;
ret = hsm_connect(atr, &atr_len);
if (ret != HSM_OK) {
    return ret;
}

设计优势总结

三层架构的分层思想与PKCS#11的设计理念一致:

PKCS#11理念SDK驱动设计共通原理
Slot抽象硬件差异总线驱动抽象总线差异概念抽象
Session管理状态设备驱动管理设备状态状态管理
Object统一接口HAL统一硬件接口接口统一
Mechanism支持扩展多总线类型可扩展扩展性

理解了PKCS#11的设计哲学,再看SDK的驱动架构,会发现它们遵循相同的分层抽象原则。 下一节,我们将深入通信协议——看数据如何从代码变成波形。

【下集预告】

APDU是什么?帧格式是什么?

I2C和SPI有什么区别?

长帧传输会遇到什么问题?

下一节,通信协议实战。