本文提供有關仔細管理 USB 頻寬的指引。 每個 USB 用戶端驅動程式都有責任將其使用的 USB 頻寬降到最低,並儘快將未使用的頻寬傳回可用頻寬集區。
為什麼我的 USB 驅動程序會遇到帶寬錯誤?
USB 匯流排上的頻寬競爭來自多個來源,包括硬體和軟體。 很難確切預測 USB 用戶端驅動程式可用的頻寬量。 USB 主機控制器的運作需要一定的頻寬。 所需的量取決於控制器是否高速。 它因系統而異。 高速運作的 USB 中樞有時必須轉譯高速上游埠與下游低速裝置之間的交易,而此轉譯程式會耗用頻寬。 但交易轉譯是否需要頻寬,取決於所連接的裝置類型及裝置樹狀結構的拓蹼。
頻寬資源最嚴重的壓力通常來自壟斷頻寬的 USB 用戶端驅動程式。 系統以先到先得的方式分配頻寬。 如果載入的第一個 USB 驅動程式要求所有可用的頻寬,則稍後載入的 USB 驅動程式不允許其裝置有任何頻寬。 系統無法設定裝置,而且無法列舉裝置。 由於列舉失敗的原因不明顯,因此使用者的體驗很差。
有時,用戶端驅動程式會耗盡高速中斷傳輸的可用頻寬。 但到目前為止,最常見的情況是用戶端驅動程式為同步傳輸配置了太多頻寬,然後無法及時釋放頻寬。 系統會保留配置的頻寬,直到要求它的驅動程式關閉其端點 (藉由開啟另一個端點) ,或移除配置頻寬的裝置為止。 系統不會為大量傳輸配置保證的頻寬,因此大量傳輸永遠不會是列舉失敗的原因。 不過,大量傳輸裝置的效能取決於為執行定期 (同步和中斷) 傳輸的裝置配置的頻寬量。
USB 2.0 規格要求同步裝置在其預設介面設定上具有零頻寬端點。 這可確保在函式驅動程式開啟非預設介面之前,不會為裝置保留任何頻寬,這有助於防止裝置設定期間因過多頻寬要求所造成列舉失敗。 它不會防止用戶端驅動程式在設定其裝置之後配置太多頻寬,從而防止其他裝置正常運作。
適當頻寬管理的關鍵是,系統中執行同步傳輸的每個 USB 裝置都必須為包含同步端點的每個介面提供多個替代 (Alt) 設定,而且用戶端驅動程式必須明智地使用這些 Alt 設定。 用戶端驅動程式應該先要求具有最高頻寬的介面設定。 如果要求失敗,用戶端驅動程式應該要求頻寬越來越小的介面設定,直到要求成功為止。
例如,假設網路攝影機裝置具有以下介面:
介面 0 (預設介面設定:預設設定中沒有具有非零同步頻寬的端點)
同步端點 1:封包大小上限 = 0 位元組
同步端點 2:封包大小上限 = 0 位元組
介面 0 Alt 設定 1
同步端點 1:封包大小上限 = 256 位元組
同步端點 2:封包大小上限 = 256 位元組
介面 0 Alt 設定 2
同步端點 1:封包大小上限 = 512 位元組
同步端點 2:封包大小上限 = 512 位元組
網路攝影機的驅動程式會將網路攝影機設定為在初始化時使用預設介面設定。 預設設定沒有同步頻寬,因此在初始化期間使用預設設定可避免網路攝影機可能無法列舉的危險,因為同步頻寬要求失敗。
當用戶端驅動程式準備好執行同步傳輸時,它應該嘗試使用 Alt 設定 2,因為 Alt 設定 2 具有最大的封包大小。 如果要求失敗,驅動程式可以使用 Alt 設定 1 進行第二次嘗試。 由於 Alt 設定 1 需要較少的頻寬,因此即使第一個要求失敗,此要求也可能會成功。 多個 Alt 設置允許駕駛員在放棄之前進行多次嘗試。
網路攝影機空閒後,可以透過再次選擇預設設定將分配的頻寬返回到可用頻寬池。
使用者可以透過在 Windows 裝置管理員中檢查控制器的屬性來查看 USB 控制器分配了多少頻寬。 選取控制器的屬性,然後查看 進階 標籤。此讀數並未指出 USB 中樞已為交易轉譯配置多少頻寬。
報告 USB 控制器頻寬使用情況的裝置管理員功能在 Windows XP 中無法正常運作。
USB 傳輸和封包大小
本文說明各種 Windows 作業系統版本中允許的 USB 傳輸大小。
傳輸大小上限
傳輸大小上限會指定 USB 驅動程式堆疊中的硬式編碼限制。 低於這些限制的傳輸大小可能會因為系統資源限制而失敗。 若要避免這些類型的失敗,並確保所有 Windows 版本之間的相容性,請避免對 USB 傳輸使用大型傳輸大小。
備註
USBD_PIPE_INFORMATION結構的 MaximumTransferSize 成員已過時。 USB 驅動程式堆疊會忽略複合和非複合裝置的 MaximumTransferSize 中的值。
在 Windows 2000 中,USB 驅動程式堆疊會將 MaximumTransferSize 初始化為 USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE。 用戶端驅動程式可以在設定裝置時設定較小的值。 針對複合裝置,在非預設介面設定中,每個函式的用戶端驅動程式只能變更管道的 MaximumTransferSize。
USB 傳輸大小受以下限制:
| 傳輸管 | Windows 8.1、Windows 8 | Windows 7、Windows Vista | Windows XP、Windows Server 2003 | Windows 2000 |
|---|---|---|---|---|
| 管理 | 64K 用於 SuperSpeed 超高速與高速傳輸技術(xHCI) 4K 全速和低速(xHCI、EHCI、UHCI、OHCI) 對於 UHCI,預設端點為 4K;非預設控制管道為 64K |
64K 高速(EHCI) 4K 用於全速及低速(EHCI、UHCI、OHCI) 對於 UHCI,預設端點的容量為 4K,非預設控制管道的容量為 64K |
64K 高速 (EHCI) 4K 全速和低速(EHCI、UHCI、OHCI) 對於 UHCI,預設端點為 4K;非預設控制管道 (UHCI) 上的 64K |
預設端點上為 4K;非預設控制管道 (OHCI) 上的 64K |
| 中斷 | 4MB 適用於 SuperSpeed、高速、全速及低速 (xHCI、EHCI、UHCI、OHCI) | 4MB 用於高速、全速和低速(EHCI、UHCI、OHCI) | 無限制 | 未確定(OHCI) |
| 大量 | 32MB 超高速 (xHCI) 4MB 用於高速和全速 (xHCI) 4MB 用於高速和全速(EHCI 和 UHCI) 256K 全速(OHCI) |
4MB 用於高速和全速(EHCI、UHCI) 256K 全速 (OHCI) |
3MB 用於高速和全速 (EHCI) 未確定 (UHCI) 256K 全速(OHCI) |
未確定(OHCI) |
| 等時的 | 1024 * 超高速(xHCI)的wBytesPerInterval (見 USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR) 1024 * 封包大小最大值,用於高速 (xHCI、EHCI) 256 * 最大封包大小 用於全速(xHCI、EHCI) 64K 全速(UHCI、OHCI) |
1024 * 高速 (EHCI) 的最大封包大小 256 * 全速 (EHCI) 的最大封包大小 64K 全速(UHCI、OHCI) |
1024 * 高速(EHCI)資料包最大大小 256 * MaximumPacketSize 的全速(EHCI) 64K 全速(UHCI、OHCI) |
64K 全速運行(OHCI) |
使用 MaximumTransferSize 限制傳輸大小不會直接影響裝置耗用的頻寬量。 用戶端驅動程式必須變更介面設定,或限制 USBD_PIPE_INFORMATION 的 MaximumPacketSize 成員中設定的封包大小上限。
封包大小上限
封包大小上限是由端點描述元的 wMaxPacketSize 欄位所定義。 用戶端驅動程式可以在裝置的選取介面要求中調節 USB 封包大小。 變更此值不會變更裝置上的 wMaxPacketSize 。
在請求的 URB 中,是管道的 USBD_PIPE_INFORMATION 結構。 在該結構中,
- 修改USBD_PIPE_INFORMATION結構的 MaximumPacketSize 成員。 將它設定為小於或等於目前介面設定的裝置韌體中定義的 wMaxPacketSize 值的值。
- 在 PipeFlags 成員 USBD_PIPE_INFORMATION 結構中設定 USBD_PF_CHANGE_MAX_PACKET 旗標。
如需有關選取介面設定的資訊,請參閱 如何選取 USB 裝置的組態。
讀取傳輸緩衝區的封包大小限制上限
當用戶端驅動程式提出讀取要求時,傳輸緩衝區必須是封包大小上限的倍數。 即使驅動程式預期數據小於封包大小上限,它仍然必須要求整個封包。 當裝置傳送的資料包小於最大大小(短資料包)時,表示傳輸已完成。
在較舊的控制器上,用戶端驅動程式可以覆蓋既有行為。 在數據傳輸 URB 的 TransferFlags 成員中,用戶端驅動程式必須設定 USBD_SHORT_TRANSFER_OK 旗標。 該旗標可讓裝置傳送小於 wMaxPacketSize 的封包。
在 xHCI 主機控制器上,批量和中斷端點的 USBD_SHORT_TRANSFER_OK 被忽略。 在 EHCI 控制器上傳輸短封包不會導致錯誤狀況。
在 EHCI 主機控制器上,會針對大容量及中斷端點忽略 USBD_SHORT_TRANSFER_OK。
在 UHCI 和 OHCI 主機控制器上,如果未為大量或中斷傳輸設定USBD_SHORT_TRANSFER_OK,則短封包傳輸會停止端點,並傳回傳輸的錯誤碼。
使用短封包來界定寫入傳輸
USB 驅動程式堆疊驅動程式不會在寫入裝置時,對封包大小施加與從裝置讀取時施加相同的限制。 某些用戶端驅動程式必須頻繁傳輸少量控制數據,以管理其裝置。 在這種情況下,將資料傳輸限制為大小統一的資料包是不切實際的。 因此,驅動程式堆疊不會在資料寫入期間將任何特殊意義指派給大小小於端點大小上限的封包。 這使得客戶驅動程式能夠將向裝置的大型傳輸分解成多個小於或等於最大允許值的 URB。
驅動程式必須以小於最大大小的封包結束傳輸,或以零長度封包來分隔傳輸結尾。 在驅動程式傳送小於 wMaxPacketSize 的封包之前,傳輸不會完成。 如果傳輸大小是最大值的精確倍數,驅動程式必須傳送零長度分隔封包,才能明確終止傳輸
用戶端驅動程式負責根據 USB 規格的要求,以零長度封包來分隔資料傳輸。 USB 驅動程式堆疊不會自動產生這些封包。
使用小於 wMaxPacketSize 的封包來分隔 USB 資料傳輸
符合規範的 USB 2.0 和 USB 1.1 驅動程式必須傳輸最大大小 (wMaxPacketSize) 的封包,然後以小於最大大小的封包結束傳輸,或以零長度封包分隔傳輸結束。 在驅動程式傳送小於 wMaxPacketSize 的封包之前,傳輸不會完成。 如果傳輸大小是最大值的精確倍數,驅動程式必須傳送零長度分隔封包,才能明確終止傳輸
裝置驅動程式負責根據 USB 規格的要求,使用零長度封包來分隔資料傳輸。 系統 USB 堆疊不會自動產生這些封包。