USB パイプの操作
フレームワークは、USB インターフェイス内の各パイプを "フレームワーク USB パイプ オブジェクト" として表します。**ドライバーが USB デバイスを構成すると、フレームワークは、選択した各インターフェイス内のパイプごとにフレームワーク USB パイプ オブジェクトを作成します。パイプ オブジェクトのメソッドにより、ドライバーは次の操作を実行できます。
パイプ情報を取得する。
パイプから読み取る。
パイプに書き込む。
パイプを停止またはリセットする。
URB をパイプに送信する。
パイプ エラーを処理する。
パイプ情報の取得
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 入力パイプからデータを読み取るために、ドライバーは次の 3 つの方法のいずれか (またはすべて) を使用できます。
データを同期的に読み取る。
USB 入力パイプからデータを同期的に読み取るために、ドライバーは WdfUsbTargetPipeReadSynchronously メソッドを呼び出すことができます。このメソッドは読み取り要求を作成して送信し、I/O 操作が完了した後、制御を戻します。
データを非同期的に読み取る。
USB 入力パイプからデータを非同期的に読み取るために、ドライバーは WdfUsbTargetPipeFormatRequestForRead メソッドを呼び出して読み取り要求を作成できます。次に、WdfRequestSend を呼び出して、その要求を非同期的 (または同期的) に送信します。
データを非同期的に連続して読み取る。
"連続的なリーダー" とは、フレームワークで提供されるメカニズムであり、USB パイプで読み取り要求を常に使用できるようにします。**このメカニズムにより、ドライバーは、要求されていない非同期の入力ストリームを提供するデバイスからいつでもデータを受信できる状態になります。たとえば、ネットワーク インターフェイス カード (NIC) のドライバーは、連続的なリーダーを使用して入力データを受信します。
入力パイプの連続的なリーダーを構成するために、ドライバーの EvtDevicePrepareHardware コールバック関数は WdfUsbTargetPipeConfigContinuousReader メソッドを呼び出す必要があります。このメソッドは、デバイスの I/ O ターゲットへの一連の読み取り要求をキューに入れます。
また、ドライバーの EvtDeviceD0Entry コールバック関数は WdfIoTargetStart を呼び出して連続的なリーダーを開始し、ドライバーの EvtDeviceD0Exit コールバック関数は WdfIoTargetStop を呼び出して連続的なリーダーを停止する必要があります。
データがデバイスから取得されるたびに、I/O ターゲットは読み取り要求を完了し、フレームワークは次の 2 つのコールバック関数の 1 つを呼び出します。I/O ターゲットがデータを正常に読み取った場合は EvtUsbTargetPipeReadComplete を呼び出し、I/O ターゲットがエラーを報告した場合は EvtUsbTargetPipeReadersFailed を呼び出します。
ドライバーが WdfUsbTargetPipeConfigContinuousReader を呼び出した後、ドライバーの EvtUsbTargetPipeReadersFailed コールバック関数が呼び出され、FALSE を返さない限り、WdfUsbTargetPipeReadSynchronously または WdfRequestSend を使用してパイプに I/O 要求を送信することはできません。
既定では、パイプの最大パケット サイズの倍数ではない読み取りバッファーがドライバーで指定された場合、フレームワークはエラーを報告します。ドライバーは、WdfUsbTargetPipeSetNoMaximumPacketSizeCheck を呼び出して、読み取りバッファー サイズのこのテストを無効にすることができます。
パイプへの書き込み
USB 出力パイプにデータを書き込むために、ドライバーは次のいずれか (または両方) の方法を使用できます。
データを同期的に書き込む。
データを USB 出力パイプに同期的に書き込むために、ドライバーは WdfUsbTargetPipeWriteSynchronously メソッドを呼び出すことができます。このメソッドは書き込み要求を作成して送信し、I/O 操作が完了した後、制御を戻します。
データを非同期的に書き込む。
データを USB 入力パイプに非同期的に書き込むために、ドライバーは WdfUsbTargetPipeFormatRequestForWrite メソッドを呼び出して書き込み要求を作成できます。次に、ドライバーは WdfRequestSend を呼び出して、要求を非同期的に送信できます。
パイプの停止とリセット
ドライバーは次のメソッドを呼び出して、USB パイプを停止またはリセットできます。
WdfUsbTargetPipeAbortSynchronously
USB パイプを停止するための要求を同期的に送信します。WdfUsbTargetPipeFormatRequestForAbort
USB パイプを停止するための要求をフォーマットします。ドライバーは WdfRequestSend を呼び出して、要求を同期的または非同期的に送信できます。WdfUsbTargetPipeResetSynchronously
USB パイプをリセットするための要求を同期的に送信します。WdfUsbTargetPipeFormatRequestForReset
USB パイプをリセットするための要求をフォーマットします。ドライバーは WdfRequestSend を呼び出して、要求を同期的または非同期的に送信する必要があります。
パイプへの URB の送信
ドライバーは、URB を含む I/O 要求を送信して USB パイプと通信する場合、次のメソッドを呼び出すことができます。
WdfUsbTargetPipeSendUrbSynchronously
URB を含む I/O 要求を同期的に送信します。WdfUsbTargetPipeFormatRequestForUrb
URB を含む I/O 要求をフォーマットします。ドライバーは WdfRequestSend を呼び出して、要求を同期的または非同期的に送信できます。WdfUsbTargetPipeWdmGetPipeHandle
デバイスの USBD パイプ ハンドルを返します。一部の URB にはこのハンドルが必要です。
パイプ エラーの処理
ドライバーの USB ターゲットがエラー状態の値で I/O 要求を完了した場合、ドライバーは次の処理を実行する必要があります。
ドライバーが USB ターゲットに追加の I/O 要求を送信していた場合、ターゲットがこの要求を完了していないときは、パイプを停止し、追加の I/O 要求を取り消します。
WdfIoTargetCancelSentIo フラッグ セットと共に WdfIoTargetStop を呼び出します。
中止要求をパイプに同期的に送信します。
WdfUsbTargetPipeAbortSynchronously を呼び出した後、または WdfUsbTargetPipeFormatRequestForAbort を呼び出した後に、WDF_REQUEST_SEND_OPTION_SYNCHRONOUS フラッグ セットと共に WdfRequestSend を呼び出します。
リセット要求をパイプに同期的に送信します。
WdfUsbTargetPipeResetSynchronously を呼び出した後、または WdfUsbTargetPipeFormatRequestForReset を呼び出した後に、WDF_REQUEST_SEND_OPTION_SYNCHRONOUS フラッグ セットと共に WdfRequestSend を呼び出します。
パイプを再起動します。
WdfIoTargetStart を呼び出します。
失敗した I/O 要求、および失敗した要求の後のすべての I/O 要求を再送信します。
多数のエラーが発生した場合、ドライバーは次の処理を実行して USB ポートのリセットを試行する必要があります。
ドライバーが各パイプの USB ターゲットに追加の I/O 要求を送信していた場合、ターゲットがこの要求を完了していないときは、パイプを停止し、追加の I/O 要求を取り消します。
アクティブな各パイプについて、WdfIoTargetCancelSentIo フラッグ セットと共に WdfIoTargetStop を呼び出します。
USB ポートをリセットするための要求を同期的に送信します。
パイプを再起動します。
ドライバーが停止したパイプごとに WdfIoTargetStart を呼び出します。
失敗した最後の I/O 要求、および失敗した要求の後のすべての I/O 要求を再送信します。