WdfUsbTargetPipeReadSynchronously 函数 (wdfusb.h)

[适用于 KMDF 和 UMDF]

WdfUsbTargetPipeReadSynchronously 方法生成读取请求,并将其同步发送到指定的 USB 输入管道。

语法

NTSTATUS WdfUsbTargetPipeReadSynchronously(
  [in]            WDFUSBPIPE                Pipe,
  [in, optional]  WDFREQUEST                Request,
  [in, optional]  PWDF_REQUEST_SEND_OPTIONS RequestOptions,
  [in, optional]  PWDF_MEMORY_DESCRIPTOR    MemoryDescriptor,
  [out, optional] PULONG                    BytesRead
);

参数

[in] Pipe

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

[in, optional] Request

框架请求对象的句柄。 此参数是可选的,可以为 NULL。 有关更多信息,请参见下面的“备注”部分。

[in, optional] RequestOptions

指向调用方分配 的WDF_REQUEST_SEND_OPTIONS 结构的指针,该结构指定请求的选项。 此指针是可选的,可以为 NULL。 有关更多信息,请参见下面的“备注”部分。

[in, optional] MemoryDescriptor

指向调用方分配 的WDF_MEMORY_DESCRIPTOR 结构的指针,该结构描述将从设备接收数据的缓冲区。 缓冲区大小必须是管道最大数据包大小的倍数,除非驱动程序已调用 WdfUsbTargetPipeSetNoMaximumPacketSizeCheck。 有关此缓冲区的详细信息,请参阅以下“备注”部分。

[out, optional] BytesRead

指向位置的指针,该位置接收读取的字节数(如果操作成功)。 此参数是可选的,可以为 NULL

返回值

如果操作成功,WdfUsbTargetPipeReadSynchronously 返回 I/O 目标的完成状态值。 否则,此方法可返回以下值之一:

返回代码 说明
STATUS_INFO_LENGTH_MISMATCH
RequestOptions 指向的WDF_REQUEST_SEND_OPTIONS结构的大小不正确。
STATUS_INVALID_PARAMETER
检测到无效的参数。
STATUS_INSUFFICIENT_RESOURCES
可用内存不足。
STATUS_INVALID_DEVICE_REQUEST
调用方的 IRQL 未PASSIVE_LEVEL,指定了无效的内存描述符,管道的类型无效,传输方向无效,或者指定的 I/O 请求已排队到 I/O 目标。
STATUS_INVALID_BUFFER_SIZE
缓冲区大小不是管道最大数据包大小的倍数。
STATUS_IO_TIMEOUT
驱动程序提供了超时值,但请求未在分配的时间内完成。
STATUS_REQUEST_NOT_ACCEPTED
请求参数表示的 I/O 请求数据包 (IRP) 不提供足够的IO_STACK_LOCATION结构来允许驱动程序转发请求。
 

此方法还可能返回其他 NTSTATUS 值

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

注解

使用 WdfUsbTargetPipeReadSynchronously 方法以同步方式发送读取请求。 若要异步发送读取请求,请使用 WdfUsbTargetPipeFormatRequestForRead,然后使用 WdfRequestSend

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

除非驱动程序在 RequestOptions 参数指向的 WDF_REQUEST_SEND_OPTIONS 结构中提供超时值,或者除非检测到错误,否则 WdfUsbTargetPipeReadSynchronously 方法不会返回。

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

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

  1. 为 Request 参数指定收到的 请求 的句柄。
  2. WdfUsbTargetPipeReadSynchronously 方法的 MemoryDescriptor 参数使用收到的请求的输出缓冲区。

    驱动程序必须调用 WdfRequestRetrieveOutputMemory 以获取表示请求输出缓冲区的框架内存对象的句柄,然后将该句柄放在 MemoryDescriptor 指向的WDF_MEMORY_DESCRIPTOR结构中。

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

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

创建新的 I/O 请求:

  1. WdfUsbTargetPipeReadSynchronously 方法的 Request 参数中提供 NULL请求句柄,或创建新的请求对象并提供其句柄:
    • 如果提供 NULL 请求句柄,框架将使用内部请求对象。 此方法易于使用,但驱动程序无法取消请求。
    • 如果调用 WdfRequestCreate 来创建一个或多个请求对象,可以通过调用 WdfRequestReuse 重用这些请求对象。 此方法使驱动程序的 EvtDriverDeviceAdd 回调函数能够预分配设备的请求对象。 此外,如果需要,另一个驱动程序线程可以调用 WdfRequestCancelSentRequest 来取消请求。

    无论驱动程序提供非 NULL 还是 NULL 请求参数,驱动程序都可以指定非 NULLRequestOptions 参数。 例如,可以使用 RequestOptions 参数指定超时值。

  2. WdfUsbTargetPipeReadSynchronously 方法的 MemoryDescriptor 参数提供缓冲区空间。

    驱动程序可以将此缓冲区空间指定为本地分配的缓冲区、WDFMEMORY 句柄或 MDL。 可以使用最方便的方法。

    如有必要,框架会将缓冲区说明转换为适用于 I/O 目标 访问数据缓冲区的方法的正确说明。

    以下技术可用:

    • 提供本地缓冲区

      由于 WdfUsbTargetPipeReadSynchronously 同步处理 I/O 请求,因此驱动程序可以创建调用例程本地的请求缓冲区,如以下代码示例所示。

      WDF_MEMORY_DESCRIPTOR  memoryDescriptor;
      MY_BUFFER_TYPE  myBuffer;
      WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor,
                                        (PVOID) &myBuffer,
                                        sizeof(myBuffer));
      
    • 提供 WDFMEMORY 句柄

      调用 WdfMemoryCreateWdfMemoryCreatePreallocated 以获取框架托管内存的句柄,如以下代码示例所示。

      WDF_MEMORY_DESCRIPTOR  memoryDescriptor;
      WDFMEMORY  memoryHandle = NULL;
      status = WdfMemoryCreate(NULL,
                               NonPagedPool,
                               POOL_TAG,
                               MY_BUFFER_SIZE,
                               &memoryHandle,
                               NULL);
      WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memoryDescriptor,
                                        memoryHandle,
                                        NULL);
      

      或者,如果希望驱动程序将该缓冲区的内容传递给 I/O 目标,驱动程序可以调用 WdfRequestRetrieveOutputMemory 来获取表示接收的 I/O 请求输出缓冲区的框架内存对象的句柄。 在删除、重用或重新格式化 WdfUsbTargetPipeReadSynchronously 发送到 I/O 目标的新请求之前,驱动程序不得完成收到的 I/O 请求。 (WdfUsbTargetPipeReadSynchronous 递 增内存对象的引用计数。删除、重用或重新格式化请求对象会递减内存对象的引用 count.)

    • 提供 MDL

      驱动程序可以通过调用 WdfRequestRetrieveOutputWdmMdl 来获取与收到的 I/O 请求关联的 MDL。

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

如果驱动程序已为管道配置连续读取器,则驱动程序无法调用 WdfUsbTargetPipeReadSynchronously

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

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

示例

下面的代码示例创建一个框架内存对象,初始化 WDF_MEMORY_DESCRIPTOR 结构,并将结构传递给 WdfUsbTargetPipeReadSynchronously。 此示例为请求对象句柄指定 NULL ,因此框架将为 I/O 目标创建新的请求对象。

WDFMEMORY  wdfMemory;
WDF_MEMORY_DESCRIPTOR  readBufDesc;
ULONG  BytesRead;

status = WdfMemoryCreate(
                         WDF_NO_OBJECT_ATTRIBUTES,
                         NonPagedPool,
                         0,
                         readSize,
                         &wdfMemory,
                         NULL
                         );
if (!NT_SUCCESS(status)){
    return ;
}

buffer = WdfMemoryGetBuffer(
                            wdfMemory,
                            NULL
                            );

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
                                  &readBufDesc,
                                  buffer,
                                  readSize
                                  );

status = WdfUsbTargetPipeReadSynchronously(
                                           Pipe,
                                           NULL,
                                           NULL,
                                           &readBufDesc,
                                           &BytesRead
                                           );

要求

要求
目标平台 通用
最低 KMDF 版本 1.0
最低 UMDF 版本 2.0
标头 wdfusb.h (包括 Wdfusb.h)
Library Wdf01000.sys (KMDF) ;WUDFx02000.dll (UMDF)
IRQL PASSIVE_LEVEL
DDI 符合性规则 DriverCreate (kmdf) InternalIoctlReqs (kmdf) IoctlReqs (kmdf) KmdfIrql (kmdf) KmdfIrql2 (kmdf) 、 KmdfIrqlExplicit (kmdf) , SyncReqSend (kmdf) UsbKmdfIrql (kmdf) UsbKmdfIrql2 (kmdf) 、 UsbKmdfIrqlExplicit (kmdf) 、 WriteReqs (kmdf)

另请参阅

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER

WdfMemoryCreate

WdfUsbTargetPipeGetInformation