mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 10:14:44 +00:00
1429 lines
39 KiB
C++
1429 lines
39 KiB
C++
![]() |
/*++
|
||
|
|
||
|
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"
|