linux 驱动 --- USB device

USB控制器可以呈现出两种不同的状态。USB控制器作为Host时,称为USB主机控制器,使用USB主机控制器驱动。USB控制器作为Device时,称为USB设备控制器,使用UDC(usb device controller)驱动。本节只分析USB控制器作为Device时的驱动框架。

USB控制器作为Device时,驱动框架可分为5层

最上层的是Gadget Function驱动,代表了具体设备的驱动,如大容量存储设备驱动(U盘、移动硬盘等)、通讯类设备驱动(USB串口、USB虚拟网卡等)、UAC驱动(USB麦克风、USB声卡等USB音频类设备)。

接下来是Gadget Funcation API层,该层是一个抽象层,向上和向下提供统一的API,屏蔽了差异,提高了驱动的兼容性。

Composite层是一个可选的中间层,可通过一种配置或多种配置高效的支持多种功能的设备,简化了USB复合设备驱动的开发。目前最流行的是使用基于Composite和configfs实现的USB gadget configfs,可在用户空间灵活的配置USB设备。

UDC驱动直接访问硬件,控制USB设备与USB主机之间的通信。

USB设备控制器通过USB线缆连接USB主机控制器,负责USB数据的发送和接收。

Gadget Function驱动(自己实现)

Linux内核的USB Gadget Function驱动都在drivers/usb/gadget/function/目录下,有:

  通讯设备类(Communication Device Class)驱动(f_acm.c、f_ecm、f_serial.c等)

  USB音频设备类驱动(f_uac1.c、f_uac2.c、u_audio.c)

  大容量存储设备驱动(f_mass_storage.c)

  USB视频设备类驱动(f_uvc.c)

Gadget Function驱动的入口使用usb_function_driver数据结构描述,驱动需要实现alloc_inst和alloc_func函数。alloc_inst创建usb_function_instance数据结构并初始化。alloc_func创建usb_function并初始化,重点是设置里面的回调函数,通常情况下,不直接使用usb_function数据结构,而是嵌入到驱动的数据结构中使用。Composite驱动会通过Gadget Function API回调alloc_inst和alloc_func函数。usb_function描述了Gadget Function驱动,Gadget Function驱动的重点是实现这些回调函数。

回调函数 bind

调用时机:当USB功能(Function)被绑定到某个配置(Configuration)时。

作用:初始化功能驱动,分配资源(如端点、缓冲区),注册USB接口描述符等。

回调函数 setup

用于处理 USB 控制请求(Control Requests)。默认情况下,USB 核心会处理标准描述符请求(如 GET_DESCRIPTOR 设备/配置/字符串描述符,除非函数驱动需要覆盖或补充这些行为),其他请求则会调用 setup,具体为:

  • 请求类型为 标准请求(Standard Requests)且需要函数驱动提供额外信息,比如 HID 的报告描述符(0x22)
  • 请求类型为 类特定请求(Class-Specific Requests)
  • 请求类型为 厂商自定义请求(Vendor-Specific Requests)

Gadget Function API(内核提供)

Gadget Funcation API是一个抽象层,上层的Gadget Function驱动使用Gadget Funcation API注册和注销,Gadget Function驱动需要实现usb_function_driver数据结构并向Gadget Funcation API层注册。下层的Composite驱动使用Gadget Funcation API和Gadget Function驱动匹配。

Gadget Function API的主要API如下:

usb_function_register函数:将注册的usb_function_driver实例挂到func_list链表中。

usb_get_function_instance函数:遍历func_list链表,将参数name和usb_function_driver->name进行对比,若名称一致,则匹配成功,调用usb_function_driver->alloc_inst函数创建usb_function_instance实例,返回usb_function_instance实例的指针。

usb_get_function函数:调用alloc_func函数创建usb_function实例

复合层(自己实现)

USB Composite 层是 Linux USB Gadget 子系统的核心组件之一,主要负责将多个独立的 USB 功能(如串口、存储、音频等)组合成一个复合 USB 设备,并管理其与主机的交互。以下是其核心职责和实现原理的详细说明:

legacy(传统方式,不推荐)

Linux内核中直接使用Composite层的USB gadget legacy驱动大多都在drivers/usb/gadget/legacy/目录下,如USB音频设备驱动文件audio.c,USB虚拟以太网设备驱动文件ether.c,HID设备驱动文件hid.c。legacy驱动可以直接使用内核提供的module_usb_composite_driver宏,方便定义Composite驱动。参数为usb_composite_driver结构体。使用usb_composite_probe注册Composite驱动。使用usb_composite_unregister函数注销Composite驱动。

缺点:

  功能绑定和设备描述符(如 VID/PID、字符串)需在内核模块中硬编码,无法动态修改。

  设备配置在初始化时固定,无法在运行时添加或移除功能。

USB Gadget Configfs(推荐)

Configfs是一种基于ram的文件系统(挂载在 /sys/kernel/config/usb_gadget/),可以在用户空间直接创建内核对象,主要适用于内核对象有众多配置的模块,比如USB复合设备。Linux 3.11版本引入了USB Gadget Configfs。USB Gadget Configfs在drivers/usb/gadget/configfs.c文件中实现。

通过 configfs 配置USB,包含的功能包括:创建设备描述符、创建配置描述符、设置接口描述符在哪个配置描述符下,以下 iap2 和 iap2_ext_acc 属于Gadget Function驱动创建的接口描述符,都绑定到c.1这个配置描述符。

 

posted @ 2025-06-26 16:07  流水灯  阅读(292)  评论(0)    收藏  举报