Void DeviceManagerImpl::EnumerateAllFactoryDevices()
{
    // 1. Mark matching devices as NOT enumerated.
    // 2. Call factory to enumerate all HW devices, adding any device that 
    //    was not matched.
    // 3. Remove non-matching devices.

    Lock::Locker deviceLock(GetLock());

    DeviceCreateDesc* devDesc, *nextdevDesc;

    // 1.
    for(devDesc = Devices.GetFirst();
        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
    {
        //if (devDesc->pFactory == factory)
            devDesc->Enumerated = false;
    }
    
    // 2.
    DeviceFactory* factory = Factories.GetFirst();
    while(!Factories.IsNull(factory))
    {
        EnumerateFactoryDevices(factory);
        factory = factory->pNext;
    }

    
    // 3.
    for(devDesc = Devices.GetFirst();
        !Devices.IsNull(devDesc);  devDesc = nextdevDesc)
    {
        // In case 'devDesc' gets removed.
        nextdevDesc = devDesc->pNext; 

        // Note, device might be not enumerated since it is opened and
        // in use! Do NOT notify 'device removed' in this case (!AB)
        if (!devDesc->Enumerated)
        {
            // This deletes the devDesc for HandleCount == 0 due to Release in DeviceHandle.
            CallOnDeviceRemoved(devDesc);

            /*
            if (devDesc->HandleCount == 0)
            {                
                // Device must be dead if it ever existed, since it AddRefs to us.
                // ~DeviceCreateDesc removes its node from list.
                OVR_ASSERT(!devDesc->pDevice);
                delete devDesc;
            }
            */
        }
    }

    return 0;
}
void DeviceManagerImpl::DetectHIDDevice(const HIDDeviceDesc& hidDevDesc)
{
    Lock::Locker deviceLock(GetLock());
    DeviceFactory* factory = Factories.GetFirst();
    while(!Factories.IsNull(factory))
    {
        if (factory->DetectHIDDevice(this, hidDevDesc))
            break;
        factory = factory->pNext;
    }
    
}
Ptr<DeviceCreateDesc> DeviceManagerImpl::FindHIDDevice(const HIDDeviceDesc& hidDevDesc)
{
    Lock::Locker deviceLock(GetLock());
    DeviceCreateDesc* devDesc;
    
    for (devDesc = Devices.GetFirst();
        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
    {
        if (devDesc->MatchHIDDevice(hidDevDesc))
            return devDesc;
    }
    return NULL;
}
Ptr<DeviceCreateDesc> DeviceManagerImpl::FindDevice(
    const String& path, 
    DeviceType deviceType)
{
    Lock::Locker deviceLock(GetLock());
    DeviceCreateDesc* devDesc;

    for (devDesc = Devices.GetFirst();
        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
    {
        if ((deviceType == Device_None || deviceType == devDesc->Type) &&
            devDesc->MatchDevice(path))
            return devDesc;
    }
    return NULL;
}
DeviceEnumerator<> DeviceManagerImpl::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
{
    Lock::Locker deviceLock(GetLock());
    
    if (Devices.IsEmpty())
        return DeviceEnumerator<>();

    DeviceCreateDesc*  firstDeviceDesc = Devices.GetFirst();
    DeviceEnumerator<> e = enumeratorFromHandle(DeviceHandle(firstDeviceDesc), args);

    if (!args.MatchRule(firstDeviceDesc->Type, firstDeviceDesc->Enumerated))
    {
        e.Next();
    }
    
    return e;
}
Ptr<DeviceCreateDesc> DeviceManagerImpl::FindHIDDevice(const HIDDeviceDesc& hidDevDesc, bool created)
{
    Lock::Locker deviceLock(GetLock());
    DeviceCreateDesc* devDesc;
    
    for (devDesc = Devices.GetFirst();
        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
    {
        if (created)
        {   // Search for matching device that is created
            if (devDesc->MatchHIDDevice(hidDevDesc) && devDesc->pDevice)
                return devDesc;
        }
        else
        {   // Search for any matching device
            if (devDesc->MatchHIDDevice(hidDevDesc))
                return devDesc;
        }
    }
    return NULL;
}
bool DeviceManagerThread::OnMessage(MessageType type, const String& devicePath)
{
	Notifier::DeviceMessageType notifierMessageType = Notifier::DeviceMessage_DeviceAdded;
	if (type == DeviceAdded)
	{
	}
	else if (type == DeviceRemoved)
	{
		notifierMessageType = Notifier::DeviceMessage_DeviceRemoved;
	}
	else
	{
		OVR_ASSERT(false);
	}

	bool error = false;
    bool deviceFound = false;
	for (UPInt i = 0; i < MessageNotifiers.GetSize(); i++)
    {
		if (MessageNotifiers[i] && 
			MessageNotifiers[i]->OnDeviceMessage(notifierMessageType, devicePath, &error))
		{
			// The notifier belonged to a device with the specified device name so we're done.
            deviceFound = true;
			break;
		}
    }
    if (type == DeviceAdded && !deviceFound)
    {
        Lock::Locker devMgrLock(&DevMgrLock);
        // a new device was connected. Go through all device factories and
        // try to detect the device using HIDDeviceDesc.
        HIDDeviceDesc devDesc;
        if (pDeviceMgr->GetHIDDeviceDesc(devicePath, &devDesc))
        {
            Lock::Locker deviceLock(pDeviceMgr->GetLock());
            DeviceFactory* factory = pDeviceMgr->Factories.GetFirst();
            while(!pDeviceMgr->Factories.IsNull(factory))
            {
                if (factory->DetectHIDDevice(pDeviceMgr, devDesc))
                {
                    deviceFound = true;
                    break;
                }
                factory = factory->pNext;
            }
        }
    }

    if (!deviceFound && strstr(devicePath.ToCStr(), "#OVR00"))
    {
        Ptr<DeviceManager> pmgr;
        {
            Lock::Locker devMgrLock(&DevMgrLock);
            pmgr = pDeviceMgr;
        }
        // HMD plugged/unplugged
        // This is not a final solution to enumerate HMD devices and get
        // a first available handle. This won't work with multiple rifts.
        // @TODO (!AB)
        pmgr->EnumerateDevices<HMDDevice>();
    }

	return !error;
}