共用方式為


使用 USB 管道

架構會將 USB 介面中的每個管道表示為架構 USB 管道物件。 當驅動程式 設定 USB 裝置時,架構會為每個選取介面中的每個管道建立架構 USB 管道物件。 Pipe 物件方法可讓驅動程式執行下列作業:

取得管道資訊

呼叫 WdfUsbInterfaceGetConfiguredPipe 以取得架構 USB 管道物件的控制碼之後,您的驅動程式可以呼叫 USB 管道物件所定義的下列方法來取得 USB 管道的相關資訊:

WdfUsbTargetPipeGetIoTarget
傳回與 USB 管道相關聯之 I/O 目標物件的控制碼。 驅動程式可以將此控制碼傳遞至 WdfRequestSend

WdfUsbTargetPipeGetInformation
擷取 USB 管道及其端點的相關資訊。

WdfUsbTargetPipeGetType
傳回 USB 管道的類型。

WdfUsbTargetPipeIsInEndpoint
判斷 USB 管道是否連接到輸入端點。

WdfUsbTargetPipeIsOutEndpoint
判斷 USB 管道是否連接到輸出端點。

WDF_USB_PIPE_DIRECTION_IN
判斷 USB 端點是否為輸入端點。

WDF_USB_PIPE_DIRECTION_OUT
判斷 USB 端點是否為輸出端點。

如需相關資訊,請參閱 如何列舉 USB 管道

從管道讀取

若要從 USB 輸入管道讀取資料,您的驅動程式可以使用下列三種技術的任何 (或所有) :

  • 同步讀取資料

    若要從 USB 輸入管道同步讀取資料,您的驅動程式可以呼叫 WdfUsbTargetPipeReadSynchronously 方法。 此方法會建置並傳送讀取要求,並在 I/O 作業完成之後傳回。

  • 以非同步方式讀取資料

    若要從 USB 輸入管道非同步讀取資料,您的驅動程式可以呼叫 WdfUsbTargetPipeFormatRequestForRead 方法來建置讀取要求。 然後,驅動程式可以呼叫 WdfRequestSend ,以非同步方式傳送要求 (或同步) 。

  • 以非同步且持續的方式讀取資料

    連續讀取器是一種架構提供的機制,可確保讀取要求一律可供 USB 管道使用。 此機制可確保驅動程式一律準備好從提供非同步、未經要求輸入資料流程的裝置接收資料。 例如,網路介面卡的驅動程式 (NIC) 可能會使用連續讀取器來接收輸入資料。

    若要為輸入管道設定連續讀取器,驅動程式的 EvtDevicePrepareHardware 回呼函式必須呼叫 WdfUsbTargetPipeConfigContinuousReader 方法。 這個方法會將一組讀取要求排入裝置的 I/O 目標。

    此外,驅動程式的 EvtDeviceD0Entry 回 呼函式必須呼叫 WdfIoTargetStart 來啟動連續讀取器,而驅動程式的 EvtDeviceD0Exit 回 呼函式必須呼叫 WdfIoTargetStop 來停止連續讀取器。

    每次從裝置取得資料時,如果 I/O 目標回報錯誤,I/O 目標就會完成讀取要求,而且架構會呼叫下列兩個回呼函式之一: EvtUsbTargetPipeReadlete,如果 I/O 目標成功讀取資料,或 EvtUsbTargetPipeReadersFailed

    如果您未提供選用的 EvtUsbTargetPipeReadersFailed 回呼,架構會藉由傳送另一個讀取要求來回應失敗的讀取嘗試。 因此,如果匯流排處於不接受讀取的狀態,架構會持續傳送新的要求,以從失敗的讀取中復原。

    驅動程式呼叫 WdfUsbTargetPipeConfigContinuousReader之後,驅動程式無法使用 WdfUsbTargetPipeReadSynchronouslyWdfRequestSend 將 I/O 要求傳送至管道,除非呼叫驅動程式的 EvtUsbTargetPipeReadersFailed 回呼函式並傳回 FALSE

根據預設,如果您的驅動程式指定的讀取緩衝區不是管道封包大小上限的倍數,架構就會回報錯誤。 您的驅動程式可以呼叫 WdfUsbTargetPipeSetNoMaximumPacketSizeCheck 來停用讀取緩衝區大小的此測試。

如需相關資訊,請參閱:

寫入管道

若要將資料寫入 USB 輸出管道,您的驅動程式可以使用一個 (或兩者) 下列技術:

  • 同步寫入資料

    若要以同步方式將資料寫入 USB 輸出管道,您的驅動程式可以呼叫 WdfUsbTargetPipeWriteSynchronously 方法。 這個方法會建置並傳送寫入要求,並在 I/O 作業完成之後傳回。

  • 以非同步方式寫入資料

    若要以非同步方式將資料寫入 USB 輸入管道,您的驅動程式可以呼叫 WdfUsbTargetPipeFormatRequestForWrite 方法來建置寫入要求。 然後,驅動程式可以呼叫 WdfRequestSend 以非同步方式傳送要求。

如需相關資訊,請參閱 如何傳送 USB 大量傳輸要求

停止和重設管道

您的驅動程式可以呼叫下列方法來停止或重設 USB 管道:

WdfUsbTargetPipeAbortSynchronously
同步傳送要求以停止 USB 管道。

WdfUsbTargetPipeFormatRequestForAbort
格式化要求以停止 USB 管道。 驅動程式可以呼叫 WdfRequestSend ,以同步或非同步方式傳送要求。

WdfUsbTargetPipeResetSynchronously
同步傳送要求以重設 USB 管道。

WdfUsbTargetPipeFormatRequestForReset
格式化要求以重設 USB 管道。 驅動程式必須呼叫 WdfRequestSend ,以同步或非同步方式傳送要求。

如果您的驅動程式的 USB 目標 完成 I/O 要求並出現錯誤狀態值,驅動程式應該執行下列動作:

  1. 停止管道,如果目標尚未完成要求,則取消驅動程式傳送至 USB 目標的任何其他 I/O 要求。

    使用WdfIoTargetCancelSentIo旗標集呼叫WdfIoTargetStop

  2. 同步傳送中止要求至管道。

    呼叫 WdfUsbTargetPipeAbortSynchronously,或呼叫 WdfUsbTargetPipeFormatRequestForAbort ,後面接著 WdfRequestSend 並設定 WDF_REQUEST_SEND_OPTION_SYNCHRONOUS 旗標。

  3. 同步傳送重設要求至管道。

    呼叫 WdfUsbTargetPipeResetSynchronously,或呼叫 WdfUsbTargetPipeFormatRequestForReset ,後面接著 WdfRequestSend 並設定 WDF_REQUEST_SEND_OPTION_SYNCHRONOUS 旗標。

  4. 重新開機管道。

    呼叫 WdfIoTargetStart

  5. 重新傳送失敗的 I/O 要求,以及遵循失敗要求的所有 I/O 要求。

在大量失敗之後,驅動程式應該執行下列動作來嘗試重設 USB 埠:

  1. 停止所有作用中的管道,如果目標尚未完成,則取消驅動程式已傳送至每個管道 USB 目標的任何其他 I/O 要求。

    針對每個使用中管道,使用WdfIoTargetCancelSentIo旗標集呼叫WdfIoTargetStop

  2. 同步傳送要求以重設 USB 埠。

    呼叫 WdfUsbTargetDeviceResetPortSynchronously

  3. 重新開機管道。

    針對驅動程式停止的每個管道呼叫 WdfIoTargetStart

  4. 重新傳送最後一個失敗的 I/O 要求,以及遵循失敗要求的所有 I/O 要求。

如需相關資訊,請參閱 如何從 USB 管道錯誤復原

將 URB 傳送至管道

如果您的 KMDF 驅動程式透過傳送包含 URB 的 I/O 要求與 USB 管道通訊,驅動程式可以呼叫下列方法:

WdfUsbTargetPipeSendUrbSynchronously (KMDF 僅)
同步傳送包含 URB 的 I/O 要求。

WdfUsbTargetPipeFormatRequestForUrb (KMDF 僅)
格式化包含 URB 的 I/O 要求。 驅動程式可以呼叫 WdfRequestSend ,以同步或非同步方式傳送要求。

WdfUsbTargetPipeWdmGetPipeHandle (KMDF 僅)
傳回裝置的 USBD 管道控制碼。 某些 URI 需要此控制碼。