共用方式為


最佳做法:使用 URBs

本主題描述客戶端驅動程式的最佳做法,以配置、建置和傳送 URB 至 Windows 8 隨附的 USB 驅動程式堆疊。

Windows 8 包含新的 USB 驅動程式堆疊,可支援通用序列總線 (USB) 3.0 裝置。 根據USB 3.0規格,新的USB 3.0驅動程式堆疊會實作數項新功能。 此外,驅動程式堆疊也包含其他功能,可讓客戶端驅動程式有效率地執行一般工作。 例如,新的驅動程式堆疊會接受 chained-MDL,讓用戶端驅動程式在實體記憶體中不連續的頁面中傳送傳輸緩衝區。

在用戶端驅動程式可以使用適用於 Windows 8 的 USB 驅動程式堆疊新功能之前,驅動程式必須先向 Windows 為裝置載入的基礎 USB 驅動程式堆疊註冊本身。 若要註冊客戶端驅動程式,請呼叫 USBD_CreateHandle 並指定 合約版本。 如果客戶端驅動程式的目的是要建置、執行及使用 Windows 8 上的改進功能和新功能,則用戶端合約版本會USBD_CLIENT_CONTRACT_VERSION_602。

針對USBD_CLIENT_CONTRACT_VERSION_602版本用戶端驅動程式,USB 驅動程式堆疊會假設用戶端驅動程式符合下列規則集:

USB 驅動程式堆疊會對收到的要求執行驗證,並盡可能處理違規。 若無法這麼做,可能會導致未定義的行為。

請勿使用已過期或無效的管道控制代碼發送 I/O 請求

用戶端驅動程式 不得 使用過時的管道句柄,將I/O要求傳送至USB驅動程式堆疊。 過時管道句柄是指在要求中取得的管道句柄,以選取組態、介面或裝置中不再選取的替代設定。 為了避免管線句柄過時,每次用戶端驅動程式選取組態或介面時,驅動程式都必須重新整理其管線句柄的快取(通常儲存在裝置內容中)。 某些競爭條件也會導致管道句柄過時。 例如,客戶端驅動程式會使用所選介面上的管道句柄來傳送 I/O 要求。 要求完成之前,客戶端驅動程式會選取不使用與管道句柄相關聯的相同端點的替代設定。 這兩個擱置的要求都可能導致競爭狀況使管道句柄無效。

在 Windows 8 中呼叫配置例程來配置 URB

Windows 8 提供配置、建置和發行 USB 要求區塊 (URB) 的新例程。 若要設定 URB,Windows 驅動程式模型 (WDM) 用戶端驅動程式必須一律使用下列清單中所示的新例程:

上述清單中的例程可能會將不透明的 URB 內容附加至已配置的 URB,以改善追蹤和處理。 用戶端驅動程式無法檢視或修改 URB 內容的內容。 如需 Windows 8 中 URB 配置的詳細資訊,請參閱 配置和建置 URB

如果 Windows Driver Framework (WDF) 用戶端驅動程式在註冊期間將其版本識別為USBD_CLIENT_CONTRACT_VERSION_602(請參閱 WdfUsbTargetDeviceCreateWithParameters),USB 驅動程式堆棧會預期用戶端驅動程式會呼叫新的 WdfUsbTargetDeviceCreateUrb 來配置 URB 的記憶體。

請勿重複使用與擱置要求相關聯的作用中URL

USB 驅動程式堆疊會刻意檢查它是否偵測到與 URB 相關聯的要求之前已重新提交的作用中 URB。 只要請求仍在待處理狀態,URB 就會處於作用中狀態,而且尚未呼叫用戶端驅動程式的 IRP 完成例程。 請勿在作用中的 URB 上執行下列工作。

  • 請勿針對其他請求重複提交使用中的 URB(將 URB 與其他 IRP 關聯)。
  • 請勿修改使用中 URB 的內容。
  • 請勿釋放使用中的 URB。

呼叫客戶端驅動程式完成例程之後,驅動程式可以針對完成例程內的特定要求類型重新提交 URB。 下列規則適用於重新提交:

  • 用戶端驅動程式不得將由 USBD_SelectConfigUrbAllocateAndBuild 所分配的 URB 重複用於除選取相同組態的選取組態要求以外的任何類型的要求。

  • 用戶端驅動程式不得在不同類型的要求中重複使用由 USBD_SelectInterfaceUrbAllocateAndBuild 配置的 URB,除非是同一介面中選取相同替代設定的選擇介面要求。 如需範例,請參閱 USBD_SelectInterfaceUrbAllocateAndBuild 中的「備註」。

  • 由 USBD_IsochUrbAllocate 配置的 URB 必須只針對不時針傳輸要求重複使用。 相反地,分配給其他類型 I/O 請求(控制、大量或中斷)的 URB 不得用於等時性請求。

    例如,客戶端驅動程式會配置並建置用於大量傳輸要求的 URB 結構。 用戶端驅動程式也想要將資料傳送至裝置中的同步端點。 大量傳輸要求完成之後,客戶端驅動程式 不得 重新格式化並提交 URB 以取得同步的要求。 這是因為與不時值要求相關聯的 URB 會根據封包數目而具有可變長度。 此外,封包必須在幀邊界上啟動和結束。 配置的 URB(針對大量傳輸)可能不符合等時傳輸所需的緩衝區配置,而且要求可能會失敗。

  • USBD_UrbAllocate所配置的 URB 不得針對等時、選取組態或選取介面要求重複使用。 您可以重複使用 URB 來選取 NULL 組態,以停用裝置中選取的組態。 URB 不得為使用中,而且用戶端驅動程式必須藉由呼叫 UsbBuildSelectConfigurationRequest 巨集並在 ConfigurationDescriptor 參數中傳遞 NULL,以重新格式化 URB。

  • 重新提交 URB 之前,用戶端驅動程式必須使用針對要求類型定義的適當 UsbBuildXxx 巨集,重新格式化 URB。 驅動程式必須格式化 URB,因為 USB 堆疊可能會改變其部分內容。

    例如,假設驅動程式呼叫 UsbBuildInterruptOrBulkTransferRequest 來初始化用於大量傳輸要求的 URB(請參閱 _URB_BULK_OR_INTERRUPT_TRANSFER)。 如果驅動程式將 URB 結構的 TransferBufferMDL 成員初始化為 NULL,USB 驅動程式堆疊會使用傳輸緩衝區指定的 TransferBuffer,在 中與裝置交換數據,而不是 MDL。 不過,在內部,USB 驅動程式堆疊可能會建立 MDL、將 MDL 指標儲存在 TransferBufferMDL 中,並使用 MDL 將數據傳遞至堆疊。 即使 USB 驅動程式堆疊釋放了 MDL 記憶體,但當用戶端驅動程式在完成例程中處理 URB 時,TransferBufferMDL 仍然可能不是 NULL。 為了確保 URB 的成員已正確格式化,驅動程式在提交要求之前必須再次呼叫 UsbBuildInterruptOrBulkTransferRequest 以重新格式化 URB。

請勿在高速和超高速等時傳輸中使用輪詢週期大於8的設定。

USB 驅動程式堆疊支援高速和 SuperSpeed 等時管道,輪詢週期為 1、2、4 或 8。 用戶端驅動程式不得將 IO 傳送至期間大於 8 的端點。 這樣做可能會導致系統錯誤檢查。

請確保等時封包的數量是每幀封包數量的倍數。

針對高速和超高速等時性傳輸,每個畫面的等時性封包數目會計算為8/輪詢期間。 用戶端驅動程式必須確定 URB 中指定的 NumberOfPackets 值(請參閱 _URB_ISOCH_TRANSFER) 是每個畫面的多個封包數目。

USB 驅動程式堆疊不支援等時性傳輸的 URBs,其中 NumberOfPackets 不是每幀封包數的倍數。

在文檔記載的 IRQL 層級上呼叫例行程式

如果您將客戶端驅動程式註冊為合約版本USBD_CLIENT_CONTRACT_VERSION_602,USB 驅動程式堆疊會假設用戶端驅動程式會在適當的 IRQL 層級傳送要求。 如果客戶端驅動程式在 DISPATCH_LEVEL 傳送要求,而該要求應該在 PASSIVE_LEVEL 傳送。 在收到要求時,在某些情況下,USB 驅動程式堆疊會驗證 IRQL 值,並可能導致要求失敗。 不過,在其他情況下,USB 驅動程式堆疊可能會產生錯誤檢查。

將要求傳送至USB裝置