【Linux驱动开发】Linux USB驱动架构详解
Linux USB驱动架构详解
概述
Linux USB子系统是Linux内核中最复杂的子系统之一,它支持USB主机模式、设备模式和OTG模式。USB驱动架构分为三个主要部分:USB主机驱动、USB设备驱动和USB Gadget驱动。本文将深入分析这三个部分的工作原理和实现机制。
1. USB主机驱动架构
1.1 USB主机控制器类型
USB主机控制器(Host Controller Device, HCD)是USB主机侧的核心组件,负责管理USB总线上的所有通信。Linux内核支持多种类型的USB主机控制器:
1.1.1 不同类型的HCD
- OHCI (Open Host Controller Interface):USB 1.1标准,支持低速(1.5Mbps)和全速(12Mbps)设备
- UHCI (Universal Host Controller Interface):Intel提出的USB 1.1标准,同样支持低速和全速设备
- EHCI (Enhanced Host Controller Interface):USB 2.0标准,支持高速(480Mbps)设备
- xHCI (eXtensible Host Controller Interface):USB 3.0及以上标准,支持超高速(5Gbps)设备
1.1.2 HCD驱动架构
USB主机驱动采用分层架构:
USB设备驱动层
↓
USB核心层 (USB Core)
↓
主机控制器驱动层 (HCD)
↓
硬件层
1.2 USB核心层(USB Core)
USB Core是USB子系统的核心,提供以下功能:
1.2.1 设备枚举和管理
- 检测设备连接和断开
- 读取设备描述符信息
- 分配设备地址
- 配置设备参数
1.2.2 URB管理
USB Request Block (URB)是USB通信的基本单元:
struct urb {struct kref kref; /* 引用计数 */void *hcpriv; /* HCD私有数据 */struct list_head urb_list; /* URB链表 */struct usb_device *dev; /* 目标设备 */unsigned int pipe; /* 管道信息 */int status; /* URB状态 */unsigned int transfer_flags; /* 传输标志 */void *transfer_buffer; /* 传输缓冲区 */dma_addr_t transfer_dma; /* DMA地址 */int transfer_buffer_length; /* 缓冲区长度 */int actual_length; /* 实际传输长度 */unsigned char *setup_packet; /* 控制传输设置包 */int start_frame; /* 等时传输起始帧 */int number_of_packets; /* 等时传输包数量 */int interval; /* 中断传输间隔 */int error_count; /* 错误计数 */void *context; /* 完成回调上下文 */usb_complete_t complete; /* 完成回调函数 *//* ... 其他字段 */
};
1.2.3 驱动匹配机制
USB Core通过以下方式匹配设备和驱动:
- 设备ID匹配:基于vendor ID和product ID
- 接口类匹配:基于接口类别、子类别和协议
- 设备类匹配:基于设备类别
1.3 HCD驱动实现
以xHCI驱动为例,HCD驱动需要实现以下关键函数:
static const struct hc_driver xhci_hc_driver = {.description = "xhci-hcd",.product_desc = "xHCI Host Controller",.hcd_priv_size = sizeof(struct xhci_hcd),/* 基本生命周期操作 */.reset = xhci_reset,.start = xhci_run,.stop = xhci_stop,.shutdown = xhci_shutdown,/* URB管理 */.urb_enqueue = xhci_urb_enqueue,.urb_dequeue = xhci_urb_dequeue,/* 端点管理 */.endpoint_disable = xhci_endpoint_disable,.endpoint_reset = xhci_endpoint_reset,/* 根Hub管理 */.hub_status_data = xhci_hub_status_data,.hub_control = xhci_hub_control,/* 设备管理 */.alloc_dev = xhci_alloc_dev,.free_dev = xhci_free_dev,/* 其他必要函数 */.get_frame_number = xhci_get_frame_number,.irq = xhci_irq,
};
2. USB设备驱动模型
2.1 USB设备层次结构
USB设备采用树形层次结构:
USB设备 (Device)
├── 配置 (Configuration)
│ ├── 接口 (Interface)
│ │ ├── 端点 (Endpoint)
│ │ ├── 端点 (Endpoint)
│ │ └── ...
│ ├── 接口 (Interface)
│ └── ...
├── 配置 (Configuration)
└── ...
2.1.1 设备描述符
struct usb_device_descriptor {__u8 bLength; /* 描述符长度 */__u8 bDescriptorType; /* 描述符类型 */__le16 bcdUSB; /* USB版本号 */__u8 bDeviceClass; /* 设备类别 */__u8 bDeviceSubClass; /* 设备子类别 */__u8 bDeviceProtocol; /* 设备协议 */__u8 bMaxPacketSize0; /* 端点0最大包大小 */__le16 idVendor; /* 厂商ID */__le16 idProduct; /* 产品ID */__le16 bcdDevice; /* 设备版本号 */__u8 iManufacturer; /* 厂商字符串索引 */__u8 iProduct; /* 产品字符串索引 */__u8 iSerialNumber; /* 序列号字符串索引 */__u8 bNumConfigurations; /* 配置数量 */
} __attribute__ ((packed));
2.1.2 接口描述符
struct usb_interface_descriptor {__u8 bLength; /* 描述符长度 */__u8 bDescriptorType; /* 描述符类型 */__u8 bInterfaceNumber; /* 接口编号 */__u8 bAlternateSetting; /* 备用设置 */__u8 bNumEndpoints; /* 端点数量 */__u8 bInterfaceClass; /* 接口类别 */__u8 bInterfaceSubClass; /* 接口子类别 */__u8 bInterfaceProtocol; /* 接口协议 */__u8 iInterface; /* 接口字符串索引 */
} __attribute__ ((packed));
2.1.3 端点描述符
struct usb_endpoint_descriptor {__u8 bLength; /* 描述符长度 */__u8 bDescriptorType; /* 描述符类型 */__u8 bEndpointAddress; /* 端点地址 */__u8 bmAttributes; /* 端点属性 */__le16 wMaxPacketSize; /* 最大包大小 */__u8 bInterval; /* 轮询间隔 *//* USB 3.0扩展字段 */__u8 bRefresh;__u8 bSynchAddress;
} __attribute__ ((packed));
2.2 USB驱动注册和匹配
2.2.1 USB驱动结构
struct usb_driver {const char *name; /* 驱动名称 *//* 当设备匹配成功时调用 */int (*probe)(struct usb_interface *intf,const struct usb_device_id *id);/* 设备断开时调用 */void (*disconnect)(struct usb_interface *intf);/* 设备挂起时调用 */int (*suspend)(struct usb_interface *intf, pm_message_t message);/* 设备恢复时调用 */int (*resume)(struct usb_interface *intf);/* 设备重置前调用 */int (*pre_reset)(struct usb_interface *intf);/* 设备重置后调用 */int (*post_reset)(struct usb_interface *intf);/* 设备ID表 */const struct usb_device_id *id_table;/* 其他字段 */struct usbdrv_wrap drvwrap;unsigned int no_dynamic_id:1;unsigned int supports_autosuspend:1;unsigned int disable_hub_initiated_lpm:1;/* 设备组 */const struct attribute_group **dev_groups;
};
2.2.2 设备ID表
struct usb_device_id {__u16 match_flags; /* 匹配标志 */__u16 idVendor; /* 厂商ID */__u16 idProduct; /* 产品ID */__u16 bcdDevice_lo; /* 设备版本号下限 */__u16 bcdDevice_hi; /* 设备版本号上限 */__u8 bDeviceClass; /* 设备类别 */__u8 bDeviceSubClass; /* 设备子类别 */__u8 bDeviceProtocol; /* 设备协议 */__u8 bInterfaceClass; /* 接口类别 */__u8 bInterfaceSubClass; /* 接口子类别 */__u8 bInterfaceProtocol; /* 接口协议 */__u8 bInterfaceNumber; /* 接口编号 */kernel_ulong_t driver_info; /* 驱动私有信息 */
};
2.3 USB设备枚举过程
USB设备枚举是USB Core自动完成的复杂过程:
2.3.1 枚举步骤
- 设备连接检测:Hub检测到设备连接
- 设备复位:Hub对设备进行复位操作
- 地址分配:USB Core为新设备分配唯一地址
- 描述符读取:读取设备描述符获取基本信息
- 配置选择:选择合适的配置
- 接口驱动匹配:为每个接口寻找匹配的驱动
2.3.2 枚举过程中的关键函数
/* 设备添加 */
int usb_new_device(struct usb_device *udev);/* 设备配置 */
int usb_configure_device(struct usb_device *udev);/* 接口驱动匹配 */
int usb_probe_interface(struct usb_interface *intf);
3. USB Gadget驱动框架
3.1 Gadget驱动架构
USB Gadget驱动使Linux系统能够作为USB设备工作,其架构分为多层:
Gadget Function驱动层
↓
Composite层 (可选)
↓
Gadget Function API层
↓
UDC (USB Device Controller)驱动层
↓
硬件层
3.2 UDC驱动
USB Device Controller (UDC)驱动直接控制USB设备控制器硬件:
3.2.1 UDC驱动结构
struct usb_gadget {const struct usb_gadget_ops *ops; /* 操作函数 */struct usb_ep *ep0; /* 端点0 */struct list_head ep_list; /* 端点链表 */enum usb_device_speed speed; /* 当前速度 */enum usb_device_speed max_speed; /* 最大速度 */unsigned int is_dualspeed:1; /* 是否支持双速 */unsigned int is_otg:1; /* 是否支持OTG */unsigned int is_a_peripheral:1; /* 是否为A设备外设 */unsigned int b_hnp_enable:1; /* B设备HNP使能 */unsigned int a_hnp_support:1; /* A设备HNP支持 */unsigned int a_alt_hnp_support:1; /* A设备备用HNP支持 */const char *name; /* 控制器名称 */struct device *dev; /* 设备结构 */
};
3.2.2 Gadget操作函数
struct usb_gadget_ops {int (*get_frame)(struct usb_gadget *gadget);int (*wakeup)(struct usb_gadget *gadget);int (*set_selfpowered)(struct usb_gadget *gadget, int is_selfpowered);int (*vbus_session)(struct usb_gadget *gadget, int is_active);int (*vbus_draw)(struct usb_gadget *gadget, unsigned mA);int (*pullup)(struct usb_gadget *gadget, int is_on);int (*ioctl)(struct usb_gadget *gadget,unsigned code, unsigned long param);
};
3.3 Gadget Function驱动
Gadget Function驱动实现具体的USB设备功能:
3.3.1 Function驱动结构
struct usb_function {const char *name; /* 功能名称 */struct usb_gadget_strings **strings; /* 字符串描述符 */struct usb_descriptor_header **descriptors; /* 描述符 */struct usb_descriptor_header **hs_descriptors; /* 高速描述符 */struct usb_descriptor_header **ss_descriptors; /* 超高速描述符 *//* 配置管理 */int (*bind)(struct usb_configuration *, struct usb_function *);void (*unbind)(struct usb_configuration *, struct usb_function *);/* 接口管理 */int (*set_alt)(struct usb_function *, unsigned interface, unsigned alt);int (*get_alt)(struct usb_function *, unsigned interface);void (*disable)(struct usb_function *);/* USB请求处理 */int (*setup)(struct usb_function *, const struct usb_ctrlrequest *);void (*suspend)(struct usb_function *);void (*resume)(struct usb_function *);/* 其他字段 */struct usb_configuration *config;struct list_head list;struct usb_ep *ep0;struct list_head ep_list;
};
3.3.2 常用Function驱动
- mass_storage:U盘功能
- acm:USB串口功能
- rndis:USB网络功能
- uac:USB音频功能
- uvc:USB视频功能
3.4 Composite框架
Composite框架支持将多个Function组合成一个复合设备:
3.4.1 Composite驱动结构
struct usb_composite_driver {const char *name; /* 驱动名称 */const struct usb_device_descriptor *dev; /* 设备描述符 */struct usb_gadget_strings **strings; /* 字符串描述符 *//* 生命周期管理 */int (*bind)(struct usb_composite_dev *cdev);int (*unbind)(struct usb_composite_dev *cdev);/* 挂起和恢复 */void (*suspend)(struct usb_composite_dev *cdev);void (*resume)(struct usb_composite_dev *cdev);/* USB请求处理 */int (*setup)(struct usb_composite_dev *cdev,const struct usb_ctrlrequest *ctrl);/* 其他字段 */struct usb_gadget_driver gadget_driver;unsigned needs_serial:1;unsigned max_speed:4;
};
3.5 ConfigFS配置接口
ConfigFS提供了用户空间配置Gadget的接口:
3.5.1 ConfigFS使用示例
# 创建Gadget配置
mkdir /sys/kernel/config/usb_gadget/g1
cd /sys/kernel/config/usb_gadget/g1# 设置设备描述符
echo 0x18d1 > idVendor # Google
echo 0x4e11 > idProduct # Nexus 4# 创建配置
mkdir configs/c.1
echo 120 > configs/c.1/MaxPower# 创建功能
mkdir functions/mass_storage.usb0
mkdir functions/acm.usb1# 绑定功能到配置
ln -s functions/mass_storage.usb0 configs/c.1/
ln -s functions/acm.usb1 configs/c.1/# 绑定到UDC
echo "musb-hdrc.0.auto" > UDC
4. 核心数据结构总结
4.1 USB核心数据结构关系
usb_device
├── usb_device_descriptor
├── usb_config
│ ├── usb_configuration
│ └── usb_interface
│ ├── usb_interface_descriptor
│ └── usb_host_endpoint
│ └── usb_endpoint_descriptor
└── usb_host_endpoint (ep0)
4.2 关键数据结构映射
| 内核结构 | USB规范 | 作用 |
|---|---|---|
| usb_device | Device | 表示整个USB设备 |
| usb_interface | Interface | 表示设备的一个功能接口 |
| usb_host_endpoint | Endpoint | 表示数据传输的端点 |
| urb | Transfer | 表示一次USB传输 |
| usb_gadget | Device | Gadget模式下的设备表示 |
| usb_function | Function | Gadget模式下的功能模块 |
4.3 驱动模型对比
| 特性 | 主机模式 | 设备模式(Gadget) |
|---|---|---|
| 控制器驱动 | HCD驱动 | UDC驱动 |
| 设备驱动 | USB设备驱动 | Function驱动 |
| 枚举过程 | 自动枚举 | 手动配置 |
| 复合设备 | 自动识别 | Composite框架 |
| 配置接口 | 内核内部 | ConfigFS |
5. 开发实践建议
5.1 USB设备驱动开发
- 分析设备描述符:使用
lsusb -v命令获取设备详细信息 - 确定驱动类型:根据接口类别或设备ID选择合适的匹配方式
- 实现基本功能:probe、disconnect、urb处理函数
- 处理错误情况:URB错误处理和设备状态管理
- 电源管理:实现suspend和resume函数
5.2 Gadget驱动开发
- 选择开发方式:Legacy方式或ConfigFS方式
- 确定功能需求:选择合适的Function驱动或开发自定义Function
- 配置描述符:准备USB描述符信息
- 实现回调函数:setup、set_alt、disable等关键函数
- 测试验证:使用USB协议分析仪进行验证
5.3 调试技巧
- 启用调试信息:配置内核USB调试选项
- 使用调试工具:usbmon、usbview等工具
- 查看系统日志:dmesg和syslog中的USB相关信息
- 分析URB传输:使用usbmon捕获URB传输数据
- 检查描述符:验证USB描述符的正确性
6. 总结
Linux USB驱动架构是一个高度模块化和分层的系统,通过清晰的接口定义实现了主机和设备模式的统一管理。理解USB协议规范、掌握核心数据结构、熟悉驱动框架是开发高质量USB驱动的关键。随着USB技术的不断发展,新的USB标准和功能不断涌现,开发者需要持续学习和跟进最新的技术趋势。
USB驱动开发涉及硬件协议、内核编程、设备管理等多个方面,需要开发者具备扎实的理论基础和丰富的实践经验。通过深入理解本文介绍的架构原理和实现机制,开发者可以更好地开发和调试USB驱动程序。
