USBDK/UsbDk/ControlDevice.cpp
Pavel Gurvich 771555ed40 UsbDk: prepare FilterDevice for device enumeration
FilterDevice: fix functions of CUsbDkChildDevice;
add GetChildrenCount() to CUsbDkFilterDevice;
Make m_ChildDevices counting list

Signed-off-by: Pavel Gurvich <pavel@daynix.com>
Signed-off-by: Dmitry Fleytman <dfleytma@redhat.com>
2014-05-11 19:26:10 +03:00

176 lines
4.9 KiB
C++

#include "ControlDevice.h"
#include "trace.h"
#include "ControlDevice.tmh"
#define MAX_DEVICE_ID_LEN (200)
#include "Public.h"
class CUsbDkControlDeviceInit : public CDeviceInit
{
public:
CUsbDkControlDeviceInit()
{}
NTSTATUS Create(WDFDRIVER Driver);
CUsbDkControlDeviceInit(const CUsbDkControlDeviceInit&) = delete;
CUsbDkControlDeviceInit& operator= (const CUsbDkControlDeviceInit&) = delete;
};
NTSTATUS CUsbDkControlDeviceInit::Create(WDFDRIVER Driver)
{
if (!CDeviceInit::Create(Driver, SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX))
{
return STATUS_INSUFFICIENT_RESOURCES;
}
SetExclusive();
SetIoBuffered();
DECLARE_CONST_UNICODE_STRING(ntDeviceName, USBDK_DEVICE_NAME);
return SetName(ntDeviceName);
}
void CUsbDkControlDeviceQueue::SetCallbacks(WDF_IO_QUEUE_CONFIG &QueueConfig)
{
QueueConfig.EvtIoDeviceControl = CUsbDkControlDeviceQueue::DeviceControl;
}
void CUsbDkControlDeviceQueue::DeviceControl(WDFQUEUE Queue,
WDFREQUEST Request,
size_t OutputBufferLength,
size_t InputBufferLength,
ULONG IoControlCode)
{
UNREFERENCED_PARAMETER(Queue);
UNREFERENCED_PARAMETER(OutputBufferLength);
UNREFERENCED_PARAMETER(InputBufferLength);
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, "%!FUNC! Request arrived");
switch (IoControlCode)
{
case IOCTL_USBDK_PING:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, "Called IOCTL_USBDK_PING\n");
//TEMP: Dump children devices
{
auto devExt = UsbDkControlGetContext(WdfIoQueueGetDevice(Queue));
devExt->UsbDkControl->DumpAllChildren();
}
LPTSTR outBuff;
size_t outBuffLen;
status = WdfRequestRetrieveOutputBuffer(Request, 0, (PVOID *)&outBuff, &outBuffLen);
if (!NT_SUCCESS(status)) {
break;
}
wcsncpy(outBuff, TEXT("Pong!"), outBuffLen/sizeof(TCHAR));
WdfRequestSetInformation(Request, outBuffLen);
status = STATUS_SUCCESS;
}
break;
}
WdfRequestComplete(Request, status);
}
void CUsbDkControlDevice::DumpAllChildren()
{
m_FilterDevices.ForEach([](CUsbDkFilterDevice *Filter)
{
Filter->EnumerateChildren([](CUsbDkChildDevice *Child){ Child->Dump(); return true; });
return true;
});
}
NTSTATUS CUsbDkControlDevice::Create(WDFDRIVER Driver)
{
CUsbDkControlDeviceInit DeviceInit;
auto status = DeviceInit.Create(Driver);
if (!NT_SUCCESS(status))
{
return status;
}
WDF_OBJECT_ATTRIBUTES attr;
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, USBDK_CONTROL_DEVICE_EXTENSION);
status = CWdfControlDevice::Create(DeviceInit, attr);
if (!NT_SUCCESS(status))
{
return status;
}
DECLARE_CONST_UNICODE_STRING(ntDosDeviceName, USBDK_DOSDEVICE_NAME);
status = CreateSymLink(ntDosDeviceName);
if (!NT_SUCCESS(status))
{
return status;
}
m_DeviceQueue = new CUsbDkControlDeviceQueue(*this, WdfIoQueueDispatchSequential);
status = m_DeviceQueue->Create();
if (NT_SUCCESS(status))
{
auto deviceContext = UsbDkControlGetContext(m_Device);
deviceContext->UsbDkControl = this;
FinishInitializing();
}
return status;
}
CRefCountingHolder<CUsbDkControlDevice> *CUsbDkControlDevice::m_UsbDkControlDevice = nullptr;
CUsbDkControlDevice* CUsbDkControlDevice::Reference(WDFDRIVER Driver)
{
if (!m_UsbDkControlDevice->InitialAddRef())
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! control device already exists");
return m_UsbDkControlDevice->Get();
}
else
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! creating control device");
}
CUsbDkControlDevice *dev = new CUsbDkControlDevice();
if (dev == nullptr)
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! cannot allocate control device");
m_UsbDkControlDevice->Release();
return nullptr;
}
*m_UsbDkControlDevice = dev;
auto status = (*m_UsbDkControlDevice)->Create(Driver);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_CONTROLDEVICE, "%!FUNC! cannot create control device %!STATUS!", status);
m_UsbDkControlDevice->Release();
return nullptr;
}
return dev;
}
bool CUsbDkControlDevice::Allocate()
{
ASSERT(m_UsbDkControlDevice == nullptr);
m_UsbDkControlDevice = new CRefCountingHolder<CUsbDkControlDevice>;
if (m_UsbDkControlDevice == nullptr)
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_CONTROLDEVICE, "%!FUNC! Cannot allocate control device holder");
return false;
}
return true;
}