WdfUsbTargetPipeFormatRequestForRead 函数 (wdfusb.h)

[适用于 KMDF 和 UMDF]

WdfUsbTargetPipeFormatRequestForRead 方法为 USB 输入管道生成读取请求,但不发送请求。

语法

NTSTATUS WdfUsbTargetPipeFormatRequestForRead(
  [in]           WDFUSBPIPE        Pipe,
  [in]           WDFREQUEST        Request,
  [in, optional] WDFMEMORY         ReadMemory,
  [in, optional] PWDFMEMORY_OFFSET ReadOffset
);

参数

[in] Pipe

通过调用 WdfUsbInterfaceGetConfiguredPipe获取的框架管道对象的句柄。

[in] Request

框架请求对象的句柄。 有关详细信息,请参阅以下“备注”部分。

[in, optional] ReadMemory

框架内存对象的句柄。 此对象表示将从管道接收数据的缓冲区。 缓冲区大小必须是管道的最大数据包大小的倍数,除非驱动程序调用了 WdfUsbTargetPipeSetNoMaximumPacketSizeCheck。 有关此缓冲区的详细信息,请参阅以下“备注”部分。

[in, optional] ReadOffset

指向调用方分配的 WDFMEMORY_OFFSET 结构的指针,该结构提供可选的字节偏移量和长度值。 框架使用这些值来确定数据传输的读取缓冲区内的起始地址和长度。 如果此指针 NULL,则数据传输从缓冲区的开头开始,传输大小为缓冲区大小。

返回值

如果作成功,则 WdfUsbTargetPipeFormatRequestForRead 返回STATUS_SUCCESS。 否则,此方法可以返回以下值之一:

返回代码 描述
STATUS_INVALID_PARAMETER
检测到无效参数。
STATUS_INSUFFICIENT_RESOURCES
内存不足。
STATUS_INVALID_DEVICE_REQUEST
指定了无效的内存描述符、管道的类型无效、传输方向无效或指定的 I/O 请求已排队到 I/O 目标。
STATUS_INTEGER_OVERFLOW
指定的 Offset 参数的偏移量无效。
STATUS_INVALID_BUFFER_SIZE
缓冲区大小不是管道的最大数据包大小的倍数。 缓冲区大小必须是管道的最大数据包大小的倍数,除非驱动程序调用了 WdfUsbTargetPipeSetNoMaximumPacketSizeCheck
STATUS_REQUEST_NOT_ACCEPTED
Request 参数表示的 I/O 请求数据包(IRP),不提供足够的 IO_STACK_LOCATION 结构,使驱动程序能够转发请求。
 

此方法还可以 返回其他NTSTATUS 值。

如果驱动程序提供无效的对象句柄,则会发生 bug 检查。

言论

使用 WdfUsbTargetPipeFormatRequestForRead(后跟 WdfRequestSend)同步或异步发送读取请求。 或者,使用 WdfUsbTargetPipeReadSynchronously 方法同步发送读取请求。

Pipe 参数指定的管道必须是输入管道,管道的 类型 必须 WdfUsbPipeTypeBulkWdfUsbPipeTypeInterrupt

可以转发驱动程序在 I/O 队列中收到的 I/O 请求,也可以创建并发送新请求。 在任一情况下,框架都需要请求对象和一些缓冲区空间。

转发驱动程序在 I/O 队列中收到的 I/O 请求:

  1. WdfUsbTargetPipeFormatRequestForRead 方法的 Request 参数指定收到的请求的句柄。
  2. 将收到的请求的输出缓冲区用于 WdfUsbTargetPipeFormatRequestForRead 方法的 ReadMemory 参数。

    驱动程序必须调用 WdfRequestRetrieveOutputMemory 以获取表示请求输出缓冲区的框架内存对象的句柄,并将该句柄用作 ReadMemory 参数的值。

有关转发 I/O 请求的详细信息,请参阅 转发 I/O 请求

驱动程序通常会将收到的 I/O 请求划分为发送到 I/O 目标的较小请求,因此驱动程序可能会创建新请求。

创建新的 I/O 请求:

  1. 创建新的请求对象,并为 WdfUsbTargetPipeFormatRequestForRead 方法的 Request 参数提供其句柄。

    调用 WdfRequestCreate 来预分配一个或多个请求对象。 可以通过调用 WdfRequestReuse来重复使用这些请求对象。 驱动程序的 EvtDriverDeviceAdd 回调函数可以预分配设备的请求对象。

  2. 提供缓冲区空间,并为 WdfUsbTargetPipeFormatRequestForRead 方法的 ReadMemory 参数提供缓冲区的句柄。

    驱动程序必须将此缓冲区空间指定为框架管理的内存的 WDFMEMORY 句柄。 驱动程序可以执行以下作之一:

    请注意,如果驱动程序调用 WdfRequestRetrieveOutputMemory 并将内存句柄传递给 WdfUsbTargetPipeFormatRequestForRead,则驱动程序在驱动程序删除、重用或重新格式化新创建的驱动程序的请求对象之前,不得完成收到的 I/O 请求。 (WdfUsbTargetPipeFormatRequestForRead 递增内存对象的引用计数。删除、重用或重新格式化请求对象会递减内存对象的引用计数。
调用 WdfUsbTargetPipeFormatRequestForRead 格式化 I/O 请求后,驱动程序必须调用 WdfRequestSend 以同步或异步方式将请求(同步或异步)发送到 I/O 目标。

多次调用 WdfUsbTargetPipeFormatRequestForRead,这些调用使用相同的请求不会导致额外的资源分配。 因此,为了减少 WdfRequestCreate 将返回STATUS_INSUFFICIENT_RESOURCES的可能性,驱动程序的 EvtDriverDeviceAdd 回调函数可以调用 WdfRequestCreate 来预分配设备的一个或多个请求对象。 驱动程序随后可以重复使用(调用 WdfRequestReuse)、重新格式化(调用 WdfUsbTargetPipeFormatRequestForRead),并重新发送(调用 WdfRequestSend)每个请求对象,而不会危及STATUS_INSUFFICIENT_RESOURCES从以后调用 WdfRequestCreate返回值。 如果参数值不更改,则对 WdfUsbTargetPipeFormatRequestForRead 的所有后续调用都将返回STATUS_SUCCESS。 (如果驱动程序每次不调用相同的请求格式方法,可能会分配其他资源。

框架在其内部 URB中设置USBD_SHORT_TRANSFER_OK标志。 设置此标志可让数据传输的最后一个数据包小于最大数据包大小。

有关在 I/O 请求完成后获取状态信息的信息,请参阅 获取完成信息

有关 WdfUsbTargetPipeFormatRequestForRead 方法和 USB I/O 目标的详细信息,请参阅 USB I/O 目标

例子

下面的代码示例来自 kmdf_fx2 示例驱动程序。 此示例是一个 EvtIoRead 回调函数,该函数将读取请求转发到 USB 管道。 该示例调用 WdfRequestRetrieveOutputMemory 以获取请求的输出缓冲区,然后格式化读取请求,以便可以将请求发送到 USB 管道。 接下来,该示例注册 CompletionRoutine 回调函数。 最后,它将请求发送到 USB 管道。

VOID 
OsrFxEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
    WDFUSBPIPE  pipe;
    NTSTATUS  status;
    WDFMEMORY  reqMemory;
    PDEVICE_CONTEXT  pDeviceContext;

    //
    // First, validate input parameters.
    //
    if (Length > TEST_BOARD_TRANSFER_BUFFER_SIZE) {
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
 
    pipe = pDeviceContext->BulkReadPipe;
 
    status = WdfRequestRetrieveOutputMemory(
                                            Request,
                                            &reqMemory
                                            );
    if (!NT_SUCCESS(status)){
        goto Exit;
    }
 
    status = WdfUsbTargetPipeFormatRequestForRead(
                                                  pipe,
                                                  Request,
                                                  reqMemory,
                                                  NULL
                                                  ); 
    if (!NT_SUCCESS(status)) {
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(
                                   Request,
                                   EvtRequestReadCompletionRoutine,
                                   pipe
                                   );
    if (WdfRequestSend(
                       Request,
                       WdfUsbTargetPipeGetIoTarget(pipe),
                       WDF_NO_SEND_OPTIONS
                       ) == FALSE) {
        status = WdfRequestGetStatus(Request);
        goto Exit;
    }

 
Exit:
    if (!NT_SUCCESS(status)) {
        WdfRequestCompleteWithInformation(
                                          Request,
                                          status,
                                          0
                                          );
    }
    return;
}

要求

要求 价值
目标平台 普遍
最低 KMDF 版本 1.0
最低 UMDF 版本 2.0
标头 wdfusb.h (包括 Wdfusb.h)
Wdf01000.sys(KMDF):WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
DDI 符合性规则 DriverCreate(kmdf)KmdfIrql(kmdf)KmdfIrql2(kmdf),KmdfIrqlExplicit(kmdf),RequestFormattedValid(kmdf)RequestSendAndForgetNoFormatting(kmdf)RequestSendAndForgetNoFormatting2(kmdf)UsbKmdfIrql(kmdf)UsbKmdfIrql2(kmdf), UsbKmdfIrqlExplicit(kmdf)

另请参阅

WDFMEMORY_OFFSET

WdfRequestCompleteWithInformation

WdfRequestGetStatus

WdfRequestSend

WdfRequestSetCompletionRoutine

WdfUsbInterfaceGetConfiguredPipe