WdfUsbTargetPipeWriteSynchronously 函数 (wdfusb.h)

[适用于 KMDF 和 UMDF]

WdfUsbTargetPipeWriteSynchronously 方法生成写入请求并将其同步发送到指定的 USB 输出管道。

语法

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

参数

[in] Pipe

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

[in, optional] Request

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

[in, optional] RequestOptions

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

[in, optional] MemoryDescriptor

指向调用方分配的 WDF_MEMORY_DESCRIPTOR 结构的指针,该结构描述包含要写入到设备的数据的缓冲区。 有关此缓冲区的详细信息,请参阅以下“备注”部分。

[out, optional] BytesWritten

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

返回值

WdfUsbTargetPipeWriteSynchronously 如果操作成功,则返回 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_IO_TIMEOUT
驱动程序提供了超时值,请求未在分配的时间内完成。
STATUS_REQUEST_NOT_ACCEPTED
Request 参数表示的 I/O 请求数据包(IRP),不提供足够的 IO_STACK_LOCATION 结构,使驱动程序能够转发请求。
 

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

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

言论

使用 WdfUsbTargetPipeWriteSynchronously 方法同步发送写入请求。 若要异步发送写入请求,请使用 WdfUsbTargetPipeFormatRequestForWrite,后跟 WdfRequestSend

指定的管道必须是输出管道,管道的 类型 必须 WdfUsbPipeTypeBulkWdfUsbPipeTypeInterrupt

WdfUsbTargetPipeWriteSynchronously 方法在请求完成之前不会返回,除非驱动程序在 RequestOptions 参数的 WDF_REQUEST_SEND_OPTIONS 结构中提供超时值,或者除非检测到错误。

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

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

  1. 请求 参数指定收到的请求的句柄。
  2. MemoryDescriptor 参数使用收到的请求的输入缓冲区。

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

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

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

创建新的 I/O 请求:

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

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

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

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

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

    可以使用以下技术:

    • 提供本地缓冲区

      由于 WdfUsbTargetPipeWriteSynchronously 同步处理 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 目标,驱动程序可以调用 WdfRequestRetrieveInputMemory 以获取表示收到的 I/O 请求输入缓冲区的框架内存对象的句柄。 在 WdfUsbTargetPipeWriteSynchronously 发送到 I/O 目标的新请求已删除、重复使用或重新格式化之前,驱动程序不得完成收到的 I/O 请求。 (WdfUsbTargetPipeWriteSynchronously 递增内存对象的引用计数。删除、重用或重新格式化请求对象会递减内存对象的引用计数。

    • 提供 MDL

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

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

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

例子

下面的代码示例创建一个内存对象,获取指向对象的缓冲区的指针,填充缓冲区,并使用缓冲区作为输入来 WdfUsbTargetPipeWriteSynchronously

WDF_MEMORY_DESCRIPTOR  writeBufDesc;
WDFMEMORY  wdfMemory;
ULONG  writeSize, bytesWritten;
size_t  bufferSize;
NTSTATUS status;

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

writeBuffer = WdfMemoryGetBuffer(
                                 wdfMemory,
                                 &bufferSize
                                 );

FillMyBuffer(
             writeBuffer,
             writeSize
             );

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
                                  &writeBufDesc,
                                  writeBuffer,
                                  writeSize
                                  );

status = WdfUsbTargetPipeWriteSynchronously(
                                            pipeHandle,
                                            NULL,
                                            NULL,
                                            &writeBufDesc,
                                            &bytesWritten
                                            );

要求

要求 价值
目标平台 普遍
最低 KMDF 版本 1.0
最低 UMDF 版本 2.0
标头 wdfusb.h (包括 Wdfusb.h)
Wdf01000.sys(KMDF):WUDFx02000.dll (UMDF)
IRQL PASSIVE_LEVEL
DDI 符合性规则 DriverCreate(kmdf)InternalIoctlReqs(kmdf)IoctlReqs(kmdf)KmdfIrql(kmdf)KmdfIrql2(kmdf)、KmdfIrqlExplicit(kmdf)、ReadReqs(kmdf)SyncReqSend(kmdf)UsbKmdfIrql(kmdf)UsbKmdfIrql2(kmdf)、UsbKmdfIrqlExplicit(kmdf)

另请参阅

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER

WdfMemoryCreate

WdfMemoryGetBuffer

WdfRequestCancelSentRequest

WdfUsbTargetPipeReadSynchronously