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驅動程序。