1. 程式人生 > 其它 >Linux USB驅動分析之USB2.0協議分析

Linux USB驅動分析之USB2.0協議分析

一條USB傳輸線分別由地線、電源線、D+和D-四條線構成,D+和D-是差分輸入線,它使用的是3.3V的電壓(與CMOS的5V電平不同),而電源線和地線可向裝置提供5V電壓,最大電流為500mA(可以在程式設計中設定)。
        USB裝置可以直接和HOST通訊,或者通過Hub和Host通訊。一個USB系統中僅有一個USB 主機,裝置包括USB功能裝置和USB HUB,最多支援127個設備。物理連線指的是USB傳輸線。在USB 2.0系統中要求使用遮蔽雙絞線。
1.2、USB HUB
        USB HUB提供了一種低成本、低複雜度的USB介面擴充套件方法。HUB的上行PORT面向HOST,下行PORT面向裝置(HUB或功能裝置)。在下行PORT上,HUB提供了裝置連線檢測和裝置移除檢測的能力,並給各下行PORT供電。HUB可以單獨使能各下行PORT不同PORT可以工作在不同的速度等級(高速/全速/低速)。
        如果USB裝置通過集線器和Host通訊,主機集線器監視著每個埠的訊號電壓,當有新裝置接入時便可覺察。集線器埠的兩根訊號線的每一根都有15kΩ的下拉電阻,而每一個裝置在D+都有一個1.5kΩ的上拉電阻。當用USB線將PC和裝置接通後,裝置的上拉電阻使訊號線的電位升高,因此被主機集線器檢測到。

二、USB資料格式

        USB的重要關鍵字:

        端點(Endpoint):位於USB裝置或主機上的一個數據緩衝區,是USB裝置中可以進行資料收發的最小單元,支援單向或者雙向的資料傳輸,用來存放和傳送USB的各種資料,每一個端點都有惟一的確定地址,有不同的傳輸特性(如輸入端點、輸出端點、配置端點、批量傳輸端點)。裝置支援端點的數量是有限制的,除預設端點外低速裝置最多支援2組端點(2 個輸入,2 個輸出),高速和全速裝置最多支援15組端點。

        幀:時間概念,在USB中,一幀就是1MS,它是一個獨立的單元,包含了一系列匯流排動作,USB將1幀分為好幾份,每一份是一個USB的傳輸動作。

        上行、下行:裝置到主機為上行,主機到裝置為下行。

2.1、USB資料傳輸方法

        資料在USB線裡傳送是由低位到高位傳送的。

        USB採用不歸零取反來傳輸資料,當傳輸線上的差分資料輸入0時就取反,輸入1時就保持原值,為了確保訊號傳送的準確性,當在USB總線上傳送一個包時,傳輸裝置就要進行位插入操作(即在資料流中每連續6個1後就插入一個0),從而強迫NRZI碼發生變化。這些是由專門硬體處理的。

2.2、資料格式

        USB資料是由二進位制數字串構成的,首先數字串構成域(有七種),域再構成包,包再構成事務(IN、OUT、SETUP),事務最後構成傳輸(中斷傳輸、並行傳輸、批量傳輸和控制傳輸)

。下面介紹一下域、包和事務。

2.2.1、域
        域是USB資料最小的單位,由若干位組成(多少位由具體的域決定),域可分為七個型別:

        1、同步域(SYNC)
        所有的USB包都由SYNC開始,高速包的SYNC寬度為32bit,全速/低速包的SYNC段度為8bit。實際接收到的SYNC長度由於USB HUB的關係,可能會小於該值。八位的值固定為0000 0001,用於本地時鐘與輸入同步。

        2、標識域(PID)
        由四位識別符號 + 四位識別符號反碼構成,表明包的型別和格式,這是一個很重要的部分,這裡可以計算出,USB的標識碼有16種。USB2.0使用了十六種標識碼,標識碼的作用是用來說明包的屬性的,標識碼是和包聯絡在一起的,標識碼分別有以下十六種:

        令牌包 :

        0x01:輸出(OUT)啟動一個方向為主機到裝置的傳輸,幷包含了裝置地址和標號。

        0x09:輸入(IN) 啟動一個方向為裝置到主機的傳輸,幷包含了裝置地址和標號。

        0x05:幀起始(SOF)表示一個幀的開始,並且包含了相應的幀號。

        0x0d:設定(SETUP)啟動一個控制傳輸,用於主機對裝置的初始化。

        資料包 :

        0x03:偶資料包(DATA0)。

        0x0b:奇資料包(DATA1)。

        握手包:

        0x02:確認接收到無誤的資料包(ACK)。

        0x0a:無效,接收(傳送)端正在忙而無法接收(傳送)資訊。

        0x0e:錯誤,端點被禁止或不支援控制管道請求。

        特殊包0x0C前導,用於啟動下行埠的低速裝置的資料傳輸。

        3、地址域(ADDR):七位地址,代表了裝置在主機上的地址,地址000 0000被命名為零地址,是任何裝置第一次連線到主機時,在被主機配置、列舉前的預設地址,由此可以知道為什麼一個USB主機只能接127個裝置的原因。

        4、端點域(ENDP),四位,由此可知一個USB裝置端點數量最大為16個。

        5、幀號域(FRAM),11位,每一個幀都有一個特定的幀號,幀號域最大容量0x800,對於同步傳輸有重要意義。

        6、資料域(DATA):長度為0~1023位元組,在不同的傳輸型別中,資料域的長度各不相同,但必須為整數個位元組的長度。

        7、校驗域(CRC):對令牌包和資料包中非PID域進行校驗的一種方法,CRC校驗在通訊中應用很泛,是一種很好的校驗方法,CRC碼的除法是模2運算,不同於10進制中的除法。

2.2.2、包
        USB資料包的格式如下:

        由域構成的包有四種類型,分別是令牌包、資料包、握手包和特殊包,前面三種是重要的包,不同包的域結構不同,介紹如下:         

        1、令牌包

        分為輸入包、輸出包、設定包和幀起始包(注意這裡的輸入包是用於設定輸入命令的,輸出包是用來設定輸出命令的,而不是放資料的)其中輸入包、輸出包和設定包的格式都是一樣的:

                                               SYNC + PID + ADDR + ENDP + CRC5(五位的校驗碼)

        幀起始包的格式:

                                               SYNC + PID + 11位FRAM + CRC5(五位的校驗碼)

        2、資料包

        分為DATA0包和DATA1包,當USB傳送資料的時候,如果一次傳送的資料長度大於相應端點的容量時,就需要把資料包分為好幾個包,分批發送,DATA0包和DATA1包交替傳送,即如果第一個資料包是DATA0,那第二個資料包就是DATA1。但也有例外情況,在同步傳輸中(四類傳輸型別中之一),所有的數據包都是為DATA0,格式如下:

                                                        SYNC + PID + 0~1023位元組 + CRC16

        3、握手包
        結構最為簡單的包,格式如下:

                                                                    SYNC + PID
        握手包包括 ACK、NAK、STALL以及NYET 四種,其中 ACK 表示肯定的應答,成功的資料傳輸。NAK 表示否定的應答,失敗的資料傳輸,要求重新傳輸。STALL表示功能錯誤或端點被設定了STALL屬性。NYET表示尚未準備好,要求等待。

2.2.3、事務

        分別有IN、OUT和SETUP三大事務,每一種事務都由令牌包、資料包、握手包三個階段構成,這裡用階段的意思是因為這些包的傳送是有一定的時間先後順序的,事務的三個階段如下:

        1、令牌包階段:啟動一個輸入、輸出或設定的事務。

        2、資料包階段:按輸入、輸出傳送相應的資料。

        3、握手包階段:返回資料接收情況,在同步傳輸的IN和OUT事務中沒有這個階段,這是比較特殊的。

        事務的三種類型如下(以下按三個階段來說明一個事務):

        1、 IN事務:

        令牌包階段——主機發送一個PID為IN的輸入包給裝置,通知裝置要往主機發送資料;

        資料包階段——裝置根據情況會作出三種反應(要注意:資料包階段也不總是傳送資料的,根據傳輸情況還會提前進入握手包階段)。

        1) 裝置端點正常:裝置往主機裡面發出資料包(DATA0與DATA1交替);

        2) 裝置正在忙:無法往主機發出資料包就傳送NAK無效包,IN事務提前結束,到了下一個IN事務才繼續;

        3) 相應裝置端點被禁止:傳送錯誤包STALL包,事務也就提前結束了,匯流排進入空閒狀態。

        握手包階段——主機正確接收到資料之後就會向裝置傳送ACK包。

        2、 OUT事務:

        令牌包階段——主機發送一個PID為OUT的輸出包給裝置,通知裝置要接收資料;

        資料包階段——比較簡單,就是主機會往裝置送資料,DATA0與DATA1交替

        握手包階段——裝置根據情況會作出三種反應

        1) 裝置端點接收正確,裝置給主機返回ACK,通知主機可以傳送新的資料,如果資料包發生了CRC校驗錯誤,將不返回任何握手資訊;

        2) 裝置正在忙,無法給主機返回ACK,就傳送NAK無效包,通知主機再次傳送資料;

        3) 相應裝置端點被禁止,傳送錯誤包STALL包,事務提前結束,匯流排直接進入空閒狀態。

        3、SETUT事務:

        令牌包階段——主機發送一個PID為SETUP的輸出包給裝置,通知裝置要接收資料;

        資料包階段——比較簡單,就是主機往裝置送資料,注意,這裡只有一個固定為8個位元組的DATA0包,這8個位元組的內容就是標準的USB裝置請求命令,詳見2.4。

        握手包階段——裝置接收到主機的命令資訊後,返回ACK,此後匯流排進入空閒狀態,並準備下一個傳輸(在SETUP事務後通常是一個IN或OUT事務構成的傳輸)。

2.3、標準的USB裝置請求命令

        標準的USB裝置請求命令是用在控制傳輸中的“初始設定步驟”裡的資料包階段(即DATA0,由八個位元組構成)。命令共有11個,大小都是8個位元組,具有相同的結構,由5個欄位構成(欄位是標準請求命令的資料部分),結構如下(括號中的數字表示位元組數,首字母bm,b,w分別表示點陣圖、位元組,雙位元組):

                    bmRequestType(1) + bRequest(1) + wvalue(2) + wIndex(2) + wLength(2)

        各欄位的意義如下:

        1、bmRequestType:D7D6D5D4D3D2D1D0

        D7=0主機到裝置

            =1裝置到主機;

        D6D5=00標準請求命令

            =01 類請求命令

            =10使用者定義的命令    

            =11保留值

        D4D3D2D1D0=00000 接收者為裝置

            =00001 接收者為裝置

            =00010 接收者為端點

            =00011 接收者為其他接收者

            =其他  其他值保留

        2、bRequest:請求命令程式碼,在標準的USB命令中,每一個命令都定義了編號,編號的值就為欄位的值,編號與命令名稱如下(要注意這裡的命令程式碼要與其他欄位結合使用,可以說命令程式碼是標準請求命令程式碼的核心,正是因為這些命令程式碼而決定了11個USB標準請求命令):

        0  GET_STATUS:用來返回特定接收者的狀態;

        1  CLEAR_FEATURE:用來清除或禁止接收者的某些特性;

        2) 3  SET_FEATURE:用來啟用或啟用命令接收者的某些特性;

        5  SET_ADDRESS:用來給裝置分配地址;

        6  GET_DEscriptOR:用於主機獲取裝置的特定描述符;

        7  SET_DEscriptOR:修改裝置中有關的描述符,或者增加新的描述符;

        8  GET_CONFIGURATION:用於主機獲取裝置當前裝置的配置值(注同上面的不同);

        9  SET_CONFIGURATION:用於主機指示裝置採用的要求的配置;

        10  GET_INTERFACE:用於獲取當前某個介面描述符編號;

        11  SET_INTERFACE:用於主機要求裝置用某個描述符來描述介面;

        12 SYNCH_FRAME:用於裝置設定和報告一個端點的同步幀;

       控制傳輸是USB的重心,而這11個命令是控制傳輸的重心,所以這11個命令是重中之重。
2.4、
描述符(Descriptor)

        Descriptor是一個完整的資料結構,可以通過C語言等程式設計實現,並存儲在USB裝置中,用於描述一個USB裝置的所有屬性,USB主機是通過一系列命令來要求裝置傳送這些資訊的。它的作用就是給主機傳遞資訊,從而讓主機知道裝置具有什麼功能、屬於哪一類裝置、要佔用多少頻寬、使用哪類傳輸方式及資料量的大小,只有主機確定了這些資訊之後,裝置才能真正開始工作,所以描述符也是十分重要的部分,標準的描述符有5種,USB為這些描述符定義了編號:

        1——裝置描述符

        2——配置描述符

        3——字元描述符

        4——介面描述符

        5——端點描述符

        上面的描述符之間有一定的關係,一個裝置只有一個裝置描述符,而一個裝置描述符可以包含多個配置描述符,而一個配置描述符可以包含多個介面描述符,一個介面使用了幾個端點,就有幾個端點描述符。這些描述符是用一定的欄位構成的,分別如下說明:

        1、裝置描述符

struct _DEVICE_DEscriptOR_STRUCT

{

    BYTE bLength;          //裝置描述符的位元組數大小,為0x12

    BYTE bDescriptorType;  //描述符型別編號,為0x01

    WORD bcdUSB;           //USB版本號

    BYTE bDeviceClass;  //USB分配的裝置類程式碼,0x01~0xfe為標準裝置類,0xff為廠商自定義型別

                        //0x00不是在裝置描述符中定義的,如HID

    BYTE bDeviceSubClass;   //usb分配的子類程式碼,同上,值由USB規定和分配的

    BYTE bDeviceProtocl;    //USB分配的裝置協議程式碼,同上

    BYTE bMaxPacketSize0;   //端點0的最大包的大小

    WORD idVendor;          //廠商編號

    WORD idProduct;         //產品編號

    WORD bcdDevice;         //裝置出廠編號

    BYTE iManufacturer;     //描述廠商字串的索引

    BYTE iProduct;          //描述產品字串的索引

    BYTE iSerialNumber;     //描述裝置序列號字串的索引

    BYTE bNumConfiguration; //可能的配置數量

}

        2、配置描述符

struct _CONFIGURATION_DEscriptOR_STRUCT

{

    BYTE bLength;          //裝置描述符的位元組數大小,為0x12

    BYTE bDescriptorType;  //描述符型別編號,為0x01

    WORD wTotalLength;     //配置所返回的所有數量的大小

    BYTE bNumInterface;    //此配置所支援的介面數量

    BYTE bConfigurationVale;   //Set_Configuration命令需要的引數值

    BYTE iConfiguration;       //描述該配置的字串的索引值

    BYTE bmAttribute;          //供電模式的選擇

    BYTE MaxPower;             //裝置從匯流排提取的最大電流

}

        3、字元描述符

struct _STRING_DEscriptOR_STRUCT

{

    BYTE bLength;          //裝置描述符的位元組數大小,為0x12

    BYTE bDescriptorType;  //描述符型別編號,為0x01

    BYTE SomeDescriptor[36];          //UNICODE編碼的字串

}

        4、介面描述符

struct _INTERFACE_DEscriptOR_STRUCT

{

    BYTE bLength;          //裝置描述符的位元組數大小,為0x12

    BYTE bDescriptorType;  //描述符型別編號,為0x01

    BYTE bInterfaceNunber; //介面的編號

    BYTE bAlternateSetting;//備用的介面描述符編號

    BYTE bNumEndpoints;    //該介面使用端點數,不包括端點0

    BYTE bInterfaceClass;  //介面型別

    BYTE bInterfaceSubClass;//介面子型別

    BYTE bInterfaceProtocol;//介面所遵循的協議

    BYTE iInterface;        //描述該介面的字串索引值

}

        5、端點描述符

struct _ENDPOIN_DEscriptOR_STRUCT

{

    BYTE bLength;          //裝置描述符的位元組數大小,為0x12

    BYTE bDescriptorType;  //描述符型別編號,為0x01

    BYTE bEndpointAddress; //端點地址及輸入輸出屬性

    BYTE bmAttribute;      //端點的傳輸型別屬性

    WORD wMaxPacketSize;   //端點收、發最大包的大小

    BYTE bInterval;        //主機查詢端點的時間間隔

}

三、傳輸
        USB系統中的資料傳輸,巨集觀看是在HOST和USB功能裝置之間進行。微觀看是在應用軟體的Buffer和USB功能裝置的端點之間進行。一般來說端點都有Buffer,可以認為USB通訊就是應用軟體Buffer和裝置端點Buffer之間的資料交換,交換的通道稱為管道。應用軟件通過和裝置之間的資料交換來完成裝置控制和資料傳輸。通常需要多個管道來完成資料交換,因為同一管道只支援一種型別的資料傳輸。用在一起來對裝置進行控制的若干管道稱為設備的介面,這就是端點、管道和介面的關係。
        USB 採用“令牌包”-“資料包”-“握手包”的傳輸機制,在令牌包中指定資料包去向或者來源的裝置地址和端點(Endpoint),從而保證了只有一個裝置對被廣播的資料包/令牌包作出響應。握手包表示了傳輸的成功與否。
        USB 採用輪詢的廣播機制傳輸資料,所有的傳輸都由主機發起,任何時刻整個 USB 體系內僅允許一個數據包的傳輸,即不同物理傳輸線上看到的資料包都是同一被廣播的資料包。

        傳輸由OUT、IN和SETUP事務構成,傳輸有四種類型,中斷傳輸、批量傳輸、同步傳輸、控制傳輸,其中中斷傳輸和批量傳輸的結構一樣,同步傳輸有最簡單的結構,而控制傳輸是最重要的也是最複雜的傳輸。

3.1、控制傳輸
        控制傳輸是一種可靠的雙向傳輸,是最重要也是最複雜的,一次控制傳輸可分為構成(初始設定階段、可選資料階段、狀資訊步驟),每一個階段可以看成一個傳輸,也就是說控制傳輸其實是由三個傳輸構成的,在USB裝置初次接到主機後,主機通過控制傳輸來交換資訊、裝置地址和讀取裝置的描述符,使得主機識別裝置,並安裝相應的驅動程式,這是每一個USB開發者都要關心的問題。
        第一階段:從HOST到Device的SETUP事務傳輸,這個階段指定了此次控制傳輸的請求型別。
        第二階段:資料階段,也有些請求沒有資料階段。
        第三階段:狀態階段,通過一次IN/OUT傳輸表明請求是否成功完成。
        控制傳輸通過控制管道在應用軟體和Device的控制端點之間進行,控制傳輸過程中傳輸的資料是有格式定義的,USB 裝置或主機可根據格式定義解析獲得的資料含義。其他三種傳輸型別都沒有格式定義。控制傳輸對於最大包長度有固定的要求。對於高速裝置該值為64Byte,對於低速裝置該值為8,全速裝置可以是8或16或32或64。
        最大包長度表徵了一個端點單次接收/傳送資料的能力,實際上反應的是該端點對應Buffer的大小。Buffer越大,單次可接收/傳送的資料包越大,反之亦反。當通過一個端點進行資料傳輸時,若資料的大小超過該端點的最大包長度時,需要將資料分成若干個資料包傳輸。並保證除最後一個包外,所有的包長度均等於該最大包長度。也就是說如果一個端點收到/傳送了一個長度小於最大包長度的包,即意味著資料傳輸結束。
        控制傳輸在訪問匯流排時也受到一些限制,如高速端點的控制傳輸不能佔用超過 20%的微幀,全速和低速的則不能超過 10%。在一幀內如果有多餘的未用時間,並且沒有同步和中斷傳輸,可以用來進行控制傳輸。


        控制傳輸(Transaction) 一次控制傳輸分為三(或兩個)個階段:建立(Setup)、資料(DATA)(可能沒有)以及狀態(Status)。每個階段都由一次或多次(資料階段)事務傳輸組成(Transaction)。
        上圖為建立階段的事務傳輸流程圖。可以看出:
        與批量傳輸相比,在流程上並沒有多大區別,區別只在於該事務傳輸發生的端點不一樣、支援的最大包長度不一樣、優先順序不一樣等這樣一些對使用者來說透明的東西。
        建立階段過後,可能會有資料階段,這個階段將會通過一次或多次控制傳輸事務,完成資料的傳輸。同樣也會採用PID翻轉的機制。
        建立階段,Device 只能返回ACK包,或者不返回任何包。
        最後是狀態階段,通過一次方向與前一次相反的控制事務傳輸來表明傳輸的成功與否。如果成功會返回一個長度為0的資料包,否則返回 NAK或STALL。下圖為整個控制傳輸的示意圖:

3.2、中斷傳輸
        中斷傳輸是一種輪詢的傳輸方式,是一種單向的傳輸。HOST通過固定的間隔對中斷端點進行查詢,若有資料傳輸或可以接收資料則返回資料或傳送資料。否則返回NAK,表示尚未準備好。中斷傳輸的延遲有保證,但並非實時傳輸,它是一種延遲有限的可靠傳輸,支援錯誤重傳。對於高速/全速/低速端點,最大包長度分別可以達到1024/64/8 Bytes。 高速中斷傳輸不得佔用超過 80%的微幀時間,全速和低速不得超過90%。 中斷端點的輪詢間隔由在端點描述符中定義,全速端點的輪詢間隔可以是1~255mS。低速端點為10~255mS,高速端點為(2interval-1)*125uS,其中 interval 取 1到 16 之間的值。
        除高速高頻寬中斷端點外,一個微幀內僅允許一次中斷事務傳輸。高速高頻寬端點最多可以在一個微幀內進行三次中斷事務傳輸,傳輸高達 3072 位元組的資料。
        所謂單向傳輸,並不是說該傳輸只支援一個方向的傳輸。而是指在某個端點上該傳輸僅支援一個方向,或輸出、或輸入。如果需要在兩個方向上進行某種單向傳輸,需要佔用兩個端點,分別配置成不同的方向。可以擁有相同的端點編號。
        中斷傳輸由OUT事務和IN事務構成,用於鍵盤、滑鼠等HID裝置的資料傳輸。
        中斷傳輸在流程上除不支援PING之外,其他的跟批量傳輸是一樣的。他們之間的區別也僅在於事務傳輸發生的端點不一樣、支援的最大包長度不一樣、優先順序不一樣等這樣一些對使用者來說透明的東西。
        主機在排定中斷傳輸任務時,會根據對應中斷端點描述符中指定的查詢間隔發起中斷傳輸。中斷傳輸有較高的優先順序,僅次於同步傳輸。同樣中斷傳輸也採用 PID 翻轉的機制來保證收發端資料同步。
        下圖為中斷傳輸的流程圖。

3.3、批量傳輸
        批量傳輸由OUT事務和IN事務構成,是一種可靠的單向傳輸,但延遲沒有保證,它儘量利用可以利用的頻寬來完成傳輸,適合資料量比較大的傳輸。低速USB裝置不支援批量傳輸,高速批量端點的最大包長度為512,全速批量端點的最大包長度可以為8、16、32、64。
        批量傳輸在訪問USB匯流排時,相對其他傳輸型別具有最低的優先順序,USB HOST總是優先安排其他型別的傳輸,當匯流排頻寬有富餘時才安排批量傳輸。高速的批量端點必須支援PING操作,向主機報告端點的狀態。NYET表示否定應答,沒有準備好接收下一個資料包,ACK 表示肯定應答,已經準備好接收下一個資料包。

        圖中一個方框表示一個 Packet,灰色的包表示主機發出的包,白色的包表示Device發出的包。批量傳輸是可靠的傳輸,需要握手包來表明傳輸的結果。若資料量比較大,將採用多次批量事務傳輸來完成全部資料的傳輸,傳輸過程中資料包的PID按照 DATA0-DATA1-DATA0-...的方式翻轉,以保證傳送端和接收端的同步。若成功則將錯誤次數計數器清0,否則累加該計數器。USB允許連續3次以下的傳輸錯誤,會重試該傳輸。超過三次後,HOST 認為該端點功能錯誤(STALL),放棄該端點的傳輸任務。
        一次批量傳輸(Transfer)由 1 次到多次批量事務傳輸(Transaction)組成。
        翻轉同步:傳送端按照 DATA0-DATA1-DATA0-...的順序傳送資料包,只有成功的事務傳輸才會導致PID翻轉,也就是說傳送段只有在接收到ACK後才會翻轉PID,傳送下一個資料包,否則會重試本次事務傳輸。同樣,若在接收端發現接收到的資料包不是按照此順序翻轉的,比如連續收到兩個DATA0,那麼接收端認為第二個DATA0是前一個DATA0的重傳。

3.4、同步傳輸

        同步傳輸是一種實時的、不可靠的傳輸,不支援錯誤重發機制。只有高速和全速端點支援同步傳輸,高速同步端點的最大包長度為1024,低速的為1023。由OUT事務和IN事務構成。有兩個特殊地方,第一,在同步傳輸的IN和OUT事務中是沒有返回包階段的;第二,在資料包階段所有的資料包都為DATA0。
        除高速高頻寬同步端點外,一個微幀內僅允許一次同步事務傳輸,高速高頻寬端點最多可以在一個微幀內進行三次同步事務傳輸,傳輸高達 3072 位元組的資料。全速同步傳輸不得佔用超過 80%的幀時間,高速同步傳輸不得佔用超過90%的微幀時間。同步端點的訪問也和中斷端點一樣,有固定的時間間隔限制。

        同步傳輸是不可靠的傳輸,所以它沒有握手包,也不支援PID翻轉。主機在排定事務傳輸時,同步傳輸有最高的優先順序。

3.5、分離傳輸(Split Transaction)
        分離傳輸是在主機控制器和USB HUB之間的傳輸,它僅在主機控制器和HUB之間執行,通過分離傳輸,可以允許全速/低速裝置連線到高速主機。分離傳輸對於USB裝置來說是透明的、不可見的。
        分離傳輸,顧名思義就是把一次完整的事務傳輸分成兩個事務傳輸來完成。其出發點是高速傳輸和全速/低速傳輸的速度不相等,如果使用一次完整的事務來傳輸,勢必會造成比較長的等待時間,從而降低了高速USB匯流排的利用率。通過將一次傳輸分成兩次,將令牌(和資料)的傳輸與響應資料(和握手)的傳輸分開,這樣就可以在中間插入其他高速傳輸,從而提高匯流排的利用率。
3.6、總結

        包是USB匯流排資料傳輸的最小單位,不能被打斷或干擾,否則會引發錯誤。若干個資料包組成一次事務傳輸,一次事務傳輸也不能打斷,屬於一次事務傳輸的幾個包必須連續,不能跨幀完成。一次傳輸由一次到多次事務傳輸構成,可以跨幀完成。
四、列舉

        USB裝置連線到HOST時,HOST必須通過預設的控制管道對其進行列舉,完成獲得其裝置描述、進行地址分配、獲得其配置描述、進行配置等操作後方可正常使用。USB裝置的即插即用特性即依賴於此。

4.1、列舉時USB的狀態

        當USB裝置插上主機時,主機就通過一系列的動作來對裝置進行列舉配置(配置是屬於列舉的一個態,態表示暫時的狀態),這些態如下:

        1、接入態(Attached):裝置接入主機後,主機通過檢測訊號線上的電平變化來發現裝置的接入;

        2、供電態(Powered):就是給裝置供電,分為裝置接入時的預設供電值,配置階段後的供電值(按資料中要求的最大值,可通過程式設計設定);

        3、預設態(Default):USB在被配置之前,通過預設地址0與主機進行通訊;

        4、地址態(Address):經過了配置,USB裝置被複位後,就可以按主機分配給它的唯一地址來與主機通訊,這種狀態就是地址態;

        5、配置態(Configured):通過各種標準的USB請求命令來獲取裝置的各種資訊,並對裝置的某些資訊進行改變或設定。

        6、掛起態(Suspended):匯流排供電裝置在3ms內沒有匯流排操作,即USB匯流排處於空閒狀態的話,該裝置就要自動進入掛起狀態,在進入掛起狀態後,總的電流功耗不超過280uA。
        狀態轉移圖如下所示:


       
4.2、列舉過程

        1、使用者將一個USB裝置插入USB埠,主機為埠供電,裝置此時處於上電狀態。主機檢測裝置。集線器使用中斷通道將事件報告給主機。

        2、主機發送Get_Port_Status(讀埠狀態)請求,以獲取更多的裝置資訊。 返回的訊息告訴主機該裝置是什麼時候連線的。 集線器檢測裝置是低速執行還是高速執行,並將此資訊送給主機,這是對Get_Port_Status請 求的響應。

        3、主機發送Set_Port_Feature(寫埠狀態)請求給集線器,要求它復位埠,請求集線器來重新設定埠。集線器使裝置的USB資料線處於重啟(RESET)狀態至少10ms。

        4、主機使用Chirp K訊號來了解全速裝置是否支援高速執行。

        5、主機發送另一個Get_Port_Status請求,確定裝置是否已經從復位狀態退出。返回的資料有一位表示裝置仍然處於重啟狀態。當集線器釋放了重啟狀態,裝置此時處於預設狀態,且已準備好在零端點通過預設通道響應主機控制傳輸。預設地址為00h,裝置能從匯流排獲取高達100mA的電流。
        6、集線器檢測裝置速度 

        集線器通過測定哪根訊號線(D+或D-)在空閒時有更高的電壓來檢測裝置是低速裝置還是全速裝置。全速和高速裝置D+有上拉電阻,低速裝置D-有上拉電阻。

        7、獲取最大資料包長度
        主機向address 0傳送Get_Device_Deor(讀裝置描述符)報文,以取得預設控制管道所支援的最大資料包長度並在有限的時間內等待USB裝置的響應該長度包含在裝置描述符的bMaxPacketSize0欄位中,其地址偏移量為7,所以這時主機只需讀取該描述符的前8個位元組。注意,主機一次只能列舉一個USB裝置,所以同一時刻只能有一個USB裝置使用預設地址0。
        例:主機向裝置傳送一個八位元組請求:80 06 00 01 00 00 40 00,裝置接收到請求後產生一箇中斷,我們可以通過讀中斷暫存器知道中斷源,並且可以加讀最後狀態暫存器來確定第一個接到的包是否為一個Setup包。當控制器處理程式判斷出它是一個Get_descriptor請求時,把裝置描述符的前16個位元組傳送到端點0緩衝區中。剩下的2個字節描述符第一次請求時不再發送。

        8、主機分配一個新的地址給裝置

        主機通過傳送一個Set_Address請求來分配一個唯一的地址給裝置。裝置讀取這個請求,返回一個確認,並儲存新的地址。從此開始所有通訊都使用這個新地址。

        例:當主機收到正確的前16位元組描述符後,會給裝置分配一個地址,我的PC分配的地址為:0x03(這個要看你的機子當的USB介面裝置數目而定) Set_Address 請求所傳送的資料為:00 05 03 00 00 00 00 00,其中的03就表示主機為裝置配的地址為0x03,在以後的通訊裡裝置就只對0x03地址作出應答。當裝置產生一個接收中斷後,根據所分配的地址設定裝置的地址暫存器相應位。

        9、主機向新地址重新發送Get_Device_Deor命令,此次讀取其裝置描述符的全部欄位,以瞭解該裝置的總體資訊,如VID,PID。
        例:主機發送裝置描述符標準請求Get_descriptor:80 06 00 01 00 00 12 00,此次將要求把18個位元組全部發送完。所以主機要分兩次來讀取。第一次讀取16個位元組,第二次讀取兩個位元組,最後主機發送0表示傳送完畢的應答。

         10、主機向裝置迴圈傳送Get_Device_Configuration命令,要求USB裝置回答,以讀取全部配置資訊。

        11、主機發送Get_Device_String命令,獲得字符集描述(unicode),比如產商、產品描述、型號等等。此時主機將會彈出視窗,展示發現新裝置的資訊,產商、產品描述、型號等。

        根據Device_Deor和Device_Configuration應答,PC判斷是否能夠提供USB的Driver,一般win2k能提供幾大類的裝置,如遊戲操作杆、儲存、印表機、掃描器等,操作就在後臺執行。但是Win98卻不可以,所以在此時將會彈出對話方塊,索要USB的Driver。

        12、主機分配並載入裝置驅動程式,這時就可能作應用中的資料傳輸了。

        13、主機發送Set_Configuration(x)(寫配置)命令請求為該裝置選擇一個合適的配置(x代表非0的配置值)。如果配置成功,USB裝置進入“配置”狀態,並可以和客戶軟體進行資料傳輸。此時,常規的USB完成了其必須進行的配置和連線工作,至此裝置應當可以開始使用。不過,USB協議還提供了一些使用者可選的協議,裝置如果不應答,也不會出錯,但是會影響到系統的功能。

        14、主機為複合裝置介面分配驅動程式。如果集線器檢測到有過流現象,或者主機要求集線器關閉電源,則USB匯流排切斷裝置供電電源。在這種情況下,裝置與主機無法通訊,但裝置處於連線狀態。   

        使用USB View 採集到的資料:

Device Descriptor:
bcdUSB:             0x0100
bDeviceClass:         0xDC
bDeviceSubClass:      0x00
bDeviceProtocol:      0x00
bMaxPacketSize0:      0x10 (16)
idVendor:           0x0471
idProduct:          0x0666
bcdDevice:          0x0100
iManufacturer:        0x00
iProduct:             0x00
iSerialNumber:        0x00
bNumConfigurations:   0x01

ConnectionStatus: DeviceConnected
Current Config Value: 0x01
Device Bus Speed:     Full
Device Address:       0x02
Open Pipes:              4

Endpoint Descriptor:
bEndpointAddress:     0x81
Transfer Type:   Interrupt
wMaxPacketSize:     0x0010 (16)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x01
Transfer Type:   Interrupt
wMaxPacketSize:     0x0010 (16)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x82
Transfer Type:        Bulk
wMaxPacketSize:     0x0040 (64)
bInterval:            0x0A

Endpoint Descriptor:
bEndpointAddress:     0x02
Transfer Type:        Bulk
wMaxPacketSize:     0x0040 (64)
bInterval:            0x0A

        對2440的USB HOST進行初始化完畢(主要包括對符合OHCI規範的暫存器的初始化—匯流排復位、中斷使能、清除中斷標誌、電源管理、記憶體指標暫存器的初始化,各種資料結構的初始化等),等待USB裝置的插入,當2440檢測到有裝置插入,就要對裝置進行枚舉了。起始列舉就相當於主機和裝置建立連線的過程(接頭),Host向Device詢問一些東西,Device將自身的裝置型別,如何進行通訊報告給Host,這樣Host就知道怎麼對Device進行操作了。

        列舉的過程實際上用到而且只用到了匯流排的“控制傳輸(Control Transfer)”。這種傳輸方式通常用於配置/命令/狀態等情形,其中的設定操作setup和狀態操作status過程的資料包具有USB協議定義的資料結構,因此,控制傳輸只能通過訊息管道進行。

        一個完整的控制傳輸包括三個過程:

        1、建立連線。   
        2、資料過程(可選) 。       
        3、狀態過程。

        建立連線的過程都是由Host發起,它開始於一個Setup令牌包,後面緊跟一個DATA0包。如果是控制輸入傳輸,資料過程則為輸入資料,若是控制輸出傳輸,則資料過程是輸出資料。

        資料過程的可選型是指設定過程需要指定資料長度,如果指定為0,則沒有資料過程。狀態過程跟在資料過程之後,狀態過程恰好和資料過程的資料傳輸方向相反,因為此階段主要是用來確認之前兩階段的所有資料都已經正確傳輸了。

       好了,下面就結合我的這個例項來看看列舉的詳細過程:

        1、控制2440向U盤傳送第一個Setup包,內容是80 06 00 01 00 00 08 00,其中最後的00 08表示得到DEVICE_DCESCRIPTOR的前8個位元組,因為這個包的主要目的是要獲得USB Device中端點0的最大包的大小(第8個位元組),所以只需要8個位元組就可以了。USB Device返回的裝置識別符號為12 01 10 01 00 00 00 40,下面我們需要把0x40記錄下來,將其放到Endpoint Descriptor資料結構的DWORD0的MPS(bit16~bit32)塊中去。
        2、接下來2440傳送第二個Setup包,內容是00 05 01 00 00 00 00 00,這一次的作用是為USB裝置分配地址。如果USB Device接收並接受了此地址設置包,會返回一個長度為0的資料包。主機接收到長度為0的狀態包之後就會返回一個ACK給Device,Device再接收到這個ACK之後,就可以啟用新地址了。這樣Device就得到了一個唯一的裝置地址,作為主機通訊的唯一表示。

        3、傳送第三個Setup包,內容是80 06 00 02 00 00 09 00,這次是為了獲取配置描述符集合的大小,此位位於讀回資料的第三個位元組。U盤返回的資料為09 02 20 00 01 01 00 80 32,即描述符集合總大小為0x20。

        4、傳送第四個Setup包,內容是80 06 00 02 00 00 09 00,和上次不同的僅僅是,這次要讀回來的資料是整個配置描述符區域。U盤返回來的資料是09 02 20 00 01 01 00 80 32 09 04 00 00 02 08 06 50 00 07 05 82 02 40 00 00 07 05 02 02 40 00 00。這時候我們就可以知道該裝置是什麼型別的裝置,支援什麼樣的操作了。

上述這兩個過程也有的程式就是直接讀取0xff個字元大小,當然同樣可以達到讀回裝置描述符集合的目的。

至此,我們已經得到了所需要的裝置資訊,之後就可以對裝置進行配置了。

        5、向裝置傳送第五個Setup包,資料為00 09 01 00 00 00 00 00,USB Device返回一個長度為0的資料包,表明資料正確接收。至此,USB列舉過程就完成了。初始設定步驟:就是一個由SET事務構成的傳輸

        可選資料步驟:就是一個由IN或OUT事務構成的傳輸,這個步驟是可選的,要看初始設定步驟有沒有要求讀/寫資料(由SET事務的資料包階段傳送的標準請求命令決定)。

        狀態資訊步驟:這個步驟就是要獲取狀態資訊,由IN或OUT事務構成的傳輸,但是要注意這裡的IN和OUT事務和之前的INT和OUT事務有兩點不同:

        1) 傳輸方向相反,通常IN表示裝置往主機送資料,OUT表示主機往裝置送資料;在這裡,IN表示主機往裝置送資料,而OUT表示裝置往主機送資料,這是為了和可選資料步驟相結合;

        2) 在這個步驟裡,資料包階段的資料包都是0長度的,即SYNC+PID+CRC16。