免费高清特黄a大片,九一h片在线免费看,a免费国产一级特黄aa大,国产精品国产主播在线观看,成人精品一区久久久久,一级特黄aa大片,俄罗斯无遮挡一级毛片

分享

USB通信協(xié)議概述

 出家人eqyi0h1n 2017-10-24


一、SUB概述

        USB協(xié)議有兩種:USB1.1和USB2.0。(現(xiàn)在有3.0了)

        USB2.0和USB1.1完全兼容。USB1.1支持的 數(shù)據(jù)傳輸率為12Mbps和1.5Mbps(用于慢 速外設(shè)),USB2.0支持的數(shù)據(jù)傳速率可達 480Mbps。在普通用戶看來,USB系統(tǒng)就是 外設(shè)通過一根USB電纜和PC機連接起來。 通常把外設(shè)稱為USB設(shè)備,把其所連接的 PC機稱為USB主機。將指向USB主機的數(shù)據(jù)傳輸方向稱為上行通信,把指向USB設(shè)備的 數(shù)據(jù)傳輸方向稱為下行通信。

        USB網(wǎng)絡(luò)采用階梯式星形拓撲結(jié)構(gòu),如圖1。一個USB網(wǎng)絡(luò)中只能有一個主機。主機內(nèi)設(shè)置了一個根集線器,提供了主機上的初始附屬點。

 

圖1 USB主機和USB設(shè)備的連接

        主機定時對集線器的狀態(tài)進行查詢。當一個新設(shè)備接入集線器時,主機會檢測到集線器狀態(tài)改變,主機發(fā)出一個命令使該端口有效并對其進行設(shè)置。位于這個端口上的設(shè)備進行響應(yīng),主機收到關(guān)于設(shè)備的信息,主機的操作系統(tǒng)確定對這個設(shè)備使用那種驅(qū)動程序,接著設(shè)備被分配一個唯一標識的地址,范圍從0~127,其中0為所有的設(shè)備在沒有分配惟一地址時使用的默認地址。主機向它發(fā)出內(nèi)部設(shè)置請求。當一個設(shè)備從總線上移走時,主機就從其可用資源列表中將這個設(shè)備刪除。

二、USB系統(tǒng)基本概念

2.1、 USB主機

        USB的所有數(shù)據(jù)通信(不論是上行通信還是下行通信)都由USB主機啟動,所以USB主機在整個數(shù)據(jù)傳輸過程中占據(jù)著主導(dǎo)地位。在USB系統(tǒng)中只允許有一個主機。從開發(fā)人員的角度看,USB主機可分為三個不同的功能模塊:客戶軟件、USB系統(tǒng)軟件和USB總線接口。

(1) 客戶軟件 :

        客戶軟件負責和USB設(shè)備的功能單元進行通信,以實現(xiàn)其特定功能。一般由開發(fā)人員自行開發(fā)??蛻糗浖荒苤苯釉L問USB設(shè)備,其與USB設(shè)備功能單元的通信必須經(jīng)過USB系統(tǒng)軟件和USB總線接口模塊才能實現(xiàn)??蛻糗浖话惆║SB設(shè)備驅(qū)動程序和界面應(yīng)用程序兩部分。

        USB設(shè)備驅(qū)動程序負責和USB系統(tǒng)軟件進行通信。通常,它向USB總線驅(qū)動程序發(fā)出I/O請求包(IRP)以啟動一次USB數(shù)據(jù)傳輸。此外,根據(jù)數(shù)據(jù)傳輸?shù)姆较?,它還應(yīng)提供一個或空或滿的數(shù)據(jù)緩沖區(qū)以存儲這些數(shù)據(jù)。
         界面應(yīng)用程序負責和USB設(shè)備驅(qū)動程序進行通信,以控制USB設(shè)備。它是最上層的軟件,只能看到向USB設(shè)備發(fā)送的原始數(shù)據(jù)和從USB設(shè)備接收的最終數(shù)據(jù)。

(2) USB系統(tǒng)軟件:

        USB系統(tǒng)軟件負責和USB邏輯設(shè)備進行配置通信,并管理客戶軟件啟動的數(shù)據(jù)傳輸。USB邏輯設(shè)備是程序員與USB設(shè)備打交道的部分。USB系統(tǒng)軟件一般包括USB總線驅(qū)動程序和USB主控制器驅(qū)動程序這兩部分。這些軟件通常由操作系統(tǒng)提供,開發(fā)人員不必掌握。

(3) USB總線接口:

       USB總線接口包括主控制器和根集線器兩部分。根集線器為USB系統(tǒng)提供連接起點,用于給USB系統(tǒng)提供一個或多個連接點(端口)。主控制器負責完成主機和USB設(shè)備之間數(shù)據(jù)的實際傳輸,包括對傳輸?shù)臄?shù)據(jù)進行串行編解碼、差錯控制等。該部分與USB系統(tǒng)軟件的接口依賴于主控制器的硬件實現(xiàn),開發(fā)人員不必掌握。

2.2、USB設(shè)備

        一個USB設(shè)備由三個功能模塊組成:USB總線接口、USB邏輯設(shè)備和功能單元。這里的USB總線接口指的是USB設(shè)備中的串行接口引擎(SIE);USB邏輯設(shè)備被USB系統(tǒng)軟件看作是一個端點的集合;功能單元被客戶軟件看作是一個接口的集合。SIE、端點和接口都是USB設(shè)備的組成單元。為了更好地描述USB設(shè)備的特征,USB提出了設(shè)備架構(gòu)的概念。從這個角度來看,可以認為USB設(shè)備是由一些配置、接口和端點組成的,即一個USB設(shè)備可以含有一個或多個配置,在每個配置中可含有一個或多個接口,在每個接口中可含有若干個端點。其中,配置和接口是對USB設(shè)備功能的抽象,實際的數(shù)據(jù)傳輸由端點來完成。在使用USB設(shè)備前,必須指明其采用的配置和接口。這個步驟一般是在設(shè)備接入主機時設(shè)備進行自舉時完成的,我們在后面會進一步介紹。USB設(shè)備使用各種描述符來說明其設(shè)備架構(gòu),包括設(shè)備描述符、配置描述符、接口描述符、端點描述符以及字符串描述符,它們通常被保存在USB設(shè)備的固件程序中。  

①設(shè)備:

        設(shè)備代表一個USB設(shè)備,它由一個或多個配置組成。設(shè)備描述符用于說明設(shè)備的總體信息,并指明其所含的配置的個數(shù)。一個USB設(shè)備只能有一個設(shè)備描述符。     

②配置:

        一個USB設(shè)備可以包含一個或多個配置,如USB設(shè)備的低功耗模式和高功耗模式可分別對應(yīng)一個配置。在使用USB設(shè)備前,必須為其選擇一個合適的配置。配置描述符用于說明USB設(shè)備中各個配置的特性,如配置所含接口的個數(shù)等。USB設(shè)備的每一個配置都必須有一個配置描述符。

③接口:

        一個配置可以包含一個或多個接口,如對一個光驅(qū)來說,當用于文件傳輸時使用其大容量存儲接口;而當用于播放CD時,使用其音頻接口。接口是端點的集合,可以包含一個或多個可替換設(shè)置,用戶能夠在USB處于配置狀態(tài)時,改變當前接口所含的個數(shù)和特性。接口描述符用于說明USB設(shè)備中各個接口的特性,如接口所屬的設(shè)備類及其子類等。USB設(shè)備的每個接口都必須有一個接口描述符。

④端點:

        端點是USB設(shè)備中的實際物理單元,USB數(shù)據(jù)傳輸就是在主機和USB設(shè)備各個端點之間進行的。端點一般由USB接口芯片提供,例如Freescale的MC68HC908JB8。USB設(shè)備中的每一個端點都有唯一的端點號,每個端點所支持的數(shù)據(jù)傳輸方向一般而言也是確定的:或是輸入(IN)或是輸出(OUT),也有些芯片提供的端點的數(shù)據(jù)方向是可以配置的,例如MC68HC908JB8包含有兩個用于數(shù)據(jù)收發(fā)的端點:端點1和端點2。其中端點1只能用于數(shù)據(jù)發(fā)送,即支持輸入(IN),端點2既能用于數(shù)據(jù)發(fā)送也可用于數(shù)據(jù)接收,即支持輸入(IN)和輸出(OUT)操作。需要注意的是,在這里數(shù)據(jù)的傳輸方向是站在主機的立場上來看得。比如端點1只能發(fā)送數(shù)據(jù),在主機看來是端點1向主機輸入數(shù)據(jù),即IN操作;當端點2配置為接收數(shù)據(jù)時,主機向端點2輸出數(shù)據(jù),即OUT操作。這一點是初學(xué)者比較容易產(chǎn)生混淆的地方。

       利用設(shè)備地址、端點號和傳輸方向就可以指定一個端點,并和它進行通信。0號端點比較特殊,它有數(shù)據(jù)輸入IN和數(shù)據(jù)輸出OUT兩個物理單元,且只能支持控制傳輸。

⑤字符串

        在USB設(shè)備中通常還含有字符串描述符,以說明一些專用信息,如制造商的名稱、設(shè)備的序列號等。它的內(nèi)容以UNICODE的形式給出,且可以被客戶軟件所讀取。對USB設(shè)備來說,字符串描述符是可選的。

⑥管道

        在USB系統(tǒng)結(jié)構(gòu)中,可以認為數(shù)據(jù)傳輸是在主機軟件(USB系統(tǒng)軟件或客戶軟件)和USB設(shè)備的各個端點之間直接進行的,它們之間的連接稱為管道。管道是在USB設(shè)備的配置過程中建立的。管道是對主機和USB設(shè)備間通信流的抽象,它表示主機的數(shù)據(jù)緩沖區(qū)和USB設(shè)備的端點之間存在著邏輯數(shù)據(jù)傳輸,而實際的數(shù)據(jù)傳輸是由USB總線接口層來完成的。

       管道和USB設(shè)備中的端點一一對應(yīng)。一個USB設(shè)備含有多少個端點,其和主機進行通信時就可以使用多少條管道,且端點的類型決定了管道中數(shù)據(jù)的傳輸類型,如中斷端點對應(yīng)中斷管道,且該管道只能進行中斷傳輸。傳輸類型在后面會介紹。不論存在著多少條管道,在各個管道中進行的數(shù)據(jù)傳輸都是相互獨立的。

三、USB物理特性

   3.1、USB接口

      USB使用一根屏蔽的4線電纜與網(wǎng)絡(luò)上的設(shè)備進行互聯(lián)。數(shù)據(jù)傳輸通過一個差分雙絞線進行,這兩根線分別標為D+和D-,另外兩根線是Vcc和Ground,其中Vcc向USB設(shè)備供電。使用USB電源的設(shè)備稱為總線供電設(shè)備,而使用自己外部電源的設(shè)備叫做自供電設(shè)備。為了避免混淆,USB電纜中的線都用不同的顏色標記,如表1所示。(現(xiàn)在為了支持主機,設(shè)備的互換,增加了一條線,OTG,也就有了mini USB)

引腳編號      信號名稱纜線顏色
1Vcc   
2Data-(D-)   
3Data+(D+)   
4 Ground   
表1    USB纜線的信號與顏色

        從一個設(shè)備連回到主機,稱為上行連接;從主機到設(shè)備的連接,稱為下行連接。為了防止回環(huán)情況的發(fā)生,上行和下行端口使用不同的連接器所以USB在電纜和設(shè)備的連接中分別采用了兩種類型的連接頭,即圖16-2所示的A型連接頭和B型連接頭。每個連接頭內(nèi)的電線號與圖16-2的引腳編號是一致的。A型連接頭,用于上行連接,即在主機或集線器上有一個A型插座,而在連接到主機或集線器的電纜的一端是A型插頭。在USB設(shè)備上有B型插座,而B型插頭在從主機或集線器接出的下行電纜的一端。采用這種連接方式,可以確保USB設(shè)備、主機/集線器和USB電纜始終以正確的方式連接,而不出現(xiàn)電纜接入方式出錯,或直接將兩個USB設(shè)備連接到一起的情況。


圖2   USB連接頭

3.2、USB信號

(1) 差分信號技術(shù)特點
             傳統(tǒng)的傳輸方式大多使用“正信號”或者“負信號”二進制表達機制,這些信號利用單線傳輸。用不同的信號電平范圍來分別表示1和0,它們之間有一個臨界值,如果在數(shù)據(jù)傳輸過程中受到中低強度的干擾,高低電平不會突破臨界值,那么信號傳輸可以正常進行。但如果遇到強干擾,高低電平突破臨界值,由此造成數(shù)據(jù)傳輸出錯。差分信號技術(shù)最大的特點是:必須使用兩條線路才能表達一個比特位,用兩條線路傳輸信號的壓差作為判斷1還是0的依據(jù)。這種做法的優(yōu)點是具有極強的抗干擾性。倘若遭受外界強烈干擾,兩條線路對應(yīng)的電平同樣會出現(xiàn)大幅度提升或降低的情況,但二者的電平改變方向和幅度幾乎相同,電壓差值就可始終保持相對穩(wěn)定,因此數(shù)據(jù)的準確性并不會因干擾噪聲而有所降低。

(2)USB通信的格式

圖3 在USB電纜上使用雙向不歸零編碼和差動信號的傳輸

       USB的數(shù)據(jù)包使用反向不歸零編碼(NRZI)。圖3描述了在USB電纜段上傳輸信息的步驟。反向不歸零編碼由傳送信息的USB代理程序完成;然后,被編碼的數(shù)據(jù)通過差分驅(qū)動器送到USB電纜上;接著,接收器將輸入的差分信號進行放大,將其送給解碼器。使用該編碼和差動信號傳輸方式可以更好地保證數(shù)據(jù)的完整性并減少噪聲干擾。


圖4      反向不歸零編碼

        使用反向不歸零編碼方式可以保證數(shù)據(jù)傳輸?shù)耐暾?,而且不要求傳輸過程中有獨立的時鐘信號。反向不歸零編碼不是一個新的編碼方式。它在許多方面都有應(yīng)用。圖4給出了一個數(shù)據(jù)流和編碼之后的結(jié)果。在反向不歸零編碼時,遇到“0”轉(zhuǎn)換,遇到“1”保持。反向不歸零碼必須保持與輸入數(shù)據(jù)的同步性,以確保數(shù)據(jù)采樣正確。反向不歸零碼數(shù)據(jù)流必須在一個數(shù)據(jù)窗口被采樣,無論前一個位時間是否發(fā)生過轉(zhuǎn)換。解碼器在每個位時間采樣數(shù)據(jù)以檢查是否有轉(zhuǎn)換。

圖5     在USB電纜上使用雙向不歸零編碼和差動信號的傳輸

        若重復(fù)相同的“1”信號一直進入時,就會造成數(shù)據(jù)長時間無法轉(zhuǎn)換,逐漸的積累,而導(dǎo)致接收器最終丟失同步信號的狀況,使得讀取的時序會發(fā)生嚴重的錯誤。因此,在NRZI編碼之間,還需執(zhí)行所謂的位填充的工作。位填充要求數(shù)據(jù)流中如果有連續(xù)的六個“1”就要強行轉(zhuǎn)換。這樣接收器在反向不歸零碼數(shù)據(jù)流中最多每七個位就檢測到一次跳轉(zhuǎn)。這樣就保證了接收器與輸入數(shù)據(jù)流保持同步。反向不歸零碼的發(fā)送器要把“0”(填充位)插到數(shù)據(jù)流中。接收器必須被設(shè)計成能夠在連續(xù)的六個“1”之后識別一個自動跳轉(zhuǎn),并且立即扔掉這六個“1”之后的“0”位。

       圖5的第一行是送到接收器的原始數(shù)據(jù)。注意數(shù)據(jù)流包括連續(xù)的八個“1”。第二行表示對原始數(shù)據(jù)進行了位填充,在原始的第六個和第七個“1”之間填入了一個“0”。第七個“1”延時一個位時間讓填充位插入。接收器知道連續(xù)六個“1”之后將是一個填充位,所以該位就要被忽略。注意,如果原始數(shù)據(jù)的第七個位是“0”,填充位也同樣插入,在填充過的數(shù)據(jù)流中就會有兩個連續(xù)的“0”。

3.3、檢測設(shè)備連接和速度

       在USB設(shè)備連接時,USB系統(tǒng)能自動檢測到這個連接,并識別出其采用的數(shù)據(jù)傳輸速率。USB采用在D+或D-線上增加上拉電阻的方法來識別低速和全速設(shè)備。USB支持三種類型的傳輸速率:1.5Mb/s的低速傳輸、12Mb/s的全速傳輸和480Mb/s的高速傳輸。如圖6所示。當主控制器或集線器的下行端口上沒有USB設(shè)備連接時,其D+和D-線上的下拉電阻使得這兩條數(shù)據(jù)線的電壓都是近地的(0V);當全速/低速設(shè)備連接以后,電流流過由集線器的下拉電阻和設(shè)備在D+/D-的上拉電阻構(gòu)成的分壓器。由于下拉電阻的阻值是15KΩ,上拉電阻的阻值是1.5KΩ,所以在D+/D-線上會出現(xiàn)大小為(Vcc*15/(15+1.5))的直流高電平電壓。當USB主機探測到D+/D-線的電壓已經(jīng)接近高電平,而其它的線保持接地時,它就知道全速/低速設(shè)備已經(jīng)連接了。保持接地時,它就知道全速/低速設(shè)備已經(jīng)連接了。

圖6:USB連接圖

四、USB通信協(xié)議

4.1、 數(shù)據(jù)包

       包(Packet)是USB系統(tǒng)中信息傳輸?shù)幕締卧?,所有?shù)據(jù)都是經(jīng)過打包后在總線上傳輸?shù)摹SB包由五部分組成,即同步字段(SYNC)、包標識符字段(PID)、數(shù)據(jù)字段、循環(huán)冗余校驗字段(CRC)和包結(jié)尾字段(EOP),包的基本格式如下:

同步字段(SYNC)PID字段數(shù)據(jù)字段CRC字段包結(jié)尾字段(EOP)

       4.1.1、SYNC字段:由8位組成,作為每個數(shù)據(jù)封包的前導(dǎo),用來產(chǎn)生同步作用,使USB設(shè)備與總線的包傳輸率同步,它的數(shù)值固定為00000001。

       4.1.2、PID字段:用來表示數(shù)據(jù)封包的類型。包標識符中的校驗字段是通過對類型字段的每個位求反碼產(chǎn)生的, PID字段如下圖所示:

PID0PID1PID2PID3~PID0~PID1~PID2~PID3
        表2中列出了信息包的類型,包括令牌、數(shù)據(jù)、握手或特殊四種信息包類型。

封包類型PID名稱PID編碼意義
令牌OUT0001B從主機到設(shè)備的數(shù)據(jù)傳輸
令牌IN1001B從設(shè)備到主機的數(shù)據(jù)傳輸
令牌SOF0101B幀的起始標記與幀碼
令牌SETUP1101B從主機到設(shè)備。表示要進行控制傳輸
數(shù)據(jù)DATA00011B偶數(shù)數(shù)據(jù)封包
數(shù)據(jù)DATA11011B奇數(shù)數(shù)據(jù)封包
握手ACK0010B接收器收到無錯誤的數(shù)據(jù)封包
握手NAK1010B接收器無法接收數(shù)據(jù)或發(fā)射器無法送出數(shù)據(jù)
握手STALL1110B

端點產(chǎn)生停滯的狀況

特殊PRE1100B使能下游端口的USB總線的數(shù)據(jù)傳輸切換到低速的設(shè)備
表2       各種信息包的類型與規(guī)范

       4.1.3、數(shù)據(jù)字段: 是用來攜帶主機與設(shè)備之間要傳遞的信息,其內(nèi)容和長度根據(jù)包標識符、傳輸類型的不同而各不相同。在USB包中,數(shù)據(jù)字段可以包含設(shè)備地址、端點號、幀序列號以及數(shù)據(jù)等內(nèi)容。在總線傳輸中,總是首先傳輸字節(jié)的最低位,最后傳輸字節(jié)的最高位。

        (1) 設(shè)備地址(ADDR)數(shù)據(jù)域ADDR數(shù)據(jù)域由7位組成,可用來尋址多達127個外圍設(shè)備。
        (2) 端點(ENDP)數(shù)據(jù)域: ENDP數(shù)據(jù)域由4位組成。通過這4個位最多可尋址出32個端點。這個ENDP數(shù)據(jù)域僅用在IN、OUT與SETUP令牌信息包中。對于慢速設(shè)備可支持端點0以及端點1作為中斷傳輸模式,而全速設(shè)備則可以擁有16個輸入端點(IN)與16個輸出端點(OUT)共32個端點。
        (3) 幀序列號:當USB令牌包的PID為SOF時,其數(shù)據(jù)字段必須為11位的幀序列號。幀序列號由主機產(chǎn)生,且每個數(shù)據(jù)幀自動加一,最大數(shù)值為0x7FF。當幀序列號達到最大數(shù)時將自動從0開始循環(huán)。
       (4) 數(shù)據(jù):它僅存于DATA信息包內(nèi),根據(jù)不同的傳輸類型,擁有不同的字節(jié)大小,從0到1023字節(jié)(實時傳輸)。

        4.1.4、循環(huán)冗余碼CRC:字段由不同數(shù)目的位所組成。根據(jù)不同的信息包類型,CRC數(shù)據(jù)域由不同數(shù)目的位所組成。其中重要的數(shù)據(jù)信息包采用CRC16的數(shù)據(jù)域(16個位),而其余的信息包類型則采用CRC5的數(shù)據(jù)域(5個位)。其中的循環(huán)冗余碼校驗CRC,是一種錯誤檢測技術(shù)。由于數(shù)據(jù)在傳輸時,有時候會發(fā)生錯誤,因此CRC可根據(jù)數(shù)據(jù)算出一個校驗值,然后依此判斷數(shù)據(jù)的正確性

        4.1.5、包結(jié)尾字段:即發(fā)送方在包的結(jié)尾發(fā)出包結(jié)尾信號。USB主機根據(jù)EOP判斷數(shù)據(jù)包的結(jié)束。

4.2、信息包格式

         4.2.1、令牌(token)包:  在USB系統(tǒng)中,只有主機才能發(fā)出令牌包。令牌包定義了數(shù)據(jù)傳輸?shù)念愋?,它是事?wù)處理的第一階段。令牌包中較為重要的是SETUP、IN和OUT這三個令牌包。它們用來在根集線器和設(shè)備端點之間建立數(shù)據(jù)傳輸。一個IN包用來建立一個從設(shè)備到根集線器的數(shù)據(jù)傳送,一個OUT包用來建立從根集線器到設(shè)備的數(shù)據(jù)傳輸。令牌包格式如下:

8位4位4位7位4位5位
SYNCPID~PIDADDRENDPCRC5
        4.2.2、數(shù)據(jù)(data)包: 數(shù)據(jù)封包含有4個域:SYNC、PID、DATA與CRC16。DATA數(shù)據(jù)域的位值是根據(jù)USB設(shè)備的傳輸速度及傳輸類型而定,且須以8字節(jié)為基本單位。也就是,若傳輸?shù)臄?shù)據(jù)不足8字節(jié),或傳輸?shù)阶詈笏S嗟囊膊蛔?字節(jié),仍須傳輸8字節(jié)的數(shù)據(jù)域。格式如下:
8位4位4位0~1023位16位
SYNCPID~PIDDATACRC16
       4.2.3、  握手(Handshake)包:握手信息包是最簡單的信息包類型。在這個握手信息包中僅包含一個PID數(shù)據(jù)域而已,它的格式如下所列:
8位4位4位
SYNCPID~PID

4.3、事務(wù)

        在USB上數(shù)據(jù)信息的一次接收或發(fā)送的處理過程稱為事務(wù)處理(Transaction)。事務(wù)處理的類型包括輸入(IN)事務(wù)處理、輸出(OUT)事務(wù)處理、設(shè)置(SETUP)事務(wù)處理和幀開始、幀結(jié)尾等類型。在輸出(OUT)事務(wù)處理和設(shè)置(SETUP)事務(wù)處理中,緊接著SETUP和OUT包后的是DATA包,DATA0和DATA1包是交替地發(fā)送的,在DATA包后面,設(shè)備將回應(yīng)一個握手信號,如果設(shè)備可以接收數(shù)據(jù),就回應(yīng)ACK包,如果設(shè)備忙,就回應(yīng)NAK包,如果設(shè)備出錯,則回應(yīng)STALL包;在IN事務(wù)中,IN包后面是設(shè)備發(fā)來的DATA包或NAK包或STALL包,若設(shè)備忙或出錯,就發(fā)NAK包或STALL包給主機,若設(shè)備數(shù)據(jù)準備好發(fā)送,則發(fā)DATA包,DATA0和DATA1包也是交替地發(fā)送的,緊接著DATA包后面是主機發(fā)給設(shè)備的握手包,ACK表示主機可以接收數(shù)據(jù),NAK包代表主機忙,STALL包代表主機出錯。

4.3.1、輸入(IN)事務(wù)處理

       輸入事務(wù)處理表示USB主機從總線上的某個USB設(shè)備接收一個數(shù)據(jù)包的過程。

      ①正常的輸入事務(wù)處理

1. 主機->設(shè)備(令牌包)SYNCIN    ADDR   ENDPCRC5
2. 設(shè)備->主機(數(shù)據(jù)包)SYNCDATA0DATA                 CRC16
3. 主機->設(shè)備(握手包)SYNCACK
       ②設(shè)備忙時的輸入事務(wù)處理  

1. 主機->設(shè)備(令牌包)SYNCIN    ADDR   ENDPCRC5
3. 主機->設(shè)備(握手包)SYNCNAK
      ③設(shè)備出錯時的輸入事務(wù)處理

1. 主機->設(shè)備(令牌包)SYNCIN    ADDR   ENDPCRC5
3. 主機->設(shè)備(握手包)SYNCSTALL

4.3.2、輸出(OUT)事務(wù)處理

       輸入事務(wù)處理表示USB主機從總線上的某個USB設(shè)備接收一個數(shù)據(jù)包的過程。

       ①正常的輸入事務(wù)處理

1. 主機->設(shè)備(令牌包)SYNCOUT   ADDR   ENDPCRC5
2. 主機->設(shè)備(數(shù)據(jù)包)SYNCDATA0DATA                 CRC16
3. 設(shè)備->主機(握手包)SYNCACK

②設(shè)備忙時的輸入事務(wù)處理

1. 主機->設(shè)備(令牌包)SYNCOUT   ADDR   ENDPCRC5
2. 主機->設(shè)備(數(shù)據(jù)包)SYNCDATA0DATA                 CRC16
3. 設(shè)備->主機(握手包)SYNCNAK

③設(shè)備出錯時的輸入事務(wù)處理

1. 主機->設(shè)備(令牌包)SYNCOUT   ADDR   ENDPCRC5
2. 主機->設(shè)備(數(shù)據(jù)包)SYNCDATA0DATA                 CRC16
3. 設(shè)備->主機(握手包)SYNCSTALL

4.3.3、設(shè)置(SETUP)事務(wù)處理

     輸入事務(wù)處理表示USB主機從總線上的某個USB設(shè)備接收一個數(shù)據(jù)包的過程。

      ①正常的輸入事務(wù)處理

1. 主機->設(shè)備(令牌包)SYNCSETUP  ADDR   ENDPCRC5
2. 主機->設(shè)備(數(shù)據(jù)包)SYNCDATA0DATA                 CRC16
3. 設(shè)備->主機(握手包)SYNCACK

     ②設(shè)備忙時的輸入事務(wù)處理   

1. 主機->設(shè)備(令牌包)SYNCSETUP   ADDR   ENDPCRC5
2. 主機->設(shè)備(數(shù)據(jù)包)SYNCDATA0DATA                 CRC16
3. 設(shè)備->主機(握手包)SYNCNAK

    ③設(shè)備出錯時的輸入事務(wù)處理

1. 主機->設(shè)備(令牌包)SYNCSETUP   ADDR   ENDPCRC5
2. 主機->設(shè)備(數(shù)據(jù)包)SYNCDATA0DATA                 CRC16
3. 設(shè)備->主機(握手包)SYNCSTALL

4.4、USB的傳輸類型

       在USB的傳輸中,制定了4種傳輸類型:控制傳輸、中斷傳輸、批量傳輸以及等時傳輸??刂苽鬏旑愋头譃?~3個階段:設(shè)置階段、數(shù)據(jù)階段(無數(shù)據(jù)控制沒有此階段)以及狀態(tài)階段。根據(jù)數(shù)據(jù)階段的數(shù)據(jù)傳輸?shù)姆较颍刂苽鬏斢挚煞譃?種類型:控制讀?。ㄗx取USB描述符)、控制寫入(配置USB設(shè)備)以及無數(shù)據(jù)控制。

4.4.1、控制傳輸

        控制傳輸是USB傳輸中最重要的傳輸。它包含3種類型:控制讀取、控制寫入以及無數(shù)據(jù)控制。這3種控制傳輸類型又分為2~3個階段:設(shè)置階段、數(shù)據(jù)階段(無數(shù)據(jù)控制沒有此階段)以及狀態(tài)階段。

階段一:設(shè)置階段

         主機從USB設(shè)備獲取配置信息,并設(shè)置設(shè)備的配置值。設(shè)置階段的數(shù)據(jù)交換包含了SETUP令牌封包、緊隨其后的DATA0數(shù)據(jù)封包以及ACK握手封包。它的作用是執(zhí)行一個設(shè)置(概念含糊)的數(shù)據(jù)交換,并定義此控制傳輸?shù)膬?nèi)容。

階段二:數(shù)據(jù)傳輸階段

        數(shù)據(jù)傳輸階段用來傳輸主機與設(shè)備之間的數(shù)據(jù)??刂谱x取是將數(shù)據(jù)從設(shè)備讀到主機上,讀取的數(shù)據(jù)USB設(shè)備描述符。該過程如圖16-8所示。對每一個數(shù)據(jù)信息包而言,首先,主機會發(fā)送一個IN令牌信息包,表示要讀數(shù)據(jù)進來。然后,設(shè)備將數(shù)據(jù)通過DATA1數(shù)據(jù)信息包回傳給主機。最后,主機將以下列的方式加以響應(yīng):當數(shù)據(jù)已經(jīng)正確接收時,主機送出ACK令牌信息包;當主機正在忙碌時,發(fā)出NAK握手信息包;當發(fā)生了錯誤時,主機發(fā)出STALL握手信息包。

        控制寫入則是將數(shù)據(jù)從主機傳到設(shè)備上,所傳的數(shù)據(jù)即為對USB設(shè)備的配置信息,該過程如圖16-9所示。對每一個數(shù)據(jù)信息包而言,主機將會送出一個OUT令牌信息包,表示數(shù)據(jù)要送出去。緊接著,主機將數(shù)據(jù)通過DATA0數(shù)據(jù)信息包傳遞至設(shè)備。最后,設(shè)備將以下列方式加以響應(yīng):當數(shù)據(jù)已經(jīng)正確接收時,設(shè)備送出ACK令牌信息包;當設(shè)備正在忙碌時,設(shè)備發(fā)出NAK握手信息包;當發(fā)生了錯誤時,設(shè)備發(fā)出STALL握手信息包。

圖7  控制讀取的IN數(shù)據(jù)交換的過程示意圖           圖 8   控制寫入的OUT數(shù)據(jù)交換的過程示意圖

階段三:狀態(tài)階段

         狀態(tài)階段用來表示整個傳輸?shù)倪^程已完全結(jié)束。狀態(tài)階段傳輸?shù)姆较虮仨毰c數(shù)據(jù)階段的方向相反,即原來是IN令牌封包,這個階段應(yīng)為OUT令牌封包;反之,原來是OUT令牌封包,這個階段應(yīng)為IN令牌封包。對于控制讀取而言,主機會送出OUT令牌封包,其后再跟著0長度的DATA1封包。而此時,設(shè)備也會做出相對應(yīng)的動作,送ACK握手封包、NAK握手封包或STALL握手封包。相對地對于控制寫入傳輸,主機會送出IN令牌封包,然后設(shè)備送出表示完成狀態(tài)階段的0長度的DATA1封包,主機再做出相對應(yīng)的動作:送ACK握手封包、NAK握手封包或STALL握手封包。

4.4.2、實時傳輸

        實時傳輸適用于必須以固定速率抵達或在指定時刻抵達,可以容忍偶爾錯誤的數(shù)據(jù)上。實時傳輸一般用于麥克風(fēng)、喇叭等設(shè)備。實時傳輸只需令牌與數(shù)據(jù)兩個信息包階段,沒有握手包,故數(shù)據(jù)傳錯時不會重傳。

4.4.3、批量傳輸

      用于傳輸大量數(shù)據(jù),要求傳輸不能出錯,但對時間沒有要求,適用于打印機、存儲設(shè)備等。

4.4.4、中斷傳輸

      中斷傳輸方式總是用于對設(shè)備的查詢,以確定是否有數(shù)據(jù)需要傳輸。因此中斷傳輸?shù)姆较蚩偸菑腢SB設(shè)備到主機。

4.5、設(shè)備列舉

4.5.1、描述符

        USB描述符就好像是USB外圍設(shè)備的“身份證”一樣,詳細地記錄著外圍設(shè)備相關(guān)的一切信息。為了描述不同的數(shù)據(jù),就需以不同類型的USB描述符來加以描述,它共有以下幾種類型:設(shè)備描述符、配置描述符、接口描述符和端點描述符,這幾個描述符是必須具有的,下面將結(jié)合實例詳細介紹;其他的描述符,例如,字符串描述符、數(shù)種不同的群組描述符以及報告描述符則可以根據(jù)不同的設(shè)備進行選擇。

(1)設(shè)備描述符

       設(shè)備描述符具有 18 字節(jié)的長度,并且是主機向設(shè)備請求的第一個描述符。 以下列出設(shè)備描述符的范例、數(shù)值以及各個字段的意義(以C語言偽代碼表示):

typedef struct _USB_DEVICE_DESCRIPTOR { BYTE bLength; //0x12, 表示該描述符的字節(jié)長度為18個字節(jié), BYTE bDescriptorType; //描述符類型,1代表設(shè)備 WORD bcdUSB; BYTE bDeviceClass; BYTE bDeviceSubClass; BYTE bDeviceProtocol; BYTE bMaxPacketSize0; WORD idVendor; WORD idProduct; WORD bcdDevice; BYTE iManufacturer; BYTE iProduct; BYTE iSerialNumber; BYTE bNumConfigurations;} USB_DEVICE_DESCRIPTOR;

        bLength是本結(jié)構(gòu)的數(shù)據(jù)長度,這樣可以方便以后兼容不同的版本協(xié)議。因為不同的結(jié)構(gòu)是不同的長度,這樣就可以區(qū)分不同的協(xié)議了。比如有一天想添加一個字段,那么它的長度就會改變,這時就可以根據(jù)不同的長度進行解釋不同的協(xié)議了。這次返回的結(jié)構(gòu)長度是0x12,也就是18個字節(jié),它的長度是從bLength長度開始,也就是說是完全整個結(jié)構(gòu)的長度。
        bDescriptorType是描述符的類型。它的定義跟主控器發(fā)下來描述符的類型是一樣的,如下:
類型類型
DEVICE                             1            ENDPOINT5          
CONFIGURATION2DEVICE_QUALIFIER6
STRING  3OTHER_SPEED_CONFIGURATION7
INTERFACE4INTERFACE_POWER18
                                               表3、描述符類型
由于返回的是設(shè)備描述符,所以就選擇了1,也就是包里顯示的第二個字節(jié)01。用這個類型來區(qū)分不同的描述符。

        bcdUSB是USB發(fā)布的協(xié)議版本。也就是本設(shè)備能適用于那種協(xié)議,目前USB主要有兩個版本,一個是1.10,一個是2.10版本。在本設(shè)備里,采用了1.10的協(xié)議版本。由于這個字段是采用BCD編碼,所以1.10的表示為0x0110的格式,0x0210就表示USB2.10版本。

        bDeviceClass是設(shè)備分類。當它的值是0時,表示所有接口在配置描述符里,并且所有接口是獨立的。當它的值是1到FEH時,表示不同的接口關(guān)聯(lián)的。當它的值是FFH時,它是廠商自己定義的。在這個設(shè)備里,是定義為0。

        bDeviceSubClass是設(shè)備子分類碼。當前面的bDeviceClass值是0時,這里一定要設(shè)置為0。其它就跟據(jù)USB-IF組織定義的編碼。

        bDeviceProtocol是設(shè)備使用的協(xié)議。如果使用USB-IF組織定義的協(xié)議,就需要設(shè)置這里的值。如果不使用,就直接設(shè)置為0。如果廠商自己定義的可以設(shè)置為FFH。

        bMaxPacketSize0是端點0收發(fā)最大的包大小。僅允許設(shè)置8,16,32,64中的任何一個大小。

        idVendor是廠商標識。由USB-IF分配的編碼。

        idProduct是廠商定義的產(chǎn)品標識。由廠家和產(chǎn)品標識,就可以讓操作系統(tǒng)加載不同的驅(qū)動程序。

        bcdDevice是用BCD表示的設(shè)備發(fā)布的版本號。

        iManufacturer是廠商字符串的偏移值。這值主要說明了它在字符串描述符里的偏移位置。如果它設(shè)置為0,表示沒有廠商字符串。字符串描述符后面會講到。

        iProduct是產(chǎn)品字符串的偏移值。這值主要說明了它在字符串描述符里的偏移位置。如果它設(shè)置為0,表示沒有產(chǎn)品字符串。字符串描述符后面會講到。

        iSerialNumber是序列號字符串的偏移值。這值主要說明了它在字符串描述符里的偏移位置。如果它設(shè)置為0,表示沒有序列號字符串。所有字符串,都是采有UNICODE編碼。

        bNumConfigurations是配置描述符的個數(shù)。在這里只使用了一個配置,所以設(shè)置為1。

2)配置描述符

     配置描述符具有 9 字節(jié)的長度,針對設(shè)備給予配置的信息。以下列出配置 描述符的范例、數(shù)值以及各個字段的意義:

typedef struct _USB_CONFIGURATION_DESCRIPTOR { BYTE bLength; //是配置的長度,也就是配置結(jié)構(gòu)的整個長度。在這里9個字節(jié)。 BYTE bDescriptorType; //是描述符的類型,這里配置描述符,所以設(shè)置為02。具體含義見表3 WORD wTotalLength; //是所有配置設(shè)置的結(jié)構(gòu)長度。包括配置描述符、接口描述符、HID或者其它描述符和端點描述符的長度。 BYTE bNumInterfaces; //該配置支持的接口數(shù)目(1字節(jié)) BYTE bConfigurationValue; //配置值,作為Set Configuration請求的配置值 BYTE iConfiguration; //是說明配置的字符的偏移值 BYTE bmAttributes; //是配置特性,D7位保留。D6位是說明是否自供電。D5位是否支持遠程喚醒。D4—D0是保留,設(shè)置為0。 BYTE MaxPower; //是使用的功率,它采用電流來表示。每2mA為單位,比如它的值是50時就表示是100mA的電流消耗。
//通過這樣說明,主控器就知道這個設(shè)備是什么樣的設(shè)備,有多少功能。} USB_CONFIGURATION_DESCRIPTOR;

3)接口描述符

      接口描述符具有 9 字節(jié)的長度,用來描述每一個設(shè)備的接口特性。以下列 出接口描述符的范例、數(shù)值以及各個字段的意義:

typedef struct _USB_INTERFACE_DESCRIPTOR { BYTE bLength; //表示該描述符的字節(jié)長度為9個字節(jié). BYTE bDescriptorType; //描述符類型,4代表接口。具體含義見表3 BYTE bInterfaceNumber; //接口數(shù)目以0為基值(表示一個接口)。 BYTE bAlternateSetting; //域,交互設(shè)置值為0(因為只有一個接口) BYTE bNumEndpoints; //端點數(shù)目設(shè)置為2 BYTE bInterfaceClass; //接口群組,$FF表示是供應(yīng)商說明書 BYTE bInterfaceSubClass; //接口次群組 BYTE bInterfaceProtocol; //接口協(xié)議,$FF表示該接口使用的 ;是供應(yīng)商說明的協(xié)議 BYTE iInterface; //接口的字符串描述符的索引,本實例沒有 }USB_INTERFACE_DESCRIPTOR;

(4)端點描述符

        端點描述符具有 7 字節(jié)長度,用來描述端點的屬性以及各個端點的位置。 該實例中有兩個端點,bEndpointAddress域的值不同,來區(qū)別IN/OUT端點

typedef struct _USB_ENDPOINT_DESCRIPTOR { BYTE bLength; //表示該描述符的字節(jié)長度為 7 個字節(jié) BYTE bDescriptorType; //描述符類型,5代表端點。具體含義見表3 BYTE bEndpointAddress; //端點地址([0x81=IN,0x02=OUT]) BYTE bmAttributes; //傳輸類型的屬性設(shè)置為中斷傳輸 ;(0=控制,1=等時,2=批量,3=中斷) WORD wMaxPacketSize; //域,最大信息包的大小設(shè)置為8個字節(jié) BYTE bInterval; //輪詢間隔,以ms為單位,在此設(shè)置為10m,0xA, }USB_ENDPOINT_DESCRIPTOR;
(5) 字符串描述符
ypedef struct _USB_STRING_DESCRIPTOR { BYTE bLength; //是所有數(shù)據(jù)的長度。具體長度根據(jù)bString的長度而定 BYTE bDescriptorType; //是描述類型,這里字符串描述符,所以它是3 WORD bString/*[]*/; //是可變的字符數(shù)組。不超過254個應(yīng)都可以的,并且它是使用UNICODE編碼的字符串。美國英語的標識,0x0409。中文的標識=0x0804。
//通過這個字符串描述符,主控器就知道字符串描述符是使用什么語言說明的了,這樣就可以支持全世界的語言標識。
} USB_STRING_DESCRIPTOR;

4.5.2.USB請求

   主機要獲取相關(guān)信息,需要發(fā)送配置包,用C代碼定義如下:

typedef struct _USB_SETUP_PACKET{ REQUEST_TYPE bmRequestType; BYTE bRequest; WORD_BYTE wValue; WORD_BYTE wIndex; WORD wLength;} USB_SETUP_PACKET;

       bmRequestType是包含有下面幾方面的內(nèi)容:D7 D6 D5 D4 D3 D2 D1 D0

        在這一個字節(jié)里,又按位分為:D7位是表示后面?zhèn)魉蛿?shù)據(jù)的方向位。當D7等于0時,表示后面的數(shù)據(jù)是從主控器發(fā)送到USB設(shè)備。在PC里,就是從PC機發(fā)送到USB的設(shè)備。當D7等于1時,表示后面的數(shù)據(jù)是從USB設(shè)備發(fā)送到主控器。在PC里,就是從USB設(shè)備發(fā)送到USB設(shè)備。

        D6-D5位是請求主分類型:0 是表示標準的請求。1 是表示類別的請求。2 是表示廠商的請求。3 是保留。

        D4-D0位是表求接收這個包的接口。0 是表示USB設(shè)備接收。1 是表示接口接收。2 是表示端點接收。3 是表示其它接收,不知道的。4-31是保留。

     bRequest是本描述符的請求類型,也就是后面發(fā)送的數(shù)據(jù)是什么樣的東西。由于USB里有很多配置信息,比如獲取設(shè)備描述符,又有設(shè)置USB地址等等,就是通過這個字節(jié)來區(qū)分的。

類型類型
0     GET_STATUS 7    SET_DESCRIPTOR
1CLEAR_FEATURE8GET_CONFIGURATION
2Reserved for future use9SET_CONFIGURATION
3SET_FEATURE10GET_INTERFACE
4Reserved for future use11SET_INTERFACE
5SET_ADDRESS12SYNCH_FRAME
6GET_DESCRIPTOR  

                                 表4: 請求描述符的類型。

   主控器想讀取USB設(shè)備的描述符,那么bRequest的值就應(yīng)該是0x06.

        wValue是根據(jù)不同的請求而設(shè)置不同的值。一般就是傳送參數(shù)給設(shè)備標明這是什么請求。在上面GET_DESCRIPTOR獲取設(shè)備描述符里,它的值是00 01。在GET_DESCRIPTOR里這個字段的低字節(jié)表示描述符的索引,高字節(jié)表示描述符的類型。高字節(jié)的類型如表3所示。wValue值在這里的高字節(jié)是01,那么它就是設(shè)備描述符了。低字節(jié)是00,那么它就是表示從偏移地址0開始讀取設(shè)備描述符。由于在配置描述符里有很多配置,所以低字節(jié)在那里就可以用來識別獲取同樣類型的描述符不同的配置。

        wIndex是根據(jù)不同的請求而設(shè)置不同的值。一般用來說明端點號或者說明接口標識。在獲取描述符里,設(shè)置為0,或者是語言ID。在這個發(fā)送的描述符里,它是設(shè)置為00 00。

        wLength是根據(jù)請求來決定下一階段發(fā)送數(shù)據(jù)的長度。前面請求第一個字節(jié)里,已經(jīng)說明下一階段數(shù)據(jù)傳送的方向,這里說明了傳送數(shù)據(jù)的長度。不管是發(fā)送數(shù)據(jù),還是接收數(shù)據(jù),都不要超過這個數(shù)據(jù)長度,否則主機會出問題,或者設(shè)備有問題。

面結(jié)合實例分別介紹幾個主要的設(shè)備請求。

(1) 清除特性(Clear Feature):

bmRequestTypebRequestwValuewIndexwLengthdata
00000000B(0端點)
00000001B(1端點)
00000010B(2端點)
CLEAR_FEATUR
(01H)
特性選擇0接口端點0
        該請求中的wValue表示特性選擇器,它對應(yīng)的值為:0=端點,1=設(shè)備。當某個特點不允許取消,或該特性根本不存在,或者是指向一個根本不存在的接口或端點時,該請求將會導(dǎo)致設(shè)備請求失敗。如果端點被固件設(shè)為停止狀態(tài),主機軟件(總線驅(qū)動程序)也可以發(fā)送一個值為0的CLEAR_FEATURE命令清除該端點的停止狀態(tài),本實例中就是這樣使用該請求的。

(2) 取得描述符(Get Descriptor)

bmRequestTypebRequestwValuewIndexwLengthdata
10000000BGET_DESCRIPTOR
(06H)
描述符類型與描述符指針0或語言ID描述符的長度各個描述符
        該請求中的wValue的高字節(jié)表示要取的描述符類型,低字節(jié)表示描述符的索引值,描述的類型有:1表示設(shè)備描述符,2表示配置描述符,3表示字符串描述符,4表示接口描述符,5表示端點描述符。wIndex的值為0或語言ID;當要取的描述符是字符串描述符時,該域的值為語言ID;當為其他的描述符時,該域為0。wLength表示要返回的數(shù)據(jù)長度,如果SETUP階段的地址使用的是預(yù)設(shè)地址0(ENDP字段為0),這時的wLength值會大于實際的描述的值。這是為什么呢?原因是用戶以預(yù)設(shè)的地址0來取得設(shè)備描述符時,不管設(shè)多少字節(jié),用戶最多只取其前8字節(jié),即在控制傳輸過程只有一次數(shù)據(jù)階段。但是,如果用戶以新的地址(ENDP字段不為0)來取得設(shè)備描述符時,這時wLength的值就要注意了。

(3) 設(shè)置地址(Set Address)

bmRequestTypebRequestwValuewIndexwLengthdata
10000000BSET_ADDRESS(05H)設(shè)備地址00
        該請求與其他的請求有一個重要的不同點,該請求下,USB設(shè)備一直不改變它的地址,直到該請求的狀態(tài)階段被成功地完成,而其他請求的操作都是在狀態(tài)階段之前完成,可以閱讀本實例加深對該點的理解。若特定的設(shè)備地址大于127,或者wIndex 或wLength為非0值,那么該請求不執(zhí)行。

(4) 設(shè)置配置(Set Configuration)

bmRequestTypebRequestwValuewIndexwLengthdata
00000000B(0端點)
00000001B(1端點)
00000010B(2端點)
CLEAR_FEATUR
(01H)
特性選擇0接口端點0
        該請求中的wValue域的低字節(jié)表示設(shè)置的值,該值必須為0或者與配置描述符中的配置值相匹配。如果設(shè)置值等于0,表示設(shè)備在地址狀態(tài)。如果wIndex 或 wLength為非0值,那么該請求不執(zhí)行。

4.5.3、設(shè)備列舉

      設(shè)備列舉可以簡單地概括為這樣的一個過程:主機通過USB設(shè)備請求來取得設(shè)備描述符并對該設(shè)備進行配置。該過程可以簡化為如下5個步驟:
第一步,使用預(yù)設(shè)的地址0取得設(shè)備描述符。
第二步,設(shè)置設(shè)備的新地址。
第三步,使用新地址取得設(shè)備描述符。
第四步,取得配置描述符。
第五步,設(shè)置配置描述符。
        設(shè)備列舉使用的是控制傳輸。上述的5個步驟必須符合控制傳輸?shù)幕炯軜?gòu),第一步、第三步和第四步使用的是控制讀取,第二步和第五步使用的是無數(shù)據(jù)控制。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多