W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
一個(gè) USB 設(shè)備是一個(gè)非常復(fù)雜的事物, 如同在官方的 USB 文檔(可從 http://www.usb.org 中得到)中描述的. 幸運(yùn)的是, Linux 提供了一個(gè)子系統(tǒng)稱為 USB 核, 來(lái)處理大部分復(fù)雜的工作. 這一章描述驅(qū)動(dòng)和 USB 核之間的交互. 圖USB 設(shè)備概覽顯示了 USB 設(shè)備如何包含配置, 接口, 和端點(diǎn), 以及 USB 驅(qū)動(dòng)如何綁定到 USB 接口, 而不是整個(gè) USB 設(shè)備.
USB 通訊的最基本形式是通過(guò)某些稱為 端點(diǎn) 的. 一個(gè) USB 端點(diǎn)只能在一個(gè)方向承載數(shù)據(jù), 或者從主機(jī)到設(shè)備(稱為輸出端點(diǎn))或者從設(shè)備到主機(jī)(稱為輸入端點(diǎn)). 端點(diǎn)可看作一個(gè)單向的管道.
一個(gè) USB 端點(diǎn)可是 4 種不同類型的一種, 它來(lái)描述數(shù)據(jù)如何被傳送:
CONTROL
控制端點(diǎn)被用來(lái)允許對(duì) USB 設(shè)備的不同部分存取. 通常用作配置設(shè)備, 獲取關(guān)于設(shè)備的信息, 發(fā)送命令到設(shè)備, 或者獲取關(guān)于設(shè)備的狀態(tài)報(bào)告. 這些端點(diǎn)在尺寸上常常較小. 每個(gè) USB 設(shè)備有一個(gè)控制端點(diǎn)稱為"端點(diǎn) 0", 被 USB 核用來(lái)在插入時(shí)配置設(shè)備. 這些傳送由 USB 協(xié)議保證來(lái)總有足夠的帶寬使它到達(dá)設(shè)備.
INTERRUPT
中斷端點(diǎn)傳送小量的數(shù)據(jù), 以固定的速率在每次 USB 主請(qǐng)求設(shè)備數(shù)據(jù)時(shí). 這些端點(diǎn)對(duì) USB 鍵盤(pán)和鼠標(biāo)來(lái)說(shuō)是主要的傳送方法. 它們還用來(lái)傳送數(shù)據(jù)到 USB 設(shè)備來(lái)控制設(shè)備, 但通常不用來(lái)傳送大量數(shù)據(jù). 這些傳送由 USB 協(xié)議保證來(lái)總有足夠的帶寬使它到達(dá)設(shè)備.
BULK
塊端點(diǎn)傳送大量的數(shù)據(jù). 這些端點(diǎn)常常比中斷端點(diǎn)大(它們一次可持有更多的字符). 它們是普遍的, 對(duì)于需要傳送不能有任何數(shù)據(jù)丟失的數(shù)據(jù). 這些傳送不被 USB 協(xié)議保證來(lái)一直使它在特定時(shí)間范圍內(nèi)完成. 如果總線上沒(méi)有足夠的空間來(lái)發(fā)送整個(gè) BULK 報(bào)文, 它被分為多次傳送到或者從設(shè)備. 這些端點(diǎn)普遍在打印機(jī), 存儲(chǔ)器, 和網(wǎng)絡(luò)設(shè)備上.
ISOCHRONOUS
同步端點(diǎn)也傳送大量數(shù)據(jù), 但是這個(gè)數(shù)據(jù)常常不被保證它完成. 這些端點(diǎn)用在可以處理數(shù)據(jù)丟失的設(shè)備中, 并且更多依賴于保持持續(xù)的數(shù)據(jù)流. 實(shí)時(shí)數(shù)據(jù)收集, 例如音頻和視頻設(shè)備, 一直都使用這些端點(diǎn).
控制和塊端點(diǎn)用作異步數(shù)據(jù)傳送, 無(wú)論何時(shí)驅(qū)動(dòng)決定使用它們. 中斷和同步端點(diǎn)是周期性的. 這意味著這些端點(diǎn)被設(shè)置來(lái)連續(xù)傳送數(shù)據(jù)在固定的時(shí)間, 這使它們的帶寬被 USB 核所保留.
USB 端點(diǎn)在內(nèi)核中使用結(jié)構(gòu) struct usb_host_endpoint 來(lái)描述. 這個(gè)結(jié)構(gòu)包含真實(shí)的端點(diǎn)信息在另一個(gè)結(jié)構(gòu)中, 稱為 struct usb_endpoint_descriptor. 后者包含所有的 USB-特定 數(shù)據(jù), 以設(shè)備自身特定的準(zhǔn)確格式. 驅(qū)動(dòng)關(guān)心的這個(gè)結(jié)構(gòu)的成員是:
bEndpointAddress
這是這個(gè)特定端點(diǎn)的 USB 地址. 還包含在這個(gè) 8-位 值的是端點(diǎn)的方向. 位掩碼 USB_DIR_OUT 和 USB_DIR_IN 可用來(lái)和這個(gè)成員比對(duì), 來(lái)決定給這個(gè)端點(diǎn)的數(shù)據(jù)是到設(shè)備還是到主機(jī).
bmAttributes
這是端點(diǎn)的類型. 位掩碼 USB_ENDPOINT_XFERTYPE_MASK 應(yīng)當(dāng)用來(lái)和這個(gè)值比對(duì), 來(lái)決定這個(gè)端點(diǎn)是否是 USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, 或者是類型 USB_ENDPOINT_XFER_INT. 這些宏定義了同步, 塊, 和中斷端點(diǎn), 相應(yīng)地.
wMaxPacketSize
這是以字節(jié)計(jì)的這個(gè)端點(diǎn)可一次處理的最大大小. 注意驅(qū)動(dòng)可能發(fā)送大量的比這個(gè)值大的數(shù)據(jù)到端點(diǎn), 但是數(shù)據(jù)會(huì)被分為 wMaxPakcetSize 的塊, 當(dāng)真正傳送到設(shè)備時(shí). 對(duì)于高速設(shè)備, 這個(gè)成員可用來(lái)支持端點(diǎn)的一個(gè)高帶寬模式, 通過(guò)使用幾個(gè)額外位在這個(gè)值的高位部分. 關(guān)于如何完成的細(xì)節(jié)見(jiàn) USB 規(guī)范.
bInterval
如果這個(gè)端點(diǎn)是中斷類型的, 這個(gè)值是為這個(gè)端點(diǎn)設(shè)置的間隔, 即在請(qǐng)求端點(diǎn)的中斷之間的時(shí)間. 這個(gè)值以毫秒表示.
這個(gè)結(jié)構(gòu)的成員沒(méi)有一個(gè)"傳統(tǒng)" Linux 內(nèi)核的命名機(jī)制. 這是因?yàn)檫@些成員直接對(duì)應(yīng)于 USB 規(guī)范中的名子. USB 內(nèi)核程序員認(rèn)為使用規(guī)定的名子更重要, 以便在閱讀規(guī)范時(shí)減少混亂, 不必使這些名子對(duì) Linux 程序員看起來(lái)熟悉.
USB 端點(diǎn)被綁在接口中. USB 接口只處理一類 USB 邏輯連接, 例如一個(gè)鼠標(biāo), 一個(gè)鍵盤(pán), 或者一個(gè)音頻流. 一些 USB 設(shè)備有多個(gè)接口, 例如一個(gè) USB 揚(yáng)聲器可能有 2 個(gè)接口: 一個(gè) USB 鍵盤(pán)給按鈕和一個(gè) USB 音頻流. 因?yàn)橐粋€(gè) USB 接口表示基本的功能, 每個(gè) USB 驅(qū)動(dòng)控制一個(gè)接口; 因此, 對(duì)揚(yáng)聲器的例子, Linux 需要 2 個(gè)不同的驅(qū)動(dòng)給一個(gè)硬件設(shè)備.
USB 接口可能有預(yù)備的設(shè)置, 是對(duì)接口參數(shù)的不同選擇. 接口的初始化的狀態(tài)是第一個(gè)設(shè)置, 0 號(hào). 預(yù)備的設(shè)置可用來(lái)以不同方式控制單獨(dú)的端點(diǎn), 例如來(lái)保留不同量的 USB 帶寬給設(shè)備. 每個(gè)有同步端點(diǎn)的設(shè)備使用預(yù)備設(shè)備給同一個(gè)接口.
USB 接口在內(nèi)核中使用 struct usb_interface 結(jié)構(gòu)來(lái)描述. 這個(gè)結(jié)構(gòu)是 USB 核傳遞給 USB 驅(qū)動(dòng)的并且是 USB 驅(qū)動(dòng)接下來(lái)負(fù)責(zé)控制的. 這個(gè)結(jié)構(gòu)中的重要成員是:
struct usb_host_interface *altsetting
一個(gè)包含所有預(yù)備設(shè)置的接口結(jié)構(gòu)的數(shù)組, 可被挑選給這個(gè)接口. 每個(gè) struct usb_host_interface 包含一套端點(diǎn)配置, 如同由 struct usb_host_endpoint 結(jié)構(gòu)所定義的. 注意這些接口結(jié)構(gòu)沒(méi)有特別的順序.
unsigned num_altsetting
由 altsetting 指針指向的預(yù)備設(shè)置的數(shù)目.
struct usb_host_interface *cur_altsetting
指向數(shù)組 altsetting 的一個(gè)指針, 表示這個(gè)接口當(dāng)前的激活的設(shè)置.
int minor
如果綁定到這個(gè)接口的 USB 驅(qū)動(dòng)使用 USB 主編號(hào), 這個(gè)變量包含由 USB 核心安排給接口的次編號(hào). 這只在一次成功地調(diào)用 usb_register_dev (本章稍后描述)之后才有效.
在 struct usb_interface 結(jié)構(gòu)中有其他成員, 但是 USB 驅(qū)動(dòng)不需要知道它們.
USB 接口是自己被捆綁到配置的. 一個(gè) USB 設(shè)備可有多個(gè)配置并且可能在它們之間轉(zhuǎn)換以便改變?cè)O(shè)備的狀態(tài). 例如, 一些允許固件被下載到它們的設(shè)備包含多個(gè)配置來(lái)實(shí)現(xiàn)這個(gè). 一個(gè)配置只能在一個(gè)時(shí)間點(diǎn)上被使能. Linux 處理多配置 USB 設(shè)備不是太好, 但是, 幸運(yùn)的是, 它們很少.
linux 描述 USB 配置使用結(jié)構(gòu) struct usb_host_config 和整個(gè) USB 設(shè)備使用結(jié)構(gòu) struct usb_device. USB 設(shè)備驅(qū)動(dòng)通常不會(huì)需要讀寫(xiě)這些結(jié)構(gòu)的任何值, 因此它們?cè)谶@里沒(méi)有詳細(xì)定義. 好奇的讀者可在內(nèi)核源碼樹(shù)的文件 include/linux/usb.h 中找到對(duì)它們的描述.
一個(gè) USB 設(shè)備驅(qū)動(dòng)通常不得不轉(zhuǎn)換數(shù)據(jù)從給定的 struct usb_interface 結(jié)構(gòu)到 struct usb_device 結(jié)構(gòu), USB 核心需要給很多的函數(shù)調(diào)用. 為此, 提供有函數(shù) interface_to_usbdev. 在以后, 希望所有的當(dāng)前需要一個(gè) struct usb_device 的 USB 調(diào)用, 將被轉(zhuǎn)換為采用一個(gè) struct usb_interface 參數(shù), 并且不會(huì)要求驅(qū)動(dòng)做這個(gè)轉(zhuǎn)換.
所以總結(jié), USB 設(shè)備是非常復(fù)雜的, 并且由許多不同邏輯單元組成. 這些單元之間的關(guān)系可簡(jiǎn)單地描述如下:
設(shè)備通常有一個(gè)或多個(gè)配置.
配置常常有一個(gè)或多個(gè)接口
接口常常有一個(gè)或多個(gè)設(shè)置.
接口有零或多個(gè)端點(diǎn).
[45] 本章的多個(gè)部分是基于內(nèi)核中的給 Linux 內(nèi)核 USB 代碼的文檔, 這些代碼由內(nèi)核 USB 開(kāi)發(fā)者編寫(xiě)并且以 GPL 發(fā)布.
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: