使用 USB 管道
框架将 USB 接口中的每个管道表示为框架 USB 管道对象。 当驱动程序 配置 USB 设备时,框架会为每个所选接口中的每个管道创建一个框架 USB 管道对象。 管道对象方法使驱动程序能够执行以下操作:
获取管道信息
调用 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 目标都将完成读取请求,框架将调用以下两个回调函数之一: EvtUsbTargetPipeReadComplete(如果 I/O 目标成功读取数据),如果 I/O 目标报告错误,则调用 EvtUsbTargetPipeReadersFailed。
如果不提供可选的 EvtUsbTargetPipeReadersFailed 回调,框架将通过发送另一个读取请求来响应失败的读取尝试。 因此,如果总线处于不接受读取的状态,框架会不断发送新的请求,以从失败的读取中恢复。
驱动程序调用 WdfUsbTargetPipeConfigContinuousReader 后,驱动程序无法使用 WdfUsbTargetPipeReadSynchronously 或 WdfRequestSend 将 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 请求,则驱动程序应执行以下操作:
如果目标尚未完成请求,请停止管道并取消驱动程序已发送到 USB 目标的任何其他 I/O 请求。
向管道同步发送中止请求。
调用 WdfUsbTargetPipeAbortSynchronously,或调用 WdfUsbTargetPipeFormatRequestForAbort ,后跟 WdfRequestSend 并设置 WDF_REQUEST_SEND_OPTION_SYNCHRONOUS 标志。
同步向管道发送重置请求。
调用 WdfUsbTargetPipeResetSynchronously,或调用 WdfUsbTargetPipeFormatRequestForReset ,然后调用 WdfRequestSend 并设置 WDF_REQUEST_SEND_OPTION_SYNCHRONOUS 标志。
重启管道。
调用 WdfIoTargetStart。
重新发送失败的 I/O 请求,以及失败请求后的所有 I/O 请求。
多次失败后,驱动程序应尝试通过执行以下操作来重置 USB 端口:
如果目标尚未完成,请停止所有活动管道,并取消驱动程序发送到每个管道的 USB 目标的任何其他 I/O 请求。
对于每个活动管道,调用 设置了 WdfIoTargetCancelSentIo 标志的 WdfIoTargetStop 。
同步发送重置 USB 端口的请求。
重启管道。
为驱动程序停止的每个管道调用 WdfIoTargetStart 。
重新发送失败的最后一个 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 管道句柄。 某些 URB 需要此句柄。