[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_opt_ WDFREQUEST Request, _In_opt_ PWDF_REQUEST_SEND_OPTIONS RequestOptions, _In_ PWDF_USB_CONTROL_SETUP_PACKET SetupPacket, _In_opt_ PWDF_MEMORY_DESCRIPTOR MemoryDescriptor, _Out_opt_ PULONG BytesTransferred );
A handle to a USB device object that was obtained from a previous call to WdfUsbTargetDeviceCreateWithParameters.
A handle to a framework request object. This parameter is optional and can be NULL. For more information, see the following Remarks section.
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.
A pointer to a caller-allocated WDF_USB_CONTROL_SETUP_PACKET structure that describes the control transfer.
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.
A pointer to a location that receives the number of bytes that are transferred. This parameter is optional and can be NULL.
WdfUsbTargetDeviceSendControlTransferSynchronously returns the I/O target's completion status value if the operation succeeds. Otherwise, this method can return one of the following values:
||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:
Specify the received request's handle for the Request parameter.
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.
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.
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; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor, (PVOID) &myBuffer, sizeof(myBuffer));
Supply a WDFMEMORY handle
Call WdfMemoryCreate or WdfMemoryCreatePreallocated to obtain a handle to framework-managed memory, as shown in the following code example.
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.)
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);
- Supply an MDL Drivers can obtain MDLs that are associated with a received I/O request by calling WdfRequestRetrieveInputWdmMdl or WdfRequestRetrieveOutputWdmMdl.
- Supply a local buffer
WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR( &controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, USBFX2LK_REENUMERATE, 0, 0 ); status = WdfUsbTargetDeviceSendControlTransferSynchronously( UsbDevice, WDF_NO_HANDLE, NULL, &controlSetupPacket, NULL, NULL ); return status;
|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, KmdfIrql, KmdfIrql2, RequestForUrbXrb, SyncReqSend, UsbKmdfIrql, UsbKmdfIrql2|