UsbDk: USB devices lists synchronization logic

This patch introduces logic for synchronization of our USB
devices list with DEVICE_RELATIONS structure received on QDR.

Signed-off-by: Dmitry Fleytman <dfleytma@redhat.com>
This commit is contained in:
Dmitry Fleytman 2014-03-27 14:38:56 +02:00
parent ed5be722ea
commit 17a328fb71
2 changed files with 57 additions and 1 deletions

View file

@ -170,6 +170,51 @@ void CDeviceRelations::PushBack(PDEVICE_OBJECT Relation)
m_Relations->Objects[m_PushPosition++] = Relation;
}
void CUsbDkFilterDevice::DropRemovedDevices(const CDeviceRelations &Relations)
{
m_ChildrenDevices.ForEachDetachedIf([&Relations](CUsbDkChildDevice *Child) { return !Relations.Contains(*Child); },
[](CUsbDkChildDevice *Child) -> bool { delete Child; return true; });
}
void CUsbDkFilterDevice::AddNewDevices(const CDeviceRelations &Relations)
{
Relations.ForEachIf([this](PDEVICE_OBJECT PDO){ return !IsChildRegistered(PDO); },
[this](PDEVICE_OBJECT PDO){ RegisterNewChild(PDO); return true; });
}
void CUsbDkFilterDevice::RegisterNewChild(PDEVICE_OBJECT PDO)
{
CWdmDeviceAccess pdoAccess(PDO);
CObjHolder<CRegText> DevID(pdoAccess.GetDeviceID());
if (!DevID || DevID->empty())
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! No Device IDs read");
return;
}
CObjHolder<CRegText> InstanceID(pdoAccess.GetInstanceID());
if (!InstanceID || InstanceID->empty())
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! No Instance ID read");
return;
}
CUsbDkChildDevice *Device = new CUsbDkChildDevice(DevID, InstanceID, PDO);
if (Device == nullptr)
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Cannot allocate child device instance");
return;
}
DevID.detach();
InstanceID.detach();
m_ChildrenDevices.PushBack(Device);
}
void CUsbDkFilterDevice::ClearChildrenList()
{
m_ChildrenDevices.ForEachDetached([](CUsbDkChildDevice* Child) { delete Child; return true; });

View file

@ -34,9 +34,12 @@ public:
PCWCHAR InstanceID() const { return *m_InstanceID->begin(); }
PDEVICE_OBJECT PDO() const { ObReferenceObject(m_PDO); return m_PDO; }
bool Match(PCWCHAR deviceID, PCWCHAR instanceID)
bool Match(PCWCHAR deviceID, PCWCHAR instanceID) const
{ return m_DeviceID->Match(deviceID) && m_InstanceID->Match(instanceID); }
bool Match(PDEVICE_OBJECT PDO) const
{ return m_PDO == PDO; }
void Dump();
PLIST_ENTRY GetListEntry()
@ -55,6 +58,8 @@ private:
CUsbDkChildDevice& operator= (const CUsbDkChildDevice&) = delete;
};
class CDeviceRelations;
class CUsbDkFilterDevice : private CWdfDevice, public CAllocatable<NonPagedPool, 'DFHR'>
{
public:
@ -101,6 +106,12 @@ private:
bool ShouldAttach();
void ClearChildrenList();
void DropRemovedDevices(const CDeviceRelations &Relations);
void AddNewDevices(const CDeviceRelations &Relations);
bool IsChildRegistered(PDEVICE_OBJECT PDO)
{ return !m_ChildrenDevices.ForEachIf([PDO](CUsbDkChildDevice *Child){ return Child->Match(PDO); }, ConstFalse); }
void RegisterNewChild(PDEVICE_OBJECT PDO);
CWdfWorkitem m_QDRCompletionWorkItem;
PIRP m_QDRIrp = nullptr;