rk3588/kernel-6.1 USB 总线枚举、驱动匹配与数据传输分析

rk3588/kernel-6.1 USB 总线枚举、驱动匹配与数据传输分析

1. USB 子系统整体结构

rk3588/kernel-6.1 中 USB 主机侧代码主要位于:

  • drivers/usb/core/:USB core,总线、枚举、匹配、URB、hub、配置描述符解析;
  • drivers/usb/host/:Host Controller Driver,例如 xHCI/EHCI/OHCI;
  • drivers/usb/dwc3/:Synopsys DWC3 双角色控制器,RK3588 常见 USB3/DRD 控制器基础;
  • drivers/usb/gadget/:USB device/gadget 侧框架;
  • drivers/usb/class/:USB class 驱动;
  • drivers/usb/storage/:U 盘/USB mass storage;
  • drivers/usb/serial/:USB 串口;
  • drivers/usb/typec/drivers/usb/roles/:Type-C 与 dual-role 切换;
  • drivers/phy/rockchip/:Rockchip USB2/USB3/Type-C PHY。

USB core 的 Makefile:

1
2
3
4
usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
usbcore-y += devio.o notify.o generic.o quirks.o devices.o
usbcore-y += phy.o port.o

核心职责:

  • hub.c:端口变化检测、设备复位、地址分配、读取描述符、枚举;
  • config.c:解析配置、接口、端点描述符;
  • driver.c:USB bus 注册、驱动注册、id_table 匹配、probe/disconnect;
  • urb.c:URB 提交前检查和通用入口;
  • hcd.c:URB 到 Host Controller Driver 的桥接;
  • message.c:同步 control/bulk 消息封装;
  • usb.c:USB core 初始化、设备模型、接口辅助函数;
  • endpoint.c / sysfs.c:端点和设备信息导出。

2. USB 主机侧分层模型

USB 主机侧从上到下可分为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
USB 设备功能驱动
例如 usb-storage、cdc-acm、usbhid、usb-skeleton
|
USB Core
枚举、匹配、配置、URB 管理、设备模型
|
HCD 通用层
struct usb_hcd / struct hc_driver
|
Host Controller Driver
xHCI/EHCI/OHCI/UHCI/DWC3 host glue
|
USB 控制器硬件 + PHY
|
USB 外设

对 RK3588 来说,常见主机路径是:

1
2
3
4
5
Rockchip USB PHY / Type-C / role switch
-> DWC3 控制器
-> xHCI platform HCD
-> USB core
-> 具体 USB 设备驱动

drivers/usb/dwc3/core.cdwc3_get_dr_mode()dwc3_set_prtcap()__dwc3_set_mode() 负责 DWC3 host/device/OTG 角色处理。
drivers/usb/host/xhci-plat.c 负责 platform xHCI HCD 创建、DMA mask 设置、寄存器映射和 usb_add_hcd()


3. USB 设备枚举流程

USB 枚举由 hub 负责。无论是 root hub 还是外接 hub,端口状态变化最终都会进入 drivers/usb/core/hub.c

整体流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
端口 connect/change 中断
-> hub_irq()
-> hub_event()
-> hub_port_connect_change()
-> hub_port_connect()
-> usb_alloc_dev()
-> choose_devnum()
-> hub_port_init()
-> usb_new_device()
-> usb_enumerate_device()
-> usb_get_configuration()
-> device_add()
-> driver core 匹配 USB 设备/接口驱动

3.1 端口连接处理:hub_port_connect()

hub_port_connect() 是新设备枚举的主入口之一。

它做的事情:

  1. 如果端口已有旧设备,先 usb_disconnect()
  2. 对端口信号做 debounce;
  3. 分配 struct usb_device
  4. 设置初始状态为 USB_STATE_POWERED
  5. 调用 choose_devnum() 分配 USB 地址编号;
  6. 调用 hub_port_init() 复位设备并读取设备描述符;
  7. 把设备挂到父 hub 的 port_dev->child
  8. 调用 usb_new_device() 继续枚举和注册。

关键路径:

1
2
3
4
5
6
hub_port_connect()
-> usb_alloc_dev()
-> usb_set_device_state(USB_STATE_POWERED)
-> choose_devnum()
-> hub_port_init()
-> usb_new_device()

3.2 地址分配:choose_devnum()

USB 总线上设备地址范围是 1-127。
choose_devnum()usb_bus.devmap 中找空闲地址:

1
2
3
find_next_zero_bit(bus->devmap.devicemap, 128, bus->devnum_next)
-> set_bit(devnum, bus->devmap.devicemap)
-> udev->devnum = devnum

地址释放在 release_devnum() 中完成。

3.3 端口复位和设备描述符读取:hub_port_init()

hub_port_init() 是 USB 枚举中最复杂的阶段。

主要动作:

  1. hub_port_reset() 复位端口,识别设备速度;
  2. 根据速度设置 ep0 max packet 初始值;
  3. 读取设备描述符前 8/64 字节,确认 bMaxPacketSize0
  4. hub_set_address() 发送标准 SET_ADDRESS 请求;
  5. 再读取完整 usb_device_descriptor
  6. 处理 USB2/USB3 速度、quirk、延迟、链路状态等。

这个阶段设备从默认地址 0 切换到内核分配的地址,并进入 USB_STATE_ADDRESS

3.4 读取配置与字符串:usb_enumerate_device()

usb_new_device() 会调用:

1
2
3
4
5
6
7
usb_enumerate_device()
-> usb_get_configuration()
-> usb_cache_string(iProduct)
-> usb_cache_string(iManufacturer)
-> usb_cache_string(iSerialNumber)
-> usb_enumerate_device_otg()
-> usb_detect_interface_quirks()

usb_get_configuration() 会读取并解析:

  • configuration descriptor;
  • interface descriptor;
  • endpoint descriptor;
  • class/vendor-specific descriptor;
  • SuperSpeed companion descriptor。

解析完成后形成内核对象:

1
2
3
4
5
struct usb_device
-> struct usb_host_config[]
-> struct usb_interface[]
-> struct usb_host_interface[]
-> struct usb_host_endpoint[]

3.5 注册到设备模型:device_add()

usb_new_device() 最后调用:

1
device_add(&udev->dev)

此时 USB 设备对 sysfs、udev、driver core 可见。
后续 generic USB 设备驱动通常会选择配置,创建 interface device,再触发接口驱动匹配。


4. 配置、接口和端点

USB 设备结构不是“一个设备只对应一个驱动”,而是:

1
2
3
4
5
6
7
8
9
Device
Configuration
Interface 0
Altsetting 0
Endpoint 1 IN
Endpoint 2 OUT
Interface 1
Altsetting 0
Endpoint 3 Interrupt IN

Linux USB 驱动多数绑定在 struct usb_interface 上,而不是整个 struct usb_device 上。

例如复合设备:

  • 一个 USB 声卡可能有 audio control interface 和 audio streaming interface;
  • 一个 4G 模块可能同时暴露 serial、network、diagnostic interface;
  • 一个 USB 摄像头可能有 video control 和 video streaming interface。

每个 interface 可以匹配不同驱动。

关键结构在 include/linux/usb.h

  • struct usb_device
  • struct usb_interface
  • struct usb_host_interface
  • struct usb_host_endpoint
  • struct usb_driver
  • struct urb

5. USB 驱动注册

USB 接口驱动通过 struct usb_driver 描述:

1
2
3
4
5
6
7
8
static struct usb_driver my_usb_driver = {
.name = "my_usb",
.probe = my_probe,
.disconnect = my_disconnect,
.id_table = my_table,
};

module_usb_driver(my_usb_driver);

module_usb_driver() 最终调用:

1
2
usb_register_driver()
-> driver_register(&new_driver->drvwrap.driver)

usb_register_driver() 会设置:

1
2
3
new_driver->drvwrap.driver.bus = &usb_bus_type
new_driver->drvwrap.driver.probe = usb_probe_interface
new_driver->drvwrap.driver.remove = usb_unbind_interface

也就是说,驱动真正注册到 Linux driver core,挂在 usb_bus_type 总线上。


6. USB 驱动匹配机制

6.1 id_table

USB 驱动通过 struct usb_device_id 表声明支持的设备或接口。

常见宏:

1
2
3
USB_DEVICE(vendor, product)
USB_DEVICE_INFO(dev_class, dev_subclass, dev_protocol)
USB_INTERFACE_INFO(intf_class, intf_subclass, intf_protocol)

示例:drivers/usb/usb-skeleton.c

1
2
3
4
5
static const struct usb_device_id skel_table[] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ }
};
MODULE_DEVICE_TABLE(usb, skel_table);

MODULE_DEVICE_TABLE(usb, ...) 会导出模块别名,支持热插拔自动加载模块。

6.2 匹配入口:usb_device_match()

drivers/usb/core/driver.cusb_device_match() 是 USB bus 的 .match 回调。

它区分两类对象:

  1. struct usb_device:匹配 usb_device_driver
  2. struct usb_interface:匹配普通 usb_driver

接口驱动匹配路径:

1
2
3
4
usb_device_match()
-> is_usb_interface(dev)
-> usb_match_id(intf, usb_drv->id_table)
-> usb_match_dynamic_id()

usb_match_id() 会遍历驱动的 id_table,调用 usb_match_one_id() 对比:

  • idVendor/idProduct;
  • bDeviceClass/bDeviceSubClass/bDeviceProtocol;
  • bInterfaceClass/bInterfaceSubClass/bInterfaceProtocol;
  • product revision 范围;
  • match_flags。

6.3 probe 调用:usb_probe_interface()

匹配成功后,driver core 调用 usb_probe_interface()

它做的事情:

  1. 检查设备和 interface 是否 authorized;
  2. 再次用动态 ID 或 id_table 找匹配项;
  3. runtime PM 唤醒设备;
  4. 设置 interface 状态为 USB_INTERFACE_BINDING
  5. 处理 autosuspend、LPM、altsetting;
  6. 调用具体驱动的 driver->probe(intf, id)
  7. 成功后设置为 USB_INTERFACE_BOUND

核心流程:

1
2
3
4
5
6
usb_probe_interface()
-> usb_match_dynamic_id()
-> usb_match_id()
-> usb_autoresume_device()
-> driver->probe(intf, id)
-> USB_INTERFACE_BOUND

驱动自己的 probe() 通常会:

  • 分配私有结构;
  • 获取 usb_deviceusb_interface
  • 解析 endpoint;
  • 分配 URB 和 buffer;
  • 注册字符设备、input 设备、netdev、scsi host 等上层对象;
  • usb_set_intfdata() 保存私有数据。

7. usb-skeleton.c 驱动示例

drivers/usb/usb-skeleton.c 是 USB 字符设备驱动模板。

它展示了完整接口驱动写法:

  1. 声明 usb_device_id
1
2
3
4
static const struct usb_device_id skel_table[] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ }
};
  1. probe() 中查找 bulk endpoint;
  2. 分配 bulk in URB 和 buffer;
  3. 注册 USB 字符设备;
  4. read() 中提交 bulk in URB;
  5. write() 中提交 bulk out URB;
  6. disconnect() 中 kill URB、注销设备、处理并发关闭。

读路径:

1
2
3
4
5
6
7
8
userspace read()
-> skel_read()
-> skel_do_read_io()
-> usb_fill_bulk_urb()
-> usb_submit_urb()
-> skel_read_bulk_callback()
-> wake_up_interruptible()
-> copy_to_user()

写路径:

1
2
3
4
5
6
7
8
9
userspace write()
-> skel_write()
-> usb_alloc_urb()
-> usb_alloc_coherent()
-> usb_fill_bulk_urb()
-> usb_anchor_urb()
-> usb_submit_urb()
-> skel_write_bulk_callback()
-> usb_free_coherent()

8. USB 数据传输类型

USB 有四种传输类型:

类型 用途 Linux 常用接口
Control 枚举、标准请求、配置、少量控制命令 usb_control_msg() / control URB
Bulk 大量可靠数据,吞吐优先 usb_bulk_msg() / bulk URB
Interrupt 小数据、周期轮询、低延迟 interrupt URB
Isochronous 音视频实时流,带宽保证,不重传 isoc URB

端点 0 永远是 control endpoint。
其他 endpoint 来自配置描述符和接口 altsetting。


9. URB 数据传输模型

Linux USB 数据传输核心对象是 struct urb(USB Request Block)。

异步传输基本流程:

1
2
3
4
5
6
7
8
usb_alloc_urb()
-> usb_fill_bulk_urb() / usb_fill_control_urb() / usb_fill_int_urb()
-> usb_submit_urb()
-> HCD 排队到硬件
-> 设备传输完成
-> HCD 中断处理
-> usb_hcd_giveback_urb()
-> urb->complete()

URB 关键字段:

  • dev:目标 usb_device
  • pipe:端点号、方向、传输类型;
  • transfer_buffer:数据 buffer;
  • transfer_buffer_length:请求长度;
  • actual_length:实际传输长度;
  • setup_packet:control 传输 setup 包;
  • complete:完成回调;
  • context:驱动私有上下文;
  • status:完成状态;
  • interval:interrupt/isoc 周期;
  • iso_frame_desc[]:isoc 分包描述。

10. usb_submit_urb() 到 HCD 的路径

drivers/usb/core/urb.cusb_submit_urb() 做通用检查:

  1. URB 和 complete 回调不能为空;
  2. 设备状态必须有效;
  3. 通过 pipe 找 endpoint;
  4. 检查 control setup packet;
  5. 检查 endpoint max packet;
  6. 检查 isoc packet 长度;
  7. 检查 SG 约束;
  8. 修正 interrupt/isoc interval;
  9. 调用 usb_hcd_submit_urb()

路径:

1
2
3
4
usb_submit_urb()
-> usb_pipe_endpoint()
-> endpoint/type/length/interval 检查
-> usb_hcd_submit_urb()

drivers/usb/core/hcd.cusb_hcd_submit_urb()

1
2
3
4
5
usb_hcd_submit_urb()
-> usb_get_urb()
-> usbmon_urb_submit()
-> map_urb_for_dma()
-> hcd->driver->urb_enqueue()

如果是 root hub,则走 rh_urb_enqueue() 模拟 root hub 响应。
普通设备则映射 DMA,并调用具体 HCD 的 urb_enqueue()


11. xHCI 如何传输 URB

RK3588 主机侧常见是 xHCI。
include/linux/usb/hcd.hstruct hc_driver 定义 HCD 操作:

1
2
3
4
5
int (*urb_enqueue)(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
int (*urb_dequeue)(struct usb_hcd *hcd, struct urb *urb, int status);
void (*endpoint_disable)(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
int (*address_device)(struct usb_hcd *hcd, struct usb_device *udev, unsigned int timeout_ms);
int (*add_endpoint)(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);

drivers/usb/host/xhci.cxhci_hc_driver

1
2
3
4
5
6
7
.map_urb_for_dma = xhci_map_urb_for_dma
.unmap_urb_for_dma = xhci_unmap_urb_for_dma
.urb_enqueue = xhci_urb_enqueue
.urb_dequeue = xhci_urb_dequeue
.address_device = xhci_address_device
.add_endpoint = xhci_add_endpoint
.check_bandwidth = xhci_check_bandwidth

xhci_urb_enqueue() 会根据 endpoint 类型进入不同队列函数:

1
2
3
4
control      -> xhci_queue_ctrl_tx()
bulk -> xhci_queue_bulk_tx() / SG
interrupt -> xhci_queue_intr_tx()
isochronous -> xhci_queue_isoc_tx_prepare()

xHCI 硬件用 TRB(Transfer Request Block)描述传输:

1
2
3
4
5
6
7
8
9
10
URB
-> xHCI TD
-> one or more TRB
-> endpoint transfer ring
-> doorbell
-> hardware DMA
-> event ring completion
-> xhci_giveback_urb_in_irq()
-> usb_hcd_giveback_urb()
-> urb->complete()

xhci-ring.c 文件开头描述了 xHCI ring 的生产者/消费者模型:

  • software 往 command/endpoint ring 里放 TRB;
  • hardware 消费 endpoint ring;
  • hardware 往 event ring 里写 completion event;
  • software 消费 event ring;
  • doorbell 用来通知 hardware 有新 TRB。

12. 同步传输封装

USB core 提供同步接口,底层仍然使用 URB。

12.1 Control 传输

usb_control_msg() 位于 drivers/usb/core/message.c

流程:

1
2
3
4
5
6
7
8
9
usb_control_msg()
-> 分配 usb_ctrlrequest
-> usb_internal_control_msg()
-> usb_alloc_urb()
-> usb_fill_control_urb()
-> usb_start_wait_urb()
-> usb_submit_urb()
-> wait_for_completion_timeout()
-> usb_kill_urb() on timeout

control 传输常用于:

  • GET_DESCRIPTOR
  • SET_ADDRESS
  • SET_CONFIGURATION
  • GET_STATUS
  • CLEAR_FEATURE
  • class/vendor command。

USB 枚举本身大量使用 control transfer。

12.2 Bulk 同步传输

usb_bulk_msg() 同样位于 message.c

流程:

1
2
3
4
usb_bulk_msg()
-> usb_alloc_urb()
-> usb_fill_bulk_urb() 或 usb_fill_int_urb()
-> usb_start_wait_urb()

适合简单、低并发场景。
高性能驱动更常使用异步 URB 队列保持吞吐。


13. USB DMA 与 buffer

USB 主机控制器一般通过 DMA 访问 URB buffer。
驱动可以用普通 buffer,让 USB core/HCD 自动 DMA map:

1
2
3
buf = kmalloc(size, GFP_KERNEL);
usb_fill_bulk_urb(urb, udev, pipe, buf, size, complete, ctx);
usb_submit_urb(urb, GFP_KERNEL);

也可以使用 coherent buffer 并设置 URB_NO_TRANSFER_DMA_MAP

1
2
3
4
buf = usb_alloc_coherent(udev, size, GFP_KERNEL, &dma);
urb->transfer_buffer = buf;
urb->transfer_dma = dma;
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

usb-skeleton.c 的写路径使用了 usb_alloc_coherent(),减少反复 map/unmap 成本。

注意:

  • completion 回调可能在软中断上下文执行;
  • callback 中不能做长时间睡眠操作;
  • disconnect 中必须 usb_kill_urb()usb_kill_anchored_urbs()
  • 已提交 URB 的 buffer 在 complete 前不能释放;
  • usb_anchor 常用于批量管理多个未完成 URB。

14. 断开、解绑与错误处理

设备拔出时路径:

1
2
3
4
5
6
7
8
9
hub 发现 disconnect
-> usb_disconnect()
-> usb_set_device_state(USB_STATE_NOTATTACHED)
-> hub_disconnect_children()
-> usb_disable_device()
-> device_del()
-> driver core remove
-> usb_unbind_interface()
-> driver->disconnect()

usb_unbind_interface() 会:

  • 设置 interface 为 USB_INTERFACE_UNBINDING
  • 终止接口上的 URB;
  • 调用驱动 disconnect()
  • 禁用 endpoint;
  • 清理 runtime PM 状态。

驱动 disconnect() 要特别注意并发:

  • 用户进程可能还持有 file descriptor;
  • read/write 可能正在等待 completion;
  • URB callback 可能正在或即将执行;
  • 需要用 mutex、kref、anchor、waitqueue 保护生命周期。

usb-skeleton.c 使用:

  • kref 管理对象生命周期;
  • io_mutex 防止 disconnect 与 read/write 并发;
  • usb_anchor 管理提交中的 URB;
  • usb_kill_anchored_urbs() 停止所有写请求。

15. RK3588 平台相关点

RK3588 USB 主机侧通常涉及:

  1. DWC3 控制器

    • drivers/usb/dwc3/core.c
    • 支持 host/device/OTG/DRD;
    • 通过 dr_mode、role switch、Type-C 状态决定角色;
    • host 模式下创建 xHCI 子设备。
  2. xHCI platform HCD

    • drivers/usb/host/xhci-plat.c
    • 设置 DMA mask;
    • 创建 usb_hcd
    • 映射寄存器;
    • 注册 USB2 roothub 和 USB3 roothub;
    • 调用 usb_add_hcd() 后 USB core 开始管理 root hub。
  3. Rockchip PHY

    • drivers/phy/rockchip/phy-rockchip-inno-usb2.c
    • drivers/phy/rockchip/phy-rockchip-inno-usb3.c
    • drivers/phy/rockchip/phy-rockchip-typec.c
    • drivers/phy/rockchip/phy-rockchip-usbdp.c
    • 负责 USB2/USB3 物理层、Type-C/DP combo PHY 等。
  4. Type-C / role switch

    • drivers/usb/typec/
    • drivers/usb/roles/
    • 决定 USB-C 口是 host 还是 device。

因此,RK3588 上“插入 U 盘并枚举”的大致链路是:

1
2
3
4
5
6
7
8
9
10
11
Type-C/USB PHY 检测连接
-> DWC3 进入 host role
-> xHCI HCD 管理 root hub
-> hub.c 发现 port connect
-> hub_port_connect()
-> hub_port_init()
-> usb_new_device()
-> 读取 U 盘描述符
-> interface 匹配 usb-storage
-> usb-storage 提交 bulk URB
-> xHCI 转成 TRB,通过 DMA 传输数据

16. USB 数据传输示例:Bulk 读写

16.1 Bulk IN

设备到主机:

1
2
3
4
5
6
usb_fill_bulk_urb(urb, udev,
usb_rcvbulkpipe(udev, bulk_in_ep),
buf, len,
complete, ctx);

ret = usb_submit_urb(urb, GFP_KERNEL);

完成后:

1
2
3
4
complete callback
-> urb->status
-> urb->actual_length
-> 处理 buf 中的数据

16.2 Bulk OUT

主机到设备:

1
2
3
4
5
6
usb_fill_bulk_urb(urb, udev,
usb_sndbulkpipe(udev, bulk_out_ep),
buf, len,
complete, ctx);

ret = usb_submit_urb(urb, GFP_KERNEL);

高吞吐场景通常同时提交多个 URB,避免 endpoint 队列空闲。


17. USB 调试方法

常用日志:

1
2
3
4
dmesg | grep -i usb
dmesg | grep -i xhci
dmesg | grep -i dwc3
dmesg | grep -i phy

常用 sysfs:

1
2
3
4
/sys/bus/usb/devices/
/sys/bus/usb/drivers/
/sys/kernel/debug/usb/devices
/sys/kernel/debug/usb/usbmon/

常用工具:

  • lsusb
  • lsusb -t
  • lsusb -v
  • usbmon
  • trace-cmd / ftrace

重要 trace/debug 方向:

  • 枚举失败:看 hub.c 日志、device descriptor readSET_ADDRESS、供电、PHY;
  • 匹配失败:看 idVendor/idProduct、interface class、MODULE_DEVICE_TABLE
  • 数据失败:看 URB status、endpoint halt、短包、timeout;
  • 高速不稳定:看 PHY、线缆、Type-C、供电、LPM、autosuspend;
  • 吞吐不足:看 URB 队列深度、bulk max packet、xHCI event、DMA 映射。

18. 常见问题

  1. 设备能枚举但驱动不 probe

    • id_table 不匹配;
    • 驱动匹配的是 interface class,但设备是 vendor-specific;
    • 模块没有导出 MODULE_DEVICE_TABLE(usb, ...)
    • interface 已被其他驱动绑定。
  2. 读取 device descriptor 失败

    • PHY/供电/线缆问题;
    • 端口 reset 失败;
    • 设备 firmware 异常;
    • low/full/high/super speed 协商异常。
  3. bulk 传输超时

    • endpoint 地址或方向错误;
    • 设备没有准备好;
    • 没有处理 stall,需要 usb_clear_halt()
    • disconnect 与 I/O 并发。
  4. callback 后数据长度不对

    • 检查 urb->actual_length
    • IN 方向可能短包结束;
    • OUT 方向可能需要 URB_ZERO_PACKET
    • isoc 要逐个检查 iso_frame_desc[]
  5. 拔出设备后崩溃

    • URB buffer 提前释放;
    • callback 访问已释放私有结构;
    • disconnect 没有 kill URB;
    • file_operations 没有用 kref/mutex 保护。

19. 总结

USB 枚举、匹配和传输可以概括为三条主线:

  1. 枚举主线
1
2
3
4
5
6
hub 端口变化
-> reset
-> SET_ADDRESS
-> GET_DESCRIPTOR
-> GET_CONFIGURATION
-> device_add
  1. 驱动匹配主线
1
2
3
4
5
6
usb_register_driver()
-> usb_bus_type
-> usb_device_match()
-> usb_match_id()
-> usb_probe_interface()
-> driver->probe()
  1. 数据传输主线
1
2
3
4
5
6
7
8
9
driver 构造 URB
-> usb_submit_urb()
-> usb_hcd_submit_urb()
-> hcd->urb_enqueue()
-> xHCI TRB/ring/doorbell
-> hardware DMA
-> event ring
-> usb_hcd_giveback_urb()
-> urb->complete()

一句话概括:
USB core 负责发现设备、解析描述符并按 usb_device_id 绑定 interface 驱动;真正的数据收发由驱动提交 URB,USB core/HCD/xHCI 把 URB 转成硬件传输描述符并在完成后回调驱动。

文章互动

阅读 --

留言

0 条留言

正在加载留言…