WdfUsbTargetDeviceSendControlTransferSynchronously function (wdfusb.h)

[Applies to KMDF and UMDF]

The WdfUsbTargetDeviceSendControlTransferSynchronously method builds a USB control transfer request and sends it synchronously to an I/O target.


NTSTATUS WdfUsbTargetDeviceSendControlTransferSynchronously(
  [in]            WDFUSBDEVICE                  UsbDevice,
  [in, optional]  WDFREQUEST                    Request,
  [in, optional]  PWDF_REQUEST_SEND_OPTIONS     RequestOptions,
  [in]            PWDF_USB_CONTROL_SETUP_PACKET SetupPacket,
  [in, optional]  PWDF_MEMORY_DESCRIPTOR        MemoryDescriptor,
  [out, optional] PULONG                        BytesTransferred


[in] UsbDevice

A handle to a USB device object that was obtained from a previous call to WdfUsbTargetDeviceCreateWithParameters.

[in, optional] Request

A handle to a framework request object. This parameter is optional and can be NULL. For more information, see the following Remarks section.

[in, optional] RequestOptions

A pointer to a caller-allocated WDF_REQUEST_SEND_OPTIONS structure that specifies options for the request. This pointer is optional and can be NULL. For more information, see the following Remarks section.

[in] SetupPacket

A pointer to a caller-allocated WDF_USB_CONTROL_SETUP_PACKET structure that describes the control transfer.

[in, optional] MemoryDescriptor

A pointer to a caller-allocated WDF_MEMORY_DESCRIPTOR structure that describes either an input or an output buffer, depending on the device-specific command. This pointer is optional and can be NULL. For more information, see the following Remarks section.

[out, optional] BytesTransferred

A pointer to a location that receives the number of bytes that are transferred. This parameter is optional and can be NULL.

Return value

WdfUsbTargetDeviceSendControlTransferSynchronously returns the I/O target's completion status value if the operation succeeds. Otherwise, this method can return one of the following values:

Return code Description
An invalid parameter was detected.
Insufficient memory was available.
An invalid memory descriptor was specified, or the specified I/O request was already queued to an I/O target.
The driver supplied a time-out value and the request did not complete within the allotted time.

This method also might return other NTSTATUS values.

A bug check occurs if the driver supplies an invalid object handle.


Use the WdfUsbTargetDeviceSendControlTransferSynchronously method to send a USB control transfer request synchronously. To send such requests asynchronously, use WdfUsbTargetDeviceFormatRequestForControlTransfer, followed by WdfRequestSend.

The WdfUsbTargetDeviceSendControlTransferSynchronously method does not return until the request has completed, unless the driver supplies a time-out value in the WDF_REQUEST_SEND_OPTIONS structure that the RequestOptions parameter points to, or unless an error is detected.

You can forward an I/O request that your driver received in an I/O queue, or you can create and send a new request. In either case, the framework requires a request object and, depending on the type of control transfer, possibly some buffer space.

To forward an I/O request that your driver received in an I/O queue:

  1. Specify the received request's handle for the Request parameter.
  2. Use the received request's input or output buffer for the MemoryDescriptor parameter.

    The driver can call WdfRequestRetrieveInputMemory or WdfRequestRetrieveOutputMemory to obtain a handle to a framework memory object that represents the request's input or output buffer and then place that handle in the WDF_MEMORY_DESCRIPTOR structure that the driver supplies for the MemoryDescriptor parameter.

To create and send a new request:
  1. Supply a NULL request handle in the Request parameter, or create a new request object and supply its handle:
    • If you supply a NULL request handle, the framework uses an internal request object. This technique is simple to use, but the driver cannot cancel the request.
    • If you call WdfRequestCreate to create one or more request objects, you can reuse these request objects by calling WdfRequestReuse. This technique enables your driver's EvtDriverDeviceAdd callback function to preallocate request objects for a device. Additionally, another driver thread can call WdfRequestCancelSentRequest to cancel the request, if necessary.

    Your driver can specify a non-NULL RequestOptions parameter, whether the driver provides a non-NULL or a NULL Request parameter. You can, for example, use the RequestOptions parameter to specify a time-out value.

  2. Provide buffer space for the WdfUsbTargetDeviceSendControlTransferSynchronously method's MemoryDescriptor parameter.

    Your driver can specify this buffer space as a locally allocated buffer, as a WDFMEMORY handle, or as an MDL. You can use whichever method is most convenient.

    If necessary, the framework converts the buffer description to one that is correct for the I/O target's method for accessing data buffers.

    The following techniques are available:

    • Supply a local buffer

      Because WdfUsbTargetDeviceSendControlTransferSynchronously handles I/O requests synchronously, the driver can create request buffers that are local to the calling routine, as shown in the following code example.

      WDF_MEMORY_DESCRIPTOR  memoryDescriptor;
      MY_BUFFER_TYPE  myBuffer;
                                        (PVOID) &myBuffer,
    • Supply a WDFMEMORY handle

      Call WdfMemoryCreate or WdfMemoryCreatePreallocated to obtain a handle to framework-managed memory, as shown in the following code example.

      WDF_MEMORY_DESCRIPTOR  memoryDescriptor;
      WDFMEMORY  memoryHandle = NULL;
      status = WdfMemoryCreate(NULL,

      Alternatively, the driver can call WdfRequestRetrieveInputMemory or WdfRequestRetrieveOutputMemory to obtain a handle to a framework memory object that represents a received I/O request's buffer, if you want the driver to pass that buffer's contents to the I/O target. The driver must not complete the received I/O request until the new request that WdfUsbTargetDeviceSendControlTransferSynchronously sends to the I/O target has been deleted, reused, or reformatted. (WdfUsbTargetDeviceSendControlTransferSynchronously increments the memory object's reference count. Deleting, reusing, or reformatting a request object decrements the memory object's reference count.)

    • Supply an MDL

      Drivers can obtain MDLs that are associated with a received I/O request by calling WdfRequestRetrieveInputWdmMdl or WdfRequestRetrieveOutputWdmMdl.

The framework sets the USBD_SHORT_TRANSFER_OK flag in its internal URB. Setting this flag allows the last packet of a data transfer to be less than the maximum packet size.

For information about obtaining status information after an I/O request completes, see Obtaining Completion Information.

For more information about the WdfUsbTargetDeviceSendControlTransferSynchronously method and USB I/O targets, see USB I/O Targets.


The following code example initializes a WDF_USB_CONTROL_SETUP_PACKET structure and then calls WdfUsbTargetDeviceSendControlTransferSynchronously to send a vendor-specific control transfer.



status = WdfUsbTargetDeviceSendControlTransferSynchronously(
return status;


Target Platform Universal
Minimum KMDF version 1.0
Minimum UMDF version 2.0
Header wdfusb.h (include Wdfusb.h)
Library Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
DDI compliance rules DriverCreate(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), RequestForUrbXrb(kmdf), SyncReqSend(kmdf), UsbKmdfIrql(kmdf), UsbKmdfIrql2(kmdf), UsbKmdfIrqlExplicit(kmdf)

See also