歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux下的USB總線驅動

一.USB理論

1.      USB概念概述

USB1.0版本速度1.5Mbps(低速USB) USB1.1版本速度12Mbps(全速USB)  USB2.0版本速度480Mbps(高速USB)

USB驅動由USB主機控制器驅動和USB設備驅動組成。USB主機控制器是用來控制USB設備和CPU之間通信的,USB主機控制器驅動主要用來驅動芯片上的主機控制器硬件。USB設備驅動主要是指具體的例如USB鼠標,USB鍵盤燈設備的驅動。

一般的通用的Linux設備,如U盤、USB鼠標、USB鍵盤,都不需要工程師再編寫驅動,需要編寫的是特定廠商、特定芯片的驅動,而且往往也可以參考內核中已經提供的驅動模板。USB只是一個總線,真正的USB設備驅動的主體工作仍然是USB設備本身所屬類型的驅動,如字符設備、tty設備、塊設備、輸入設備等。

2.      USB主機控制器

USB主機控制器屬於南橋芯片的一部分,通過PCI總線和處理器通信。USB主機控制器分為UHCI(英特爾提出)、OHCI(康柏和微軟提出)、 EHCI。其中OHCI驅動程序用來為非PC系統上以及帶有SiS和ALi芯片組的PC主辦上的USB芯片提供支持。UHCI驅動程序多用來為大多數其他PC主板(包括Intel和Via)上的USB芯片提供支持。ENCI兼容OHCI和UHCI。UHCI的硬件線路比OHCI簡單,所以成本較低,但需要較復雜的驅動程序,CPU負荷稍重。主機控制器驅動程序完成的功能主要包括:解析和維護URB,根據不同的端點進行分類緩存URB;負責不同USB傳輸類型的調度工作;負責USB數據的實際傳輸工作;實現虛擬跟HUB的功能。

3.      USB設備與USB驅動的匹配

USB設備與USB驅動怎麼匹配的呢?實際上USB設備中有一個模塊叫固件,是固件信息和USB驅動進行的匹配。固件是固化在集成電路內部的程序代碼,USB固件中包含了USB設備的出廠信息,標識該設備的廠商ID、產品ID、主版本號和次版本號等。另外固件中還包含一組程序,這組程序主要完成USB協議的處理和設備的讀寫操作。USB設備固件和USB驅動之間通信的規范是通過USB協議來完成的。

4.      USB設備的邏輯結構和端點的傳輸方式

USB設備的邏輯結構包括設備、配置、接口和端點,分別用usb_device、usb_host_config、 usb_interface、usb_host_endpoint表示。

端點的傳輸方式包括控制傳輸、中斷傳輸、批量傳輸、等時傳輸。

控制傳輸主要用於向設備發送配置信息、獲取設備信息、發送命令道設備,或者獲取設備的狀態報告。控制傳輸一般發送的數據量較小,當USB設備插入時,USB核心使用端點0對設備進行配置,另外,端口0與其他端點不一樣,端點0可以雙向傳輸。

中斷傳輸就是中斷端點以一個固定的速度來傳輸較少的數據,USB鍵盤和鼠標就是使用這個傳輸方式。這裡說的中斷和硬件上下文中的中斷不一樣,它不是設備主動發送一個中斷請求,而是主機控制器在保證不大於某個時間間隔內安排一次傳輸。中斷傳輸對時間要求比較嚴格,所以可以用中斷傳輸來不斷地檢測某個設備,當條件滿足後再使用批量傳輸傳輸大量的數據。

批量傳輸通常用在數據量大、對數據實時性要求不高的場合,例如USB打印機、掃描儀、大容量存儲設備、U盤等。

等時傳輸同樣可以傳輸大批量數據,但是對數據是否到達沒有保證,它對實時性的要求很高,例如音頻、視頻等設備。

5.      USB的URB請求塊

USB請求塊(USB request block,urb)是USB主機控制器和設備通信的主要數據結構,主機和設備之間通過urb進行數據傳輸。當主機控制器需要與設備交互時,只需要填充一個urb結構,然後將其提交給USB核心,由USB核心負責對其進行處理。

URB處理流程:

Step1:創建一個URB結構體 usb_alloc_urb()

Step2:初始化,被安排一個特定的USB設備的特定端點。fill_int/bulk/control_urb()

Step3:被USB設備驅動提交給USB核心usb_submit_urb(),注意GPF_ATOMIC,GPF_NOIO,GPF_KERNEL的使用區別。

Step4:提交由USB核心指定的USB主機控制器驅動,被主機控制器驅動處理,進行一次到USB設備的傳輸,該過程由USB核心和主機控制器完成,不受USB設備驅動控制

Step5:當urb完成,USB主機控制器驅動通知USB設備驅動。

簡單的批量與控制URB

有時候USB驅動程序只是從USB設備上接收或發送一些簡單的數據,這時候可以使用usb_bulk/control_msg()完成,這兩個函數是同步的,因此不能在中斷上下文和持有自旋鎖的情況下使用。

6.      USB的枚舉過程

內核輔助線程khubd用來監視與該集線器連接的所有端口,通常情況下,該線程處於休眠狀態,當集線器驅動程序檢測到USB端口狀態變化後,該內核線程立馬喚醒。

USB的枚舉過程:USB的枚舉過程是熱插拔USB設備的起始步驟,該過程中,主機控制器獲取設備的相關信息並配置好設備,集線器驅動程序負責該枚舉過程。枚舉過程主要分如下幾步:

Step1:根集線器報告插入設備導致的端口電流變化,集線器驅動程序檢測到這一狀態變化後,喚醒khubd線程。

Step2:khubd識別出電流變化的那個端口

Step3:khubd通過給控制端點0發送控制URB來實現從1-127中選出一個數作為插入設備的批量端點

Step4:khubd利用端口0使用的控制URB從插入的設備那裡獲得設備描述符,然後獲得配置描述符,並選擇一個合適的。

Step5:khubd請求USB核心把對應的客戶驅動程序和該USB設備掛鉤。

Copyright © Linux教程網 All Rights Reserved