This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
CrabUSB 是一个为嵌入式系统和操作系统内核设计的高性能异步 USB 主机驱动程序,使用 Rust 编写。该项目采用无锁设计,基于 TRB (Transfer Request Block) 环形结构,每个 TRB 代表一个异步任务。
- Async/Await 支持: 从头开始使用 async 原语构建非阻塞 USB 操作
- 无锁设计: 基于 TRB 环形架构,零锁异步操作
- xHCI 控制器支持: 完整实现 xHCI (可扩展主机控制器接口) 规范
- No-STD 兼容: 为
#![no_std]环境设计 - 多后端支持: xHCI (直接硬件访问) 和 libusb (用户空间测试)
- TRB 环形机制: 每个 TRB 代表一个异步任务,Future 查询环形结构获取结果
- 执行器无关: 不绑定特定执行器,可同步使用
- DMA 感知: 高效的内存管理,支持 DMA 一致性
- 零成本抽象: 类型安全端点(通过 newtype 模式实现)
CrabUSB/
├── usb-host/ # 主机驱动核心实现 (crab-usb)
│ └── src/
│ ├── backend/ # 后端实现
│ │ ├── xhci/ # xHCI 硬件驱动 (标准 USB3 主机控制器)
│ │ ├── dwc/ # DWC3 控制器驱动 (RK3588 等平台)
│ │ ├── libusb/ # libusb 用户空间后端 (libusb feature)
│ │ └── ty/ # 后端操作 trait 定义 (HubOp, DeviceOp 等)
│ ├── hub/ # Hub 设备管理和路由 (RouteString)
│ ├── device/ # 设备抽象层
│ └── osal.rs # OS 抽象层 (Kernel trait)
├── usb-if/ # USB 接口定义和类型
│ └── src/
│ ├── descriptor/ # USB 描述符解析
│ ├── host/ # Host trait 定义 (Controller, Device, Interface, Endpoint)
│ └── transfer/ # 传输类型定义
├── usb-device/ # USB 设备类实现
│ ├── uvc/ # USB Video Class (crab-uvc)
│ └── hid/keyboard/ # HID 键盘设备
├── test_crates/ # 测试用例
│ ├── test_xhci_uvc/ # xHCI UVC 测试 (aarch64-none)
│ ├── test_hub/ # Hub 多层枚举测试 (aarch64-none)
│ ├── test_libusb_uvc/# libusb UVC 测试
│ └── test_libusb/ # libusb 基础测试
├── docs/ # 架构文档
│ ├── HUB_ARCHITECTURE.md # Hub 架构设计
│ ├── design.md # 异步模型设计
│ └── rockchip/ # RK3588 平台相关文档
└── utils/
└── uvc-frame-parser/ # UVC 帧解析工具
关键模块职责:
usb-if: 定义跨后端的统一接口,所有后端必须实现这些 traitusb-host/backend: 后端实现,xHCI 用于生产环境,libusb 用于开发测试usb-host/hub: Hub 设备管理,支持 Root Hub 和 External Hub 统一接口usb-device: 设备类驱动,UVC 是最复杂的实现(视频流捕获)test_crates: 验证功能,包括 UVC 测试和 Hub 多层枚举测试
最近新增功能 (2024-2025):
- Hub 支持:完整的 Root Hub 和 External Hub 架构,支持多层 Hub 枚举
- DWC3 控制器:RK3588 平台支持,包括 USB3 PHY 和 USB2 PHY 驱动
- 事件处理:改进的事件处理机制,支持 libusb 事件处理线程
修改完代码后,确保 cargo check -p crab-usb --test test --target aarch64-unknown-none-softfloat 可以通过,
执行 cargo fmt --all 保持代码风格一致。
注意诊断警告: 修改代码后应检查 IDE 诊断信息,清理未使用的导入、变量和死代码。主要问题包括:
reg.rs: 未使用的文档注释(宏生成的项不支持外部文档)grf.rs: 多个未使用的关联项和结构体context.rs: 未使用的方法update_inputconsts.rs: 多个未使用的常量mod.rs: 未使用的导入BackendOp
-
workspace dependencies: 在根
Cargo.toml中统一定义版本 -
常用依赖:
futures(default-features = false): 异步原语thiserror(default-features = false): 错误派生log: 日志记录tock-registers: 硬件寄存器访问bare-test: 裸机测试框架rockchip-*: Rockchip 平台支持
-
查询文档: 使用
context7MCP 服务器查询依赖库的使用方法
QEMU: /home/zhourui/opensource/qemu-10.1.0
参考路径:
- 主线内核:
/home/zhourui/linux-la64 - U-Boot:
/home/zhourui/opensource/proj_usb/u-boot-orangepi - Orange Pi 内核:
/home/zhourui/orangepi-build/kernel/orange-pi-6.1-rk35xx
关键文档:
docs/rockchip/rk3588.md: RK3588 USB3 Host 控制器依赖分析(寄存器、时钟、复位、电源域)docs/rockchip/u_boot_comparison.md: U-Boot DWC3 驱动对比docs/rockchip/rk3588_phy_register_analysis.md: PHY 寄存器分析
DWC3 控制器特性:
- 寄存器基地址:
0xfc400000(USB3OTG1) - USB3 PHY 基地址:
0xfed90000(USBDP PHY) - USB2 PHY 基地址:
0xfd5d8000 - 需要 GRF (General Register Files) 配置
- 支持的最大速度: USB 3.0 SuperSpeed
PHY 初始化关键点:
- USB2 PHY 必须先初始化并输出 UTMI 480MHz 时钟
- USBDP PHY 依赖 UTMI 时钟才能正常工作
- 必须按顺序解除复位:init → cmn → lane → pcs_apb → pma_apb
- GRF 配置需要使用写使能位格式 (Bit[31:16] 为使能, Bit[15:0] 为数据)
# 标准 no_std 测试 (使用 QEMU aarch64)
cargo test -p crab-usb --test test --target aarch64-unknown-none-softfloat -- -c qemu.toml --show-output
# 运行特定测试 (例如 uboot 测试)
cargo test --package test_xhci_uvc --test test --target aarch64-unknown-none-softfloat -- --show-output uboot
# Hub 多层枚举测试 (RK3588 DWC3 平台)
cargo test --package test_hub --test test --target aarch64-unknown-none-softfloat -- --show-output test_all
# libusb 后端测试 (需要 libudev-dev)
cargo test -p crab-usb --features libusb --test test
# UVC 帧解析工具
cargo run -p uvc-frame-parser -- -l target/uvc.log -o target/output- 默认目标:
aarch64-unknown-none-softfloat - Runner:
cargo osrun(由 ostool 提供) - 配置:
.cargo/config.toml
usb-host/src/backend/ 提供了硬件抽象:
-
xHCI: 直接硬件访问,用于嵌入式系统和 OS 内核
mod.rs:Xhci结构体实现usb_if::host::Controllertraitring/: TRB 环形管理,核心异步机制event.rs: 事件处理和中断管理context.rs: 设备上下文管理endpoint.rs: 端点管理hub.rs: Root Hub 实现
-
DWC3: DesignWare USB3 DRD 控制器 (RK3588 等平台)
mod.rs:Dwc结构体封装 xHCI 主机控制器udphy/: USB3.0 Combo PHY (USBDP PHY) 驱动usb2phy.rs: USB2 PHY 驱动 (RK3588 特定调优)grf.rs: GRF (General Register Files) 配置- 关键特性:
- DWC3 在 Host 模式下实际使用 xHCI 寄存器 (0x0000-0x7fff)
- 全局寄存器区域 (0xc100-0xcfff) 包含 DWC3 特定配置
- 需要正确的 PHY 初始化顺序:USB2 PHY → USBDP PHY → DWC3 → xHCI
- 参考
docs/rockchip/rk3588.md了解完整的依赖关系
-
libusb: 用户空间后端,用于开发和测试
- 需要
libusbfeature 启用 - 使用
libusb1-sys绑定 - 关键实现细节:
- 端点地址: 必须保留完整的
bEndpointAddress(包括方向位 bit 7),不能截断为& 0x0F - ISO transfer:
libusb_alloc_transfer()第一个参数是iso_packets数量,ISO 传输必须传入正确的 packet 数 - 控制传输 buffer: 异步控制传输需要特殊布局 -
[8字节setup包] [数据区],必须使用temp_buff来保存
- 端点地址: 必须保留完整的
- 需要
-
ty/: 后端操作 trait 定义
hub.rs:HubOptrait - Hub 设备统一接口- 其他 trait:
DeviceInfoOp,DeviceOp,EventHandlerOp
定义了所有 USB 操作的标准 trait:
// Controller: 顶层控制器管理
pub trait Controller {
fn init(&mut self) -> LocalBoxFuture<'_, Result<(), USBError>>;
fn device_list(&self) -> LocalBoxFuture<'_, Result<Vec<Box<dyn DeviceInfo>>, USBError>>;
fn handle_event(&mut self); // 中断上下文调用
}
// Device: USB 设备操作
pub trait Device {
fn set_configuration(&mut self, configuration: u8) -> ...;
fn claim_interface(&mut self, interface: u8, alternate: u8) -> ...;
// Control 传输...
}
// EndpointQueue: endpoint 的运行时队列
pub trait EndpointQueue {
fn submit(&self, request: TransferRequest) -> Result<RequestId, TransferError>;
fn reclaim(&self, id: RequestId) -> Result<Option<TransferCompletion>, TransferError>;
fn poll_request(&self, id: RequestId, cx: &mut Context<'_>) -> Poll<...>;
}usb-host/src/osal.rs 定义了 Kernel trait,需要由使用者实现:
pub trait Kernel {
fn sleep(duration: Duration) -> BoxFuture<'_, ()>;
fn page_size() -> usize;
}使用 trait-ffi 的 def_extern_trait 宏实现 FFI 兼容。
- Future 类型:
LocalBoxFuture<'_, Result<T, E>> - 传输返回:
ResultTransfer<'a> = Result<TransferFuture<'a>, TransferError> - 唤醒机制: 使用
AtomicWaker实现端口状态变化通知 - 执行器无关: 不绑定特定执行器,可同步使用
所有传输类型都在 usb-if/src/transfer/ 中定义:
- Control: 设备设置和标准请求
- Bulk: 高吞吐量数据传输 (存储设备)
- Interrupt: 周期性数据传输 (HID 设备)
- Isochronous: 实时流传输 (音频/视频设备)
后端使用零成本抽象确保类型安全:
pub mod endpoint {
pub mod kind {
pub struct Bulk; // 批量传输
pub struct Interrupt; // 中断传输
pub struct Isochronous; // 等时传输
}
pub mod direction {
pub struct In; // 读取
pub struct Out; // 写入
}
}CrabUSB 实现了完整的 Root Hub 和 External Hub 支持,使用统一的 HubOp trait 接口。
核心概念:
- Root Hub: Host Controller 内部的 Hub,通过寄存器直接访问
- External Hub: USB 总线上的 Hub 设备,通过 USB Control 传输访问
- RouteString: 32位路由字符串,记录从 Root Hub 到设备的完整路径(最多 5 层)
RouteString 格式:
Bits [19:16] - Hub 5 端口号
Bits [15:12] - Hub 4 端口号
Bits [11:8] - Hub 3 端口号
Bits [7:4] - Hub 2 端口号
Bits [3:0] - Hub 1 端口号
Hub 层次示例:
Root Hub (Port 2)
└─ External Hub 1 (Port 3)
└─ External Hub 2 (Port 1)
└─ Device
RouteString = 0x00021
Root Hub Port = 0x2
相关文件:
usb-host/src/hub/mod.rs: Hub 核心结构和 RouteString 实现usb-host/src/hub/device.rs: HubDevice 实现 HubOp traitusb-host/src/backend/xhci/hub.rs: xHCI Root Hub 实现usb-host/src/backend/ty/hub.rs: HubOp trait 定义docs/HUB_ARCHITECTURE.md: 完整的 Hub 架构设计文档
使用场景:
- 多层 Hub 枚举(支持最多 5 层)
- 设备热插拔处理
- 端口状态监控和变化通知
libusb: 启用 libusb 后端,仅用于非target_os = "none"目标- 默认情况下,当
target_os = "none"时自动启用no_std
- no_std 环境: 不能使用
anyhow!宏 - 正确方式:
USBError::from("message")或"message".into() - 避免:
USBError::Other("...".into())- 这会导致类型推断问题
USB 端点地址格式:
- Bit 7: 方向位 (1=IN, 0=OUT)
- Bits 3:0: 端点号
- 示例: 端点 1 IN =
0x81(10000001b)
wMaxPacketSize 字段解析 (高速等时/中断端点):
- Bits 10:0: 最大包大小
- Bits 12:11: 事务乘数 (transactions_per_microframe = 值 + 1)
- 示例:
0x1400= max_packet_size=1024, packets_per_microframe=2 - 实际包大小 =
max_packet_size * packets_per_microframe
类特定描述符 (extra 字段):
InterfaceDescriptor::extra包含类特定描述符数据(如 UVC 格式/帧描述符)- 在
libusb_get_config_descriptor中从alt_desc.extra提取 - 用于避免额外的控制传输
- 使用
dma-api处理 DMA 一致性 crossbeam提供 lock-free 数据结构- 依赖
alloccrate,需与分配器集成
- xHCI 测试: 使用 QEMU aarch64 模拟硬件
- libusb 测试: 在主机 OS 上运行
- UVC 测试: 专门测试 USB Video Class 设备
UVC 测试运行:
# 运行 UVC 相机测试(会捕获 30 秒视频)
cargo run -p test_libusb_uvc
# 输出位置
# - JPEG 帧: target/output/images/frame_*.jpg
# - 视频信息: target/frames/video_info.toml- 使用
edition = "2024" - 广泛使用
newtype模式 (通过define_int_type!宏) - 使用
num_enum实现枚举转换 - 使用
tock-registers进行硬件寄存器访问
- 在
usb-device/下创建新包 - 使用
crab-usb和usb-if作为依赖 - 实现
usb_if::host::Interfacetrait 的使用模式
- 在
usb-host/src/backend/创建新目录 - 实现
usb_if::host::Controllertrait - 在
usb-host/src/backend/mod.rs中导出
- 启用
logcrate 的 debug 级别日志 - 使用
bare-test框架进行裸机测试 - 检查
test_crates/中的示例用法 - 使用 QEMU aarch64 进行 xHCI 测试,无需真实硬件
- 查看
docs/目录下的架构文档和平台特定文档
理解异步流程:
- 从
usb-if/src/host/开始,了解 trait 定义 - 查看
usb-host/src/backend/xhci/了解 xHCI 实现 - 研究
ring.rs理解 TRB 环形机制 - 阅读
test_crates/中的测试用例了解使用方式
理解 Hub 枚举:
- 阅读
docs/HUB_ARCHITECTURE.md了解架构设计 - 查看
usb-host/src/hub/mod.rs了解 RouteString 实现 - 研究
usb-host/src/backend/ty/hub.rs了解 HubOp trait - 运行
test_hub测试查看实际枚举流程
理解 RK3588 平台:
- 阅读
docs/rockchip/rk3588.md了解完整的依赖关系 - 查看
usb-host/src/backend/dwc/mod.rs了解 DWC3 初始化 - 研究
usb-host/src/backend/dwc/udphy/和usb2phy.rs了解 PHY 配置 - 对比 U-Boot 源码验证初始化顺序
症状: GUSB3PIPECTL 和 GUSB2PHYCFG 寄存器读取为 0x00000000,写入无效
原因: PHY 初始化顺序不正确,或 UTMI 480MHz 时钟未启动
解决:
- 确保正确的初始化顺序:
USB2 PHY 初始化 → USBDP PHY 初始化 → DWC3 配置 → xHCI HCRST - 在 xHCI HCRST 之前清除
GUSB2PHYCFG.suspendusb20(bit[6]) - 参考
docs/rockchip/rk3588.md了解完整的依赖关系
症状: PROBE/COMMIT 请求返回 Stall 错误
原因: 控制传输 buffer 布局不正确。libusb 异步控制传输需要:
[8字节setup包] [数据区]
解决: 在 usb-host/src/backend/libusb/endpoint.rs 中使用 temp_buff:
let temp_buff = vec![0u8; 8 + data_len]; // setup + 数据
// OUT 传输复制数据到 buffer[8..]
libusb_fill_control_setup(buffer, ...); // 填充 buffer[0..8]症状: 程序在 ISO 传输时崩溃
原因: libusb_alloc_transfer(0) 没有为 ISO packet descriptors 分配内存
解决: 根据 transfer 类型传递正确的 packet 数量:
let iso_packets = match &transfer.kind {
TransferKind::Isochronous { num_pkgs } => *num_pkgs as i32,
_ => 0,
};
let trans_ptr = unsafe { libusb_alloc_transfer(iso_packets) };症状: libusb 无法识别端点,传输失败
原因: 端点地址被截断 (& 0x0F),丢失方向位
解决: 保留完整的端点地址:
// ❌ 错误
address: ep_desc.bEndpointAddress & 0x0F
// ✅ 正确
address: ep_desc.bEndpointAddress