[Applies to KMDF and UMDF]

A driver's EvtUsbTargetPipeReadComplete event callback function informs the driver that a continuous reader has successfully completed a read request.



void EvtWdfUsbReaderCompletionRoutine(
  size_t NumBytesTransferred,



A handle to a framework pipe object.


A handle to a framework memory object that represents a buffer that contains data from the device.


The number of bytes of data that are in the read buffer.


Driver-defined context information that the driver specified in the EvtUsbTargetPipeReadCompleteContext member of the pipe's WDF_USB_CONTINUOUS_READER_CONFIG structure.

Return Value



To register an EvtUsbTargetPipeReadComplete callback function, the driver must place the function's address in a WDF_USB_CONTINUOUS_READER_CONFIG structure.

If a driver has created a continuous reader for a USB pipe, the framework calls the driver's EvtUsbTargetPipeReadComplete callback function each time the driver's I/O target successfully completes a read request. The callback function is called at the IRQL at which the I/O target completed the read request, which is typically IRQL = DISPATCH_LEVEL, but no higher than DISPATCH_LEVEL. (If the I/O target does not successfully complete a request, the framework calls the driver's EvtUsbTargetPipeReadersFailed callback function.)

To access the buffer that contains data that was read from the device, the driver can call WdfMemoryGetBuffer. The framework writes the data into the buffer, after the header that is defined by the HeaderLength member of the WDF_USB_CONTINUOUS_READER_CONFIG structure. Note that the pointer that WdfMemoryGetBuffer returns points to the beginning of the header, but the EvtUsbTargetPipeReadComplete callback function's NumBytesTransferred parameter does not include the header's length.

By default, the framework deletes the buffer's memory object after the EvtUsbTargetPipeReadComplete callback function returns. However, you might want the memory object to remain valid after the callback function returns. For example, you might want your driver to store the object handle in the framework pipe object's context space so that the driver can process the memory object's contents after the callback function returns. To extend the lifetime of the memory object, the callback function must pass the memory object's handle to WdfObjectReference. Subsequently, the driver must call WdfObjectDereference so that the framework can delete the object.

The framework synchronizes calls to the EvtUsbTargetPipeReadComplete and EvtUsbTargetPipeReadersFailed callback functions according to the following rules:

  • These callback functions do not run simultaneously for an individual USB pipe.

  • If the driver creates multiple continuous readers for multiple USB pipes, with multiple EvtUsbTargetPipeReadComplete and EvtUsbTargetPipeReadersFailed callback functions, the multiple callback functions can run simultaneously.

  • If the driver has specified the default NumPendingReads value or a value that is greater than 1, and if a read request completes while the EvtUsbTargetPipeReadComplete callback function is executing, the framework can call the EvtUsbTargetPipeReadComplete callback function again before the callback function returns.

  • The framework does not synchronize these callback functions with any other callback functions.

In the BufferAttributes member of the WDF_USB_CONTINUOUS_READER_CONFIG structure, your driver can specify EvtCleanupCallback and EvtDestroyCallback callback functions for the memory object. If you specify an EvtCleanupCallback callback function, the framework will call that callback function when it attempts to delete the memory object, after the EvtUsbTargetPipeReadComplete callback function returns. If the EvtUsbTargetPipeReadComplete callback function has called WdfObjectReference, the EvtCleanupCallback callback function (if provided) must not call WdfObjectDereference.

The driver must call WdfObjectDereference when it has finished using the memory object. The framework can then call the driver's EvtDestroyCallback callback function (if provided) and delete the memory object.

For more information about the EvtUsbTargetPipeReadComplete callback function and USB I/O targets, see USB I/O Targets.


To define an EvtUsbTargetPipeReadComplete callback function, you must first provide a function declaration that identifies the type of callback function you’re defining. Windows provides a set of callback function types for drivers. Declaring a function using the callback function types helps Code Analysis for Drivers, Static Driver Verifier (SDV), and other verification tools find errors, and it’s a requirement for writing drivers for the Windows operating system.

For example, to define an EvtUsbTargetPipeReadComplete callback function that is named MyUsbTargetPipeReadComplete, use the EVT_WDF_USB_READER_COMPLETION_ROUTINE type as shown in this code example:

To define an EvtUsbTargetPipeReadComplete callback function that is named MyUsbTargetPipeReadComplete, you must first provide a function declaration that SDV and other verification tools require, as follows:


Then, implement your callback function as follows:

 MyUsbTargetPipeReadComplete (
    WDFMEMORY  Buffer,
    size_t  NumBytesTransferred,
    WDFCONTEXT  Context

The EVT_WDF_USB_READER_COMPLETION_ROUTINE function type is defined in the WdfUsb.h header file. To more accurately identify errors when you run the code analysis tools, be sure to add the Use_decl_annotations annotation to your function definition. The Use_decl_annotations annotation ensures that the annotations that are applied to the EVT_WDF_USB_READER_COMPLETION_ROUTINE function type in the header file are used. For more information about the requirements for function declarations, see Declaring Functions by Using Function Role Types for KMDF Drivers. For information about Use_decl_annotations, see Annotating Function Behavior.


Target Platform Universal
Minimum KMDF version 1.0
Minimum UMDF version 2.0
Header wdfusb.h (include Wdf.h)
IRQL "<=DISPATCH_LEVEL (See Remarks section.)"

See Also