首页 > 应用开发 > IT综合 > USB协议层数据格式:深入解析通信帧结构
# USB协议层数据格式:深入解析通信帧结构
## USB协议框架概述
USB(通用串行总线)协议采用分层架构,从物理连接层到应用层共分为四个主要层次。协议层作为USB通信的核心,定义了数据传输的格式和规则,确保主机与设备间的可靠通信。
### USB通信模型基本结构
USB采用主从架构,主机控制所有通信过程。通信的基本单位是"事务",多个事务组成"传输"。USB支持四种传输类型:控制传输、中断传输、批量传输和同步传输,每种类型针对不同的数据传输需求。
## 数据包基本格式
USB通信以数据包为基本单元,所有数据包都遵循特定的格式结构。
### 同步字段与包标识符
```c
// USB数据包基本结构
typedef struct {
uint8_t sync_pattern[8]; // 同步字段:KJKJKJKK(NRZI编码)
uint8_t pid; // 包标识符
uint8_t payload[]; // 数据载荷(可变长度)
uint16_t crc; // 循环冗余校验
} usb_packet_t;
// PID类型定义
typedef enum {
// 令牌包PID
PID_OUT = 0xE1, // 主机到设备传输
PID_IN = 0x69, // 设备到主机传输
PID_SOF = 0xA5, // 帧起始
PID_SETUP = 0x2D, // 控制传输建立阶段
// 数据包PID
PID_DATA0 = 0xC3, // 数据包交替位0
PID_DATA1 = 0x4B, // 数据包交替位1
PID_DATA2 = 0x87, // 高速同步传输
PID_MDATA = 0x0F, // 高速分割与高带宽事务
// 握手包PID
PID_ACK = 0xD2, // 确认接收
PID_NAK = 0x5A, // 暂时无法响应
PID_STALL = 0x1E, // 端点挂起
PID_NYET = 0x96, // 未准备好(仅高速)
// 特殊PID
PID_PRE = 0x3C, // 前导包(低速设备)
PID_ERR = 0x3C, // 错误条件
PID_SPLIT = 0x78, // 分割事务
PID_PING = 0xB4, // 流控制探测
} pid_type_t;
```
## 令牌包详细解析
令牌包由主机发出,用于启动一个USB事务,定义事务的类型和方向。
### 标准令牌包格式
```c
// 令牌包结构体定义
typedef struct __attribute__((packed)) {
uint8_t sync; // 同步字段
uint8_t pid; // 包标识符
uint16_t device_info; // 设备地址和端点号
uint8_t crc5; // 5位CRC校验
} token_packet_t;
// 设备信息字段解析宏
#define USB_DEVICE_ADDR(device_info) ((device_info >> 7) & 0x7F)
#define USB_ENDPOINT_NUM(device_info) ((device_info >> 0) & 0x0F)
#define USB_CRC5_MASK 0x001F
// 特殊令牌包:SOF包
typedef struct __attribute__((packed)) {
uint8_t sync;
uint8_t pid; // PID_SOF
uint16_t frame_number; // 11位帧编号
uint8_t crc5;
} sof_packet_t;
```
## 数据包格式详解
数据包携带实际传输的数据内容,支持不同的数据PID类型以实现流控制和错误检测。
### 数据包结构
```c
// 数据包结构体
typedef struct __attribute__((packed)) {
uint8_t sync;
uint8_t pid; // DATA0, DATA1, DATA2, MDATA
uint8_t data[]; // 数据载荷(最多1024字节)
uint16_t crc16; // 16位CRC校验
} data_packet_t;
// CRC16计算函数
uint16_t usb_crc16(const uint8_t *data, uint32_t length) {
uint16_t crc = 0xFFFF;
for (uint32_t i = 0; i < length; i++) {
crc ^= (uint16_t)data[i];
for (uint8_t j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
// 数据交替机制实现
typedef struct {
uint8_t expected_data_pid; // 期望接收的数据PID
} endpoint_state_t;
int process_data_packet(data_packet_t *packet, endpoint_state_t *state) {
// 检查数据交替位
if ((packet->pid == PID_DATA0 || packet->pid == PID_DATA1) &&
packet->pid != state->expected_data_pid) {
// 数据交替位错误
return -1;
}
// 更新期望的PID
if (packet->pid == PID_DATA0) {
state->expected_data_pid = PID_DATA1;
} else if (packet->pid == PID_DATA1) {
state->expected_data_pid = PID_DATA0;
}
return 0;
}
```
## 握手包与特殊包
### 握手包处理
```c
// 握手包类型
typedef enum {
HANDSHAKE_ACK, // 正确接收数据
HANDSHAKE_NAK, // 暂时无法响应
HANDSHAKE_STALL, // 端点挂起
HANDSHAKE_NYET // 高速设备未准备好
} handshake_type_t;
// 握手包响应决策
handshake_type_t determine_handshake_response(
data_packet_t *data_packet,
endpoint_status_t *endpoint
) {
// 检查CRC
uint16_t calculated_crc = usb_crc16(
data_packet->data,
get_packet_length(data_packet)
);
if (calculated_crc != data_packet->crc16) {
// CRC错误,丢弃数据但不发送握手包
return -1;
}
// 检查端点状态
if (endpoint->stalled) {
return HANDSHAKE_STALL;
}
if (!endpoint->ready_to_receive) {
return HANDSHAKE_NAK;
}
if (endpoint->buffer_full) {
// 高速设备特有响应
if (endpoint->high_speed) {
return HANDSHAKE_NYET;
} else {
return HANDSHAKE_NAK;
}
}
return HANDSHAKE_ACK;
}
```
## 事务与传输结构
### 控制传输事务
```c
// 控制传输建立阶段
typedef struct __attribute__((packed)) {
uint8_t bmRequestType; // 请求特征
uint8_t bRequest; // 请求代码
uint16_t wValue; // 请求参数
uint16_t wIndex; // 请求参数
uint16_t wLength; // 数据阶段长度
} setup_stage_t;
// 完整的控制传输
typedef struct {
token_packet_t setup_token; // SETUP令牌
data_packet_t setup_data; // 建立数据
handshake_packet_t setup_handshake;
// 可选的数据阶段
token_packet_t data_token;
data_packet_t data_packet;
handshake_packet_t data_handshake;
// 状态阶段
token_packet_t status_token;
handshake_packet_t status_handshake;
} control_transfer_t;
```
## 描述符数据结构
USB设备通过描述符向主机报告其能力和配置信息。
### 标准描述符格式
```c
// 设备描述符
typedef struct __attribute__((packed)) {
uint8_t bLength; // 描述符长度(18字节)
uint8_t bDescriptorType; // 描述符类型(0x01)
uint16_t bcdUSB; // USB规范版本号
uint8_t bDeviceClass; // 设备类代码
uint8_t bDeviceSubClass; // 设备子类代码
uint8_t bDeviceProtocol; // 设备协议代码
uint8_t bMaxPacketSize0; // 端点0最大包大小
uint16_t idVendor; // 厂商ID
uint16_t idProduct; // 产品ID
uint16_t bcdDevice; // 设备版本号
uint8_t iManufacturer; // 厂商字符串索引
uint8_t iProduct; // 产品字符串索引
uint8_t iSerialNumber; // 序列号字符串索引
uint8_t bNumConfigurations;// 配置描述符数量
} device_descriptor_t;
// 配置描述符
typedef struct __attribute__((packed)) {
uint8_t bLength; // 描述符长度(9字节)
uint8_t bDescriptorType; // 描述符类型(0x02)
uint16_t wTotalLength; // 配置信息总长度
uint8_t bNumInterfaces; // 接口数量
uint8_t bConfigurationValue;// 配置值
uint8_t iConfiguration; // 配置字符串索引
uint8_t bmAttributes; // 配置特性
uint8_t bMaxPower; // 最大功耗(2mA单位)
} configuration_descriptor_t;
<"1q.q6k0.org.cn"><"3m.q6k0.org.cn"><"7d.q6k0.org.cn">
// 端点描述符
typedef struct __attribute__((packed)) {
uint8_t bLength; // 描述符长度(7字节)
uint8_t bDescriptorType; // 描述符类型(0x05)
uint8_t bEndpointAddress; // 端点地址和方向
uint8_t bmAttributes; // 端点特性
uint16_t wMaxPacketSize; // 最大包大小
uint8_t bInterval; // 轮询间隔
} endpoint_descriptor_t;
```
## 协议状态机实现
### 设备状态管理
```c
// USB设备状态定义
typedef enum {
USB_STATE_DETACHED, // 未连接
USB_STATE_ATTACHED, // 已连接
USB_STATE_POWERED, // 已供电
USB_STATE_DEFAULT, // 默认状态
USB_STATE_ADDRESS, // 已分配地址
USB_STATE_CONFIGURED, // 已配置
USB_STATE_SUSPENDED // 挂起状态
} usb_device_state_t;
// 状态机处理函数
void usb_state_machine(usb_device_t *device, usb_event_t event) {
switch (device->state) {
case USB_STATE_DEFAULT:
if (event == EVENT_SET_ADDRESS) {
device->state = USB_STATE_ADDRESS;
configure_device_address(device->assigned_address);
}
break;
case USB_STATE_ADDRESS:
if (event == EVENT_SET_CONFIGURATION) {
device->state = USB_STATE_CONFIGURED;
enable_endpoints(device);
}
break;
case USB_STATE_CONFIGURED:
if (event == EVENT_SUSPEND) {
device->state = USB_STATE_SUSPENDED;
reduce_power_consumption();
}
break;
// 其他状态转换...
}
}
```
## 错误检测与恢复机制
### 协议层错误处理
```c
// 超时检测
typedef struct {
uint32_t last_activity_time;
uint32_t timeout_threshold;
} timeout_monitor_t;
int check_timeout(timeout_monitor_t *monitor) {
uint32_t current_time = get_current_time();
uint32_t elapsed = current_time - monitor->last_activity_time;
if (elapsed > monitor->timeout_threshold) {
// 触发超时恢复
initiate_error_recovery();
return 1;
}
monitor->last_activity_time = current_time;
return 0;
}
// 协议错误恢复
void usb_protocol_recovery(usb_device_t *device) {
switch (device->recovery_level) {
case RECOVERY_LEVEL_SOFT:
// 软复位:重置端点状态
reset_endpoint_states(device);
reset_data_toggle();
break;
case RECOVERY_LEVEL_HARD:
// 硬复位:重新初始化控制器
usb_controller_reset();
reinitialize_descriptors();
break;
case RECOVERY_LEVEL_FULL:
// 完全恢复:模拟重新连接
simulate_disconnect();
simulate_reconnect();
perform_enumeration();
break;
}
}
```
## 实际数据分析示例
### USB数据包解析工具
```python
# Python实现的简单USB数据包解析器
class USBPacketParser:
def __init__(self):
self.pid_names = {
0xE1: "OUT", 0x69: "IN", 0xA5: "SOF", 0x2D: "SETUP",
0xC3: "DATA0", 0x4B: "DATA1", 0x87: "DATA2", 0x0F: "MDATA",
0xD2: "ACK", 0x5A: "NAK", 0x1E: "STALL", 0x96: "NYET"
}
def parse_packet(self, raw_data):
"""解析原始USB数据包"""
if len(raw_data) < 4:
return None
# 提取PID
pid_byte = raw_data[1]
pid_type = pid_byte & 0x0F
pid_check = (pid_byte >> 4) & 0x0F
# 验证PID(低4位应为高4位的补码)
if (pid_type ^ pid_check) != 0x0F:
return {"error": "Invalid PID checksum"}
packet_info = {
"sync": raw_data[0],
"pid": self.pid_names.get(pid_type, f"UNKNOWN(0x{pid_type:02X})"),
"raw_pid": pid_type
}
# 根据PID类型进一步解析
if pid_type in [0xE1, 0x69, 0x2D]: # 令牌包
if len(raw_data) >= 4:
device_info = raw_data[2] | (raw_data[3] << 8)
packet_info.update({
"device_address": (device_info >> 7) & 0x7F,
"endpoint_number": device_info & 0x0F,
"crc5": (device_info >> 11) & 0x1F
})
elif pid_type in [0xC3, 0x4B, 0x87, 0x0F]: # 数据包
if len(raw_data) >= 5:
data_length = len(raw_data) - 4
packet_info.update({
"data": raw_data[2:2+data_length],
"crc16": raw_data[-2] | (raw_data[-1] << 8),
"data_length": data_length
})
elif pid_type == 0xA5: # SOF包
if len(raw_data) >= 4:
frame_number = raw_data[2] | ((raw_data[3] & 0x07) << 8)
packet_info.update({
"frame_number": frame_number,
"crc5": (raw_data[3] >> 3) & 0x1F
})
return packet_info
<"0h.q6k0.org.cn"><"4s.q6k0.org.cn"><"6f.q6k0.org.cn">
```
## 性能优化与协议调优
### 批量传输优化策略
```c
// 批量传输管道管理
typedef struct {
uint8_t endpoint_address;
uint16_t max_packet_size;
uint8_t data_toggle;
uint32_t bytes_transferred;
uint32_t error_count;
double average_throughput;
} bulk_pipe_t;
// 自适应包大小调整
uint16_t adjust_packet_size(bulk_pipe_t *pipe, uint32_t transfer_size) {
if (pipe->error_count > 10) {
// 错误率过高,减小包大小
return max(8, pipe->max_packet_size / 2);
}
if (pipe->average_throughput < 0.5 * pipe->max_packet_size) {
// 吞吐量低,尝试增大包大小
uint16_t new_size = min(
pipe->max_packet_size * 2,
get_max_supported_packet_size()
);
if (transfer_size >= new_size) {
return new_size;
}
}
return pipe->max_packet_size;
}
```
## 结语
USB协议层数据格式的设计体现了在可靠性、效率和兼容性之间的精细平衡。从最基本的同步字段到复杂的描述符体系,每一层设计都服务于特定的通信需求。理解这些数据格式不仅有助于USB设备的开发调试,也为协议分析、性能优化和安全检测提供了基础。
随着USB技术的演进,从USB 1.0到最新的USB4,协议层在保持向后兼容的同时不断引入新特性。但核心的数据包格式和通信机制保持了相对稳定,这种设计哲学确保了USB作为通用接口的长期成功。深入掌握USB协议层数据格式,是开发高质量USB设备和进行底层通信分析的关键所在。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3108512/ ,如需转载,请注明出处,否则将追究法律责任。