reactos/sdk/lib/drivers/wdf/shared/targets/usb/fxusbdeviceapi.cpp

1429 lines
39 KiB
C++
Raw Normal View History

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxUsbDeviceAPI.cpp
Abstract:
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#include "fxusbpch.hpp"
extern "C" {
#include "FxUsbDeviceAPI.tmh"
}
//
// Extern "C" all APIs
//
extern "C" {
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
FxUsbTargetDeviceCreate(
__in
PFX_DRIVER_GLOBALS FxDriverGlobals,
__in
FxDeviceBase* Device,
__in
ULONG USBDClientContractVersion,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__out
WDFUSBDEVICE* UsbDevice
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Device - FxDeviceBase object
USBDClientContractVersion - The USBD Client Contract version of the client driver
UsbDevice - Pointer which will receive the created handle
Return Value:
STATUS_SUCCESS - success
STATUS_INSUFFICIENT_RESOURCES - no memory available
...
--*/
{
FxUsbDevice* pUsbDevice;
NTSTATUS status;
//
// Basic parameter validation
//
FxPointerNotNull(FxDriverGlobals, UsbDevice);
*UsbDevice = NULL;
status = FxVerifierCheckIrqlLevel(FxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateObjectAttributes(FxDriverGlobals,
Attributes,
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
if (!NT_SUCCESS(status)) {
return status;
}
pUsbDevice = new(FxDriverGlobals, Attributes) FxUsbDevice(FxDriverGlobals);
if (pUsbDevice == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Perform all init and handle creation functions. Check for error at the
// end and clean up there.
//
status = pUsbDevice->Init(Device);
if (NT_SUCCESS(status)) {
WDFOBJECT device;
device = NULL;
status = pUsbDevice->InitDevice(USBDClientContractVersion);
if (NT_SUCCESS(status)) {
status = pUsbDevice->CreateInterfaces();
}
if (NT_SUCCESS(status)) {
status = Device->AddIoTarget(pUsbDevice);
}
if (NT_SUCCESS(status)) {
status = pUsbDevice->Commit(Attributes, &device, Device);
}
if (NT_SUCCESS(status)) {
*UsbDevice = (WDFUSBDEVICE) device;
}
}
if (!NT_SUCCESS(status)) {
//
// And now free it
//
pUsbDevice->DeleteFromFailedCreate();
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceCreate)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFDEVICE Device,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__out
WDFUSBDEVICE* UsbDevice
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Device - WDFDEVICE handle to which we are attaching the WDFUSBDEVICE handle
to
PUsbDevice - Pointer which will receive the created handle
Return Value:
STATUS_SUCCESS - success
STATUS_INSUFFICIENT_RESOURCES - no memory available
...
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxDeviceBase* pDevice;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Device,
FX_TYPE_DEVICE_BASE,
(PVOID*)&pDevice,
&pFxDriverGlobals);
return FxUsbTargetDeviceCreate(pFxDriverGlobals,
pDevice,
USBD_CLIENT_CONTRACT_VERSION_INVALID,
Attributes,
UsbDevice);
}
__checkReturn
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceCreateWithParameters)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFDEVICE Device,
__in
PWDF_USB_DEVICE_CREATE_CONFIG Config,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__out
WDFUSBDEVICE* UsbDevice
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Device - WDFDEVICE handle to which we are attaching the WDFUSBDEVICE handle
to
PUsbDevice - Pointer which will receive the created handle
Return Value:
STATUS_SUCCESS - success
STATUS_INSUFFICIENT_RESOURCES - no memory available
...
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxDeviceBase* pDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Device,
FX_TYPE_DEVICE_BASE,
(PVOID*)&pDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, Config);
if (Config->Size != sizeof(WDF_USB_DEVICE_CREATE_CONFIG)) {
status = STATUS_INFO_LENGTH_MISMATCH;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDF_USB_DEVICE_CREATE_CONFIG Size 0x%x, expected 0x%x, %!STATUS!",
Config->Size, sizeof(WDF_USB_DEVICE_CREATE_CONFIG), status);
return status;
}
return FxUsbTargetDeviceCreate(pFxDriverGlobals,
pDevice,
Config->USBDClientContractVersion,
Attributes,
UsbDevice);
}
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceRetrieveInformation)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__out
PWDF_USB_DEVICE_INFORMATION Information
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, Information);
if (Information->Size != sizeof(WDF_USB_DEVICE_INFORMATION)) {
status = STATUS_INFO_LENGTH_MISMATCH;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Information size %d, expected %d %!STATUS!",
Information->Size, sizeof(WDF_USB_DEVICE_INFORMATION),
status);
return status;
}
pUsbDevice->GetInformation(Information);
return STATUS_SUCCESS;
}
__drv_maxIRQL(PASSIVE_LEVEL)
VOID
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceGetDeviceDescriptor)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__out
PUSB_DEVICE_DESCRIPTOR UsbDeviceDescriptor
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, UsbDeviceDescriptor);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return;
}
pUsbDevice->CopyDeviceDescriptor(UsbDeviceDescriptor);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceRetrieveConfigDescriptor)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__out_bcount_part_opt(*ConfigDescriptorLength, *ConfigDescriptorLength)
PVOID ConfigDescriptor,
__inout
PUSHORT ConfigDescriptorLength
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ConfigDescriptorLength);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
return pUsbDevice->GetConfigDescriptor(ConfigDescriptor,
ConfigDescriptorLength);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceQueryString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
WDFREQUEST Request,
__in_opt
PWDF_REQUEST_SEND_OPTIONS RequestOptions,
__out_ecount_opt(*NumCharacters)
PUSHORT String,
__inout
PUSHORT NumCharacters,
__in
UCHAR StringIndex,
__in_opt
USHORT LangID
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, NumCharacters);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
if (!NT_SUCCESS(status)) {
return status;
}
status = pUsbDevice->GetString(String,
NumCharacters,
StringIndex,
LangID,
Request,
RequestOptions);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceAllocAndQueryString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
PWDF_OBJECT_ATTRIBUTES StringMemoryAttributes,
__out
WDFMEMORY* StringMemory,
__out_opt
PUSHORT NumCharacters,
__in
UCHAR StringIndex,
__in_opt
USHORT LangID
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
WDFMEMORY hMemory;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
USHORT numChars = 0;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, StringMemory);
*StringMemory = NULL;
if (NumCharacters != NULL) {
*NumCharacters = 0;
}
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateObjectAttributes(pFxDriverGlobals, StringMemoryAttributes);
if (!NT_SUCCESS(status)) {
return status;
}
status = pUsbDevice->GetString(NULL, &numChars, StringIndex, LangID);
if (NT_SUCCESS(status) && numChars > 0) {
FxMemoryObject* pBuffer;
status = FxMemoryObject::_Create(pFxDriverGlobals,
StringMemoryAttributes,
NonPagedPool,
pFxDriverGlobals->Tag,
numChars * sizeof(WCHAR),
&pBuffer);
if (!NT_SUCCESS(status)) {
return STATUS_INSUFFICIENT_RESOURCES;
}
status = pBuffer->Commit(StringMemoryAttributes,
(WDFOBJECT*)&hMemory);
if (NT_SUCCESS(status)) {
status = pUsbDevice->GetString((PUSHORT) pBuffer->GetBuffer(),
&numChars,
StringIndex,
LangID);
if (NT_SUCCESS(status)) {
if (NumCharacters != NULL) {
*NumCharacters = numChars;
}
*StringMemory = hMemory;
}
}
if (!NT_SUCCESS(status)) {
//
// There can only be one context on this object right now,
// so just clear out the one.
//
pBuffer->DeleteFromFailedCreate();
}
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFEXPORT(WdfUsbTargetDeviceFormatRequestForString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
WDFREQUEST Request,
__in
WDFMEMORY Memory,
__in_opt
PWDFMEMORY_OFFSET Offset,
__in
UCHAR StringIndex,
__in_opt
USHORT LangID
)
/*++
Routine Description:
Formats a request so that it can be used to query for a string from the
device.
Arguments:
UsbDevice - device to be queried
Request - request to format
Memory - memory to write the string into
Return Value:
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
IFxMemory* pMemory;
FxUsbDevice* pUsbDevice;
FxRequestBuffer buf;
FxRequest* pRequest;
NTSTATUS status;
size_t bufferSize;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p, StringIndex %d, LandID 0x%x",
UsbDevice, Request, Memory, StringIndex, LangID);
FxObjectHandleGetPtr(pFxDriverGlobals,
Memory,
IFX_TYPE_MEMORY,
(PVOID*) &pMemory);
FxObjectHandleGetPtr(pFxDriverGlobals,
Request,
FX_TYPE_REQUEST,
(PVOID*) &pRequest);
status = pMemory->ValidateMemoryOffsets(Offset);
if (!NT_SUCCESS(status)) {
return status;
}
buf.SetMemory(pMemory, Offset);
bufferSize = buf.GetBufferLength();
//
// the string descriptor is array of WCHARs so the buffer being used must be
// of an integral number of them.
//
if ((bufferSize % sizeof(WCHAR)) != 0) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFMEMORY %p length must be even number of WCHARs, but is %I64d in "
"length, %!STATUS!",
Memory, bufferSize, status);
return status;
}
//
// While the length in the descriptor (bLength) is a byte, so the requested
// buffer cannot be bigger then that, do not check the bufferSize < 0xFF.
// We don't check because the driver can be using the WDFMEMORY as a part
// of a larger structure.
//
//
// Format the request
//
status = pUsbDevice->FormatStringRequest(pRequest, &buf, StringIndex, LangID);
if (NT_SUCCESS(status)) {
FxUsbDeviceStringContext* pContext;
pContext = (FxUsbDeviceStringContext*) pRequest->GetContext();
pContext->m_UsbParameters.Parameters.DeviceString.Buffer = Memory;
pContext->m_UsbParameters.Parameters.DeviceString.StringIndex = StringIndex;
pContext->m_UsbParameters.Parameters.DeviceString.LangID = LangID;
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p, %!STATUS!",
UsbDevice, Request, Memory, status);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceSelectConfig)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
PWDF_OBJECT_ATTRIBUTES PipesAttributes,
__inout
PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, Params);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
if (Params->Size != sizeof(WDF_USB_DEVICE_SELECT_CONFIG_PARAMS)) {
status = STATUS_INFO_LENGTH_MISMATCH;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Params size %d, expected %d %!STATUS!",
Params->Size, sizeof(WDF_USB_DEVICE_SELECT_CONFIG_PARAMS),
status);
return status;
}
//
// Sanity check the Type value as well to be in range.
//
if (Params->Type < WdfUsbTargetDeviceSelectConfigTypeDeconfig
||
Params->Type > WdfUsbTargetDeviceSelectConfigTypeUrb) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Params Type %d not a valid value, %!STATUS!",
Params->Size, status);
return status;
}
#if (FX_CORE_MODE == FX_CORE_USER_MODE)
if ((Params->Type == WdfUsbTargetDeviceSelectConfigTypeDeconfig) ||
(Params->Type == WdfUsbTargetDeviceSelectConfigTypeUrb) ||
(Params->Type == WdfUsbTargetDeviceSelectConfigTypeInterfacesDescriptor)) {
status = STATUS_NOT_SUPPORTED;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Params Type %d not supported for UMDF, %!STATUS!",
Params->Type, status);
return status;
}
#endif
status = FxValidateObjectAttributes(pFxDriverGlobals,
PipesAttributes,
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
if (!NT_SUCCESS(status)) {
return status;
}
if (pUsbDevice->HasMismatchedInterfacesInConfigDescriptor()) {
//
// Config descriptor reported zero interfaces, but we found an
// interface descriptor in it.
//
status = STATUS_INVALID_DEVICE_REQUEST;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p number of interfaces found in the config descriptor "
"does not match bNumInterfaces in config descriptor, failing config "
"operation %!WdfUsbTargetDeviceSelectConfigType!, %!STATUS!",
UsbDevice, Params->Type, status);
return status;
}
else if (pUsbDevice->GetNumInterfaces() == 0) {
//
// Special case the zero interface case and exit early
//
status = STATUS_SUCCESS;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p succeeding config operation "
"%!WdfUsbTargetDeviceSelectConfigType! on zero interfaces "
"immediately, %!STATUS!", UsbDevice, Params->Type, status);
return status;
}
switch (Params->Type) {
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
case WdfUsbTargetDeviceSelectConfigTypeDeconfig:
status = pUsbDevice->Deconfig();
break;
case WdfUsbTargetDeviceSelectConfigTypeInterfacesDescriptor:
if (Params->Types.Descriptor.InterfaceDescriptors == NULL ||
Params->Types.Descriptor.NumInterfaceDescriptors == 0) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Either InterfaceDescriptor is NULL or NumInterfaceDescriptors is zero "
"WDFUSBDEVICE %p InterfaceDescriptor %p NumInterfaceDescriptors 0x%x"
"%!WdfUsbTargetDeviceSelectConfigType! %!STATUS!", UsbDevice,
Params->Types.Descriptor.InterfaceDescriptors,
Params->Types.Descriptor.NumInterfaceDescriptors,
Params->Type,
status);
}
else {
status = pUsbDevice->SelectConfigDescriptor(
PipesAttributes,
Params);
}
break;
case WdfUsbTargetDeviceSelectConfigTypeUrb:
//
// Since the USBD macro's dont include the USBD_PIPE_INFORMATION for 0 EP's,
// make the length check to use
// sizeof(struct _URB_SELECT_CONFIGURATION) - sizeof(USBD_PIPE_INFORMATION)
//
if (Params->Types.Urb.Urb == NULL ||
Params->Types.Urb.Urb->UrbHeader.Function != URB_FUNCTION_SELECT_CONFIGURATION ||
Params->Types.Urb.Urb->UrbHeader.Length <
(sizeof(struct _URB_SELECT_CONFIGURATION) - sizeof(USBD_PIPE_INFORMATION))) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Either URB passed in was NULL or the URB Function or Length was invalid "
" WDFUSBDEVICE %p Urb 0x%p "
"%!WdfUsbTargetDeviceSelectConfigType!"
" %!STATUS!", UsbDevice,
Params->Types.Urb.Urb,
Params->Type,
status);
}
else {
status = pUsbDevice->SelectConfig(
PipesAttributes,
Params->Types.Urb.Urb,
FxUrbTypeLegacy,
NULL);
}
break;
#endif
case WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs:
if (Params->Types.MultiInterface.Pairs == NULL) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p SettingPairs Array passed is NULL, %!STATUS!",
pUsbDevice->GetHandle(),status);
break;
}
else if (Params->Types.MultiInterface.NumberInterfaces !=
pUsbDevice->GetNumInterfaces()) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p MultiInterface.NumberInterfaces %d != %d "
"(reported num interfaces), %!STATUS!",
pUsbDevice->GetHandle(),
Params->Types.MultiInterface.NumberInterfaces,
pUsbDevice->GetNumInterfaces(), status);
break;
}
// || || Fall through || ||
// \/ \/ \/ \/
case WdfUsbTargetDeviceSelectConfigTypeMultiInterface:
//
// Validate SettingIndexes passed-in
//
for (ULONG i = 0;
i < Params->Types.MultiInterface.NumberInterfaces;
i++) {
PWDF_USB_INTERFACE_SETTING_PAIR pair;
FxUsbInterface * pUsbInterface;
UCHAR numSettings;
pair = &(Params->Types.MultiInterface.Pairs[i]);
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
pair->UsbInterface,
FX_TYPE_USB_INTERFACE,
(PVOID*) &pUsbInterface);
numSettings = pUsbInterface->GetNumSettings();
if (pair->SettingIndex >= numSettings) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p SettingPairs contains invalid SettingIndex"
" for WDFUSBINTERFACE %p. Setting index passed in: %d, "
"max index: %d, returning %!STATUS!",
pUsbDevice->GetHandle(),
pair->UsbInterface,
pair->SettingIndex,
pUsbInterface->GetNumSettings() - 1,
status);
return status;
}
}
status = pUsbDevice->SelectConfigMulti(
PipesAttributes,
Params);
break;
case WdfUsbTargetDeviceSelectConfigTypeSingleInterface:
status = pUsbDevice->SelectConfigSingle( //vm changed name from SelectConfigAuto
PipesAttributes,
Params);
break;
default:
status = STATUS_INVALID_PARAMETER;
}
return status;
}
__drv_maxIRQL(DISPATCH_LEVEL)
UCHAR
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceGetNumInterfaces)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice
)
{
DDI_ENTRY();
FxUsbDevice* pUsbDevice;
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice);
return pUsbDevice->GetNumInterfaces();
}
__drv_maxIRQL(DISPATCH_LEVEL)
USBD_CONFIGURATION_HANDLE
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceWdmGetConfigurationHandle)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice
)
{
DDI_ENTRY();
FxUsbDevice* pUsbDevice;
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice);
return pUsbDevice->GetConfigHandle();
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFEXPORT(WdfUsbTargetDeviceSendControlTransferSynchronously)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__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
)
/*++
Routine Description:
Synchronously sends a control transfer to the default control pipe on the
device.
Arguments:
UsbDevice - the target representing the device
Request - Request whose PIRP to use
RequestOptions - options to use when sending the request
SetupPacket - control setup packet to be used in the transfer
MemoryDescriptor - memory to use in the transfer after the setup packet
BytesTransferred - number of bytes sent to or by the device
Return Value:
NTSTATUS
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxRequestBuffer buf;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxUsbDeviceControlContext context(FxUrbTypeLegacy);
FxSyncRequest request(pFxDriverGlobals, &context, Request);
//
// FxSyncRequest always succeesds for KM but can fail for UM.
//
status = request.Initialize();
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Failed to initialize FxSyncRequest");
return status;
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p control transfer sync", UsbDevice);
FxPointerNotNull(pFxDriverGlobals, SetupPacket);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
if (!NT_SUCCESS(status)) {
return status;
}
status = buf.ValidateMemoryDescriptor(
pFxDriverGlobals,
MemoryDescriptor,
MemoryDescriptorNullAllowed | MemoryDescriptorNoBufferAllowed
);
if (!NT_SUCCESS(status)) {
return status;
}
status = pUsbDevice->FormatControlRequest(request.m_TrueRequest,
SetupPacket,
&buf);
if (NT_SUCCESS(status)) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, WDFREQUEST %p being submitted",
UsbDevice, request.m_TrueRequest->GetTraceObjectHandle());
status = pUsbDevice->SubmitSync(request.m_TrueRequest, RequestOptions);
if (BytesTransferred != NULL) {
if (NT_SUCCESS(status)) {
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
*BytesTransferred = context.m_Urb->TransferBufferLength;
#elif (FX_CORE_MODE == FX_CORE_USER_MODE)
*BytesTransferred = context.m_UmUrb.UmUrbControlTransfer.TransferBufferLength;
#endif
}
else {
*BytesTransferred = 0;
}
}
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, %!STATUS!", UsbDevice, status);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFEXPORT(WdfUsbTargetDeviceFormatRequestForControlTransfer)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
WDFREQUEST Request,
__in
PWDF_USB_CONTROL_SETUP_PACKET SetupPacket,
__in_opt
WDFMEMORY TransferMemory,
__in_opt
PWDFMEMORY_OFFSET TransferOffset
)
/*++
Routine Description:
Formats a request so that a control transfer can be sent to the device
after this call returns successfully.
Arguments:
UsbDevice - the target representing the device
Request - Request to format
SetupPacket - control setup packet to be used in the transfer
TransferMemory - memory to use in the transfer after the setup packet
TransferOffset - offset into TransferMemory and size override for transfer
length
Return Value:
NTSTATUS
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
IFxMemory* pMemory;
FxUsbDevice* pUsbDevice;
FxRequestBuffer buf;
FxRequest* pRequest;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p",
UsbDevice, Request, TransferMemory);
FxPointerNotNull(pFxDriverGlobals, SetupPacket);
if (TransferMemory != NULL) {
FxObjectHandleGetPtr(pFxDriverGlobals,
TransferMemory,
IFX_TYPE_MEMORY,
(PVOID*) &pMemory);
status = pMemory->ValidateMemoryOffsets(TransferOffset);
if (!NT_SUCCESS(status)) {
return status;
}
buf.SetMemory(pMemory, TransferOffset);
}
else {
pMemory = NULL;
}
FxObjectHandleGetPtr(pFxDriverGlobals,
Request,
FX_TYPE_REQUEST,
(PVOID*) &pRequest);
status = pUsbDevice->FormatControlRequest(pRequest, SetupPacket, &buf);
if (NT_SUCCESS(status)) {
FxUsbDeviceControlContext* pContext;
pContext = (FxUsbDeviceControlContext*) pRequest->GetContext();
RtlCopyMemory(
&pContext->m_UsbParameters.Parameters.DeviceControlTransfer.SetupPacket,
SetupPacket,
sizeof(*SetupPacket)
);
if (pMemory != NULL) {
pContext->m_UsbParameters.Parameters.DeviceControlTransfer.Buffer =
TransferMemory;
}
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"format control request WDFUSBDEVICE %p, WDFREQWUEST %p, WDFMEMORY %p, %!STATUS!",
UsbDevice, Request, TransferMemory, status);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceResetPortSynchronously)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = pUsbDevice->Reset();
return status;
}
#pragma warning(disable:28285)
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceCreateIsochUrb)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__in
ULONG NumberOfIsochPackets,
__out
WDFMEMORY* UrbMemory,
__deref_opt_out_bcount(GET_ISOCH_URB_SIZE(NumberOfIsochPackets))
PURB* Urb
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Attributes - Attributes associated with this object
NumberOfIsochPacket - Maximum number of Isoch packets that will be programmed into this Urb
UrbMemory - The returned handle to the caller for the allocated Urb
Urb - (opt) Pointer to the associated urb buffer.
Return Value:
STATUS_INVALID_PARAMETER - any required parameters are not present/invalid
STATUS_INVALID_DEVICE_STATE - If the client did not specify a client contract verion while
creating the WDFUSBDEVICE
STATUS_INSUFFICIENT_RESOURCES - could not allocated the object that backs
the handle
STATUS_SUCCESS - success
...
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
//
// Basic parameter validation
//
FxPointerNotNull(pFxDriverGlobals, UrbMemory);
if (pUsbDevice->GetUSBDHandle() == NULL) {
status = STATUS_INVALID_DEVICE_STATE;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"USBDEVICE Must have been created with Client Contract Verion Info, %!STATUS!",
status);
return status;
}
status = pUsbDevice->CreateIsochUrb(Attributes,
NumberOfIsochPackets,
UrbMemory,
Urb);
return status;
}
__drv_maxIRQL(DISPATCH_LEVEL)
WDFUSBINTERFACE
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceGetInterface)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
UCHAR InterfaceIndex
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
FxUsbInterface *pUsbInterface;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
pUsbInterface = pUsbDevice->GetInterfaceFromIndex(InterfaceIndex);
if (pUsbInterface != NULL) {
return pUsbInterface->GetHandle();
}
else {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p has %d interfaces, index %d requested, returning "
"NULL handle",
UsbDevice, pUsbDevice->GetNumInterfaces(), InterfaceIndex);
return NULL;
}
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceQueryUsbCapability)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
CONST GUID* CapabilityType,
__in
ULONG CapabilityBufferLength,
__drv_when(CapabilityBufferLength == 0, __out_opt)
__drv_when(CapabilityBufferLength != 0 && ResultLength == NULL, __out_bcount(CapabilityBufferLength))
__drv_when(CapabilityBufferLength != 0 && ResultLength != NULL, __out_bcount_part_opt(CapabilityBufferLength, *ResultLength))
PVOID CapabilityBuffer,
__out_opt
__drv_when(ResultLength != NULL,__deref_out_range(<=,CapabilityBufferLength))
PULONG ResultLength
)
/*++
Routine Description:
Queries USB capability for the device. Such capabilities are available
only with USB 3.0 stack. On earlier stacks this API will fail with
STATUS_NOT_IMPLEMENTED
Arguments:
UsbDevice - Device whose capability is to be queried.
CapabilityType - Type of capability as defined by
IOCTL_INTERNAL_USB_GET_USB_CAPABILITY
CapabilityBufferLength - Length of Capability buffer
CapabilityBuffer - Buffer for capability. Can be NULL if
CapabilitiyBufferLength is 0
ResultLength - Actual length of the capability. This parameter is optional.
Return Value:
STATUS_SUCCESS - success
STATUS_NOT_IMPLEMENTED - Capabilties are not supported by USB stack
STATUS_INSUFFICIENT_RESOURCES - no memory available
...
--*/
{
DDI_ENTRY();
NTSTATUS status;
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
if (CapabilityBufferLength > 0) {
FxPointerNotNull(pFxDriverGlobals, CapabilityBuffer);
}
status = pUsbDevice->QueryUsbCapability(CapabilityType,
CapabilityBufferLength,
CapabilityBuffer,
ResultLength);
return status;
}
} // extern "C"