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通過以下方式匹配設備和驅動:

  1. 設備ID匹配:基於vendor ID和product ID
  2. 接口類匹配:基於接口類別、子類別和協議
  3. 設備類匹配:基於設備類別

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 枚舉步驟
  1. 設備連接檢測:Hub檢測到設備連接
  2. 設備復位:Hub對設備進行復位操作
  3. 地址分配:USB Core為新設備分配唯一地址
  4. 描述符讀取:讀取設備描述符獲取基本信息
  5. 配置選擇:選擇合適的配置
  6. 接口驅動匹配:為每個接口尋找匹配的驅動
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設備驅動開發

  1. 分析設備描述符:使用lsusb -v命令獲取設備詳細信息
  2. 確定驅動類型:根據接口類別或設備ID選擇合適的匹配方式
  3. 實現基本功能:probe、disconnect、urb處理函數
  4. 處理錯誤情況:URB錯誤處理和設備狀態管理
  5. 電源管理:實現suspend和resume函數

5.2 Gadget驅動開發

  1. 選擇開發方式:Legacy方式或ConfigFS方式
  2. 確定功能需求:選擇合適的Function驅動或開發自定義Function
  3. 配置描述符:準備USB描述符信息
  4. 實現回調函數:setup、set_alt、disable等關鍵函數
  5. 測試驗證:使用USB協議分析儀進行驗證

5.3 調試技巧

  1. 啓用調試信息:配置內核USB調試選項
  2. 使用調試工具:usbmon、usbview等工具
  3. 查看系統日誌:dmesg和syslog中的USB相關信息
  4. 分析URB傳輸:使用usbmon捕獲URB傳輸數據
  5. 檢查描述符:驗證USB描述符的正確性

6. 總結

Linux USB驅動架構是一個高度模塊化和分層的系統,通過清晰的接口定義實現了主機和設備模式的統一管理。理解USB協議規範、掌握核心數據結構、熟悉驅動框架是開發高質量USB驅動的關鍵。隨着USB技術的不斷髮展,新的USB標準和功能不斷涌現,開發者需要持續學習和跟進最新的技術趨勢。

USB驅動開發涉及硬件協議、內核編程、設備管理等多個方面,需要開發者具備紮實的理論基礎和豐富的實踐經驗。通過深入理解本文介紹的架構原理和實現機制,開發者可以更好地開發和調試USB驅動程序。