reactos/sdk/lib/drivers/wdf/shared/targets/usb/km/fxusbdeviceapikm.cpp
Victor Perevertkin 8a978a179f
[WDF] Add Windows Driver Framework files
Takern from Microsoft GitHub repo:
d9c6040fe9

Licensed under MIT
2020-11-03 00:06:26 +03:00

445 lines
12 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxUsbDeviceAPI.cpp
Abstract:
Author:
Environment:
kernel mode only
Revision History:
--*/
#include "fxusbpch.hpp"
extern "C" {
#include "FxUsbDeviceApiKm.tmh"
}
//
// Extern "C" all APIs
//
extern "C" {
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceRetrieveCurrentFrameNumber)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__out
PULONG CurrentFrameNumber
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, CurrentFrameNumber);
return pUsbDevice->GetCurrentFrameNumber(CurrentFrameNumber);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceSendUrbSynchronously)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
WDFREQUEST Request,
__in_opt
PWDF_REQUEST_SEND_OPTIONS RequestOptions,
__in_xcount("union bug in SAL")
PURB Urb
)
{
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRequestBuffer buf;
NTSTATUS status;
FxUsbDevice* pUsbDevice;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxUsbUrbContext context;
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, Urb %p", UsbDevice, Urb);
FxPointerNotNull(pFxDriverGlobals, Urb);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
if (!NT_SUCCESS(status)) {
return status;
}
buf.SetBuffer(Urb, 0);
status = FxFormatUrbRequest(pFxDriverGlobals,
pUsbDevice,
request.m_TrueRequest,
&buf,
pUsbDevice->GetUrbType(),
pUsbDevice->GetUSBDHandle());
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);
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"Device %p, Urb %p, %!STATUS!",
UsbDevice, Urb, status);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceFormatRequestForUrb)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
WDFREQUEST Request,
__in
WDFMEMORY UrbMemory,
__in_opt
PWDFMEMORY_OFFSET UrbOffsets
)
{
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, Request %p, Memory %p",
UsbDevice, Request, UrbMemory);
FxPointerNotNull(pFxDriverGlobals, UrbMemory);
FxObjectHandleGetPtr(pFxDriverGlobals,
UrbMemory,
IFX_TYPE_MEMORY,
(PVOID*) &pMemory);
FxObjectHandleGetPtr(pFxDriverGlobals,
Request,
FX_TYPE_REQUEST,
(PVOID*) &pRequest);
status = pMemory->ValidateMemoryOffsets(UrbOffsets);
if (!NT_SUCCESS(status)) {
return status;
}
bufferSize = pMemory->GetBufferSize();
if (UrbOffsets != NULL && UrbOffsets->BufferOffset > 0) {
bufferSize -= UrbOffsets->BufferOffset;
}
if (bufferSize < sizeof(_URB_HEADER)) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"UrbMemory %p buffer size, %I64d, smaller then"
"_URB_HEADER, %!STATUS!",
UrbMemory, pMemory->GetBufferSize(), status);
return status;
}
buf.SetMemory(pMemory, UrbOffsets);
status = FxFormatUrbRequest(pFxDriverGlobals,
pUsbDevice,
pRequest,
&buf,
pUsbDevice->GetUrbType(),
pUsbDevice->GetUSBDHandle());
if (NT_SUCCESS(status)) {
FxUsbUrbContext* pContext;
pContext = (FxUsbUrbContext*) pRequest->GetContext();
pContext->SetUsbType(WdfUsbRequestTypeDeviceUrb);
pContext->m_UsbParameters.Parameters.DeviceUrb.Buffer = UrbMemory;
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, Request %p, Memory %p, %!STATUS!",
UsbDevice, Request, UrbMemory, status);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceIsConnectedSynchronous)(
__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->IsConnected();
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFEXPORT(WdfUsbTargetDeviceCyclePortSynchronously)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice
)
/*++
Routine Description:
Synchronously cycles a device on a USB port. This will cause the device
to be surprise removed and reenumerated. Very similar to the reenumerate
interface we use in the pnp state machine. Usually a driver will do this
after it has downloaded firmware and wants to be reenumerated as a new
device.
Arguments:
UsbDevice - the IOTARGET representing the device
Return Value:
NTSTATUS
--*/
{
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->CyclePort();
return status;
}
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFEXPORT(WdfUsbTargetDeviceFormatRequestForCyclePort)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
WDFREQUEST Request
)
/*++
Routine Description:
Formats a WDFREQUEST so that it will cycle the port and reenumerate the
device when sent.
Arguments:
UsbDevice - the IOTARGET representing the device that will be reenumerated
Request - the request which will be formatted
Return Value:
NTSTATUS
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
FxRequest* pRequest;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxObjectHandleGetPtr(pFxDriverGlobals,
Request,
FX_TYPE_REQUEST,
(PVOID*) &pRequest);
status = pUsbDevice->FormatCycleRequest(pRequest);
return status;
}
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFAPI
WDFEXPORT(WdfUsbTargetDeviceCreateUrb)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__out
WDFMEMORY* UrbMemory,
__deref_opt_out_bcount(sizeof(URB))
PURB* Urb
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Attributes - Attributes associated with this object
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->CreateUrb(Attributes, UrbMemory, Urb);
return status;
}
} // extern "C"