OVR_Win32_DeviceManager.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   OVR_Win32_DeviceManager.cpp
00004 Content     :   Win32 implementation of DeviceManager.
00005 Created     :   September 21, 2012
00006 Authors     :   Michael Antonov
00007 
00008 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
00009 
00010 Use of this software is subject to the terms of the Oculus license
00011 agreement provided at the time of installation or download, or which
00012 otherwise accompanies this software in either electronic or hard copy form.
00013 
00014 *************************************************************************************/
00015 
00016 #include "OVR_Win32_DeviceManager.h"
00017 
00018 // Sensor & HMD Factories
00019 #include "OVR_SensorImpl.h"
00020 #include "OVR_LatencyTestImpl.h"
00021 #include "OVR_Win32_HMDDevice.h"
00022 #include "OVR_Win32_DeviceStatus.h"
00023 #include "OVR_Win32_HIDDevice.h"
00024 
00025 #include "Kernel/OVR_Timer.h"
00026 #include "Kernel/OVR_Std.h"
00027 #include "Kernel/OVR_Log.h"
00028 
00029 DWORD Debug_WaitedObjectCount = 0;
00030 
00031 namespace OVR { namespace Win32 {
00032 
00033 
00034 //-------------------------------------------------------------------------------------
00035 // **** Win32::DeviceManager
00036 
00037 DeviceManager::DeviceManager()
00038 {
00039     HidDeviceManager = *HIDDeviceManager::CreateInternal(this);
00040 }
00041 
00042 DeviceManager::~DeviceManager()
00043 {
00044     // make sure Shutdown was called.
00045     OVR_ASSERT(!pThread);
00046 }
00047 
00048 bool DeviceManager::Initialize(DeviceBase*)
00049 {
00050     if (!DeviceManagerImpl::Initialize(0))
00051         return false;
00052 
00053     pThread = *new DeviceManagerThread(this);
00054     if (!pThread || !pThread->Start())
00055         return false;
00056          
00057     pCreateDesc->pDevice = this;
00058     LogText("OVR::DeviceManager - initialized.\n");
00059     return true;
00060 }
00061 
00062 void DeviceManager::Shutdown()
00063 {   
00064     LogText("OVR::DeviceManager - shutting down.\n");
00065 
00066     // Set Manager shutdown marker variable; this prevents
00067     // any existing DeviceHandle objects from accessing device.
00068     pCreateDesc->pLock->pManager = 0;
00069 
00070     // Push for thread shutdown *WITH NO WAIT*.
00071     // This will have the following effect:
00072     //  - Exit command will get enqueued, which will be executed later on the thread itself.
00073     //  - Beyond this point, this DeviceManager object may be deleted by our caller.
00074     //  - Other commands, such as CreateDevice, may execute before ExitCommand, but they will
00075     //    fail gracefully due to pLock->pManager == 0. Future commands can't be enqued
00076     //    after pManager is null.
00077     //  - Once ExitCommand executes, ThreadCommand::Run loop will exit and release the last
00078     //    reference to the thread object.
00079     pThread->PushExitCommand(false);
00080     pThread->DetachDeviceManager();
00081     pThread.Clear();
00082 
00083     DeviceManagerImpl::Shutdown();
00084 }
00085 
00086 ThreadCommandQueue* DeviceManager::GetThreadQueue()
00087 {
00088     return pThread;
00089 }
00090 
00091 bool DeviceManager::GetDeviceInfo(DeviceInfo* info) const
00092 {
00093     if ((info->InfoClassType != Device_Manager) &&
00094         (info->InfoClassType != Device_None))
00095         return false;
00096     
00097     info->Type    = Device_Manager;
00098     info->Version = 0;
00099     OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, "DeviceManager");
00100     OVR_strcpy(info->Manufacturer,DeviceInfo::MaxNameLength, "Oculus VR, Inc.");        
00101     return true;
00102 }
00103 
00104 DeviceEnumerator<> DeviceManager::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
00105 {
00106     // TBD: Can this be avoided in the future, once proper device notification is in place?
00107     if (GetThreadId() != OVR::GetCurrentThreadId())
00108     {
00109         pThread->PushCall((DeviceManagerImpl*)this,
00110             &DeviceManager::EnumerateAllFactoryDevices, true);
00111     }
00112     else
00113         DeviceManager::EnumerateAllFactoryDevices();
00114 
00115     return DeviceManagerImpl::EnumerateDevicesEx(args);
00116 }
00117 
00118 ThreadId DeviceManager::GetThreadId() const
00119 {
00120     return pThread->GetThreadId();
00121 }
00122     
00123 bool DeviceManager::GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const
00124 {
00125     if (GetHIDDeviceManager())
00126         return static_cast<HIDDeviceManager*>(GetHIDDeviceManager())->GetHIDDeviceDesc(path, pdevDesc);
00127     return false;
00128 }
00129 
00130 
00131 //-------------------------------------------------------------------------------------
00132 // ***** DeviceManager Thread 
00133 
00134 DeviceManagerThread::DeviceManagerThread(DeviceManager* pdevMgr)
00135     : Thread(ThreadStackSize), hCommandEvent(0), pDeviceMgr(pdevMgr)
00136 {    
00137     // Create a non-signaled manual-reset event.
00138     hCommandEvent = ::CreateEvent(0, TRUE, FALSE, 0);
00139     if (!hCommandEvent)
00140         return;
00141 
00142     // Must add event before starting.
00143     AddOverlappedEvent(0, hCommandEvent);
00144 
00145         // Create device messages object.
00146         pStatusObject = *new DeviceStatus(this);
00147 }
00148 
00149 DeviceManagerThread::~DeviceManagerThread()
00150 {
00151     // Remove overlapped event [0], after thread service exit.
00152     if (hCommandEvent)
00153     {
00154         RemoveOverlappedEvent(0, hCommandEvent);    
00155         ::CloseHandle(hCommandEvent);
00156         hCommandEvent = 0;
00157     }
00158 }
00159 
00160 int DeviceManagerThread::Run()
00161 {
00162     ThreadCommand::PopBuffer command;
00163 
00164     SetThreadName("OVR::DeviceManagerThread");
00165     LogText("OVR::DeviceManagerThread - running (ThreadId=0x%X).\n", GetThreadId());
00166   
00167         if (!pStatusObject->Initialize())
00168         {
00169                 LogText("OVR::DeviceManagerThread - failed to initialize MessageObject.\n");
00170         }
00171 
00172     while(!IsExiting())
00173     {
00174         // PopCommand will reset event on empty queue.
00175         if (PopCommand(&command))
00176         {
00177             command.Execute();
00178         }
00179         else
00180         {
00181             DWORD eventIndex = 0;
00182             do {
00183                 UPInt numberOfWaitHandles = WaitHandles.GetSize();
00184                                 Debug_WaitedObjectCount = (DWORD)numberOfWaitHandles;
00185 
00186                 DWORD waitMs = INFINITE;
00187 
00188                 // If devices have time-dependent logic registered, get the longest wait
00189                 // allowed based on current ticks.
00190                 if (!TicksNotifiers.IsEmpty())
00191                 {
00192                     UInt64 ticksMks = Timer::GetTicks();
00193                     DWORD  waitAllowed;
00194                     
00195                     for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++)
00196                     {
00197                         waitAllowed = (DWORD)(TicksNotifiers[j]->OnTicks(ticksMks) / Timer::MksPerMs);
00198                         if (waitAllowed < waitMs)
00199                             waitMs = waitAllowed;
00200                     }
00201                 }
00202           
00203                                 // Wait for event signals or window messages.
00204                 eventIndex = MsgWaitForMultipleObjects((DWORD)numberOfWaitHandles, &WaitHandles[0], FALSE, waitMs, QS_ALLINPUT);
00205                                 
00206                 if (eventIndex != WAIT_FAILED)
00207                 {
00208                     if (eventIndex == WAIT_TIMEOUT)
00209                         continue;
00210 
00211                     // TBD: Does this ever apply?
00212                     OVR_ASSERT(eventIndex < WAIT_ABANDONED_0);
00213 
00214                     if (eventIndex == WAIT_OBJECT_0)
00215                     {
00216                         // Handle [0] services commands.
00217                         break;
00218                     }
00219                                         else if (eventIndex == WAIT_OBJECT_0 + numberOfWaitHandles)
00220                                         {
00221                                                 // Handle Windows messages.
00222                                                 pStatusObject->ProcessMessages();
00223                                         }
00224                     else 
00225                     {
00226                         // Notify waiting device that its event is signaled.
00227                         unsigned i = eventIndex - WAIT_OBJECT_0; 
00228                         OVR_ASSERT(i < numberOfWaitHandles);
00229                         if (WaitNotifiers[i])                        
00230                             WaitNotifiers[i]->OnOverlappedEvent(WaitHandles[i]);
00231                     }
00232                 }
00233 
00234             } while(eventIndex != WAIT_FAILED);
00235                     
00236         }
00237     }
00238 
00239         pStatusObject->ShutDown();
00240 
00241     LogText("OVR::DeviceManagerThread - exiting (ThreadId=0x%X).\n", GetThreadId());
00242     return 0;
00243 }
00244 
00245 bool DeviceManagerThread::AddOverlappedEvent(Notifier* notify, HANDLE hevent)
00246 {
00247     WaitNotifiers.PushBack(notify);
00248     WaitHandles.PushBack(hevent);
00249 
00250     OVR_ASSERT(WaitNotifiers.GetSize() <= MAXIMUM_WAIT_OBJECTS);
00251     return true;
00252 }
00253 
00254 bool DeviceManagerThread::RemoveOverlappedEvent(Notifier* notify, HANDLE hevent)
00255 {
00256     // [0] is reserved for thread commands with notify of null, but we still
00257     // can use this function to remove it.
00258     for (UPInt i = 0; i < WaitNotifiers.GetSize(); i++)
00259     {
00260         if ((WaitNotifiers[i] == notify) && (WaitHandles[i] == hevent))
00261         {
00262             WaitNotifiers.RemoveAt(i);
00263             WaitHandles.RemoveAt(i);
00264             return true;
00265         }
00266     }
00267     return false;
00268 }
00269 
00270 bool DeviceManagerThread::AddTicksNotifier(Notifier* notify)
00271 {
00272      TicksNotifiers.PushBack(notify);
00273      return true;
00274 }
00275 
00276 bool DeviceManagerThread::RemoveTicksNotifier(Notifier* notify)
00277 {
00278     for (UPInt i = 0; i < TicksNotifiers.GetSize(); i++)
00279     {
00280         if (TicksNotifiers[i] == notify)
00281         {
00282             TicksNotifiers.RemoveAt(i);
00283             return true;
00284         }
00285     }
00286     return false;
00287 }
00288 
00289 bool DeviceManagerThread::AddMessageNotifier(Notifier* notify)
00290 {
00291         MessageNotifiers.PushBack(notify);
00292         return true;
00293 }
00294 
00295 bool DeviceManagerThread::RemoveMessageNotifier(Notifier* notify)
00296 {
00297         for (UPInt i = 0; i < MessageNotifiers.GetSize(); i++)
00298         {
00299                 if (MessageNotifiers[i] == notify)
00300                 {
00301                         MessageNotifiers.RemoveAt(i);
00302                         return true;
00303                 }
00304         }
00305         return false;
00306 }
00307 
00308 bool DeviceManagerThread::OnMessage(MessageType type, const String& devicePath)
00309 {
00310         Notifier::DeviceMessageType notifierMessageType = Notifier::DeviceMessage_DeviceAdded;
00311         if (type == DeviceAdded)
00312         {
00313         }
00314         else if (type == DeviceRemoved)
00315         {
00316                 notifierMessageType = Notifier::DeviceMessage_DeviceRemoved;
00317         }
00318         else
00319         {
00320                 OVR_ASSERT(false);
00321         }
00322 
00323         bool error = false;
00324     bool deviceFound = false;
00325         for (UPInt i = 0; i < MessageNotifiers.GetSize(); i++)
00326     {
00327                 if (MessageNotifiers[i] && 
00328                         MessageNotifiers[i]->OnDeviceMessage(notifierMessageType, devicePath, &error))
00329                 {
00330                         // The notifier belonged to a device with the specified device name so we're done.
00331             deviceFound = true;
00332                         break;
00333                 }
00334     }
00335     if (type == DeviceAdded && !deviceFound)
00336     {
00337         Lock::Locker devMgrLock(&DevMgrLock);
00338         // a new device was connected. Go through all device factories and
00339         // try to detect the device using HIDDeviceDesc.
00340         HIDDeviceDesc devDesc;
00341         if (pDeviceMgr->GetHIDDeviceDesc(devicePath, &devDesc))
00342         {
00343             Lock::Locker deviceLock(pDeviceMgr->GetLock());
00344             DeviceFactory* factory = pDeviceMgr->Factories.GetFirst();
00345             while(!pDeviceMgr->Factories.IsNull(factory))
00346             {
00347                 if (factory->DetectHIDDevice(pDeviceMgr, devDesc))
00348                 {
00349                     deviceFound = true;
00350                     break;
00351                 }
00352                 factory = factory->pNext;
00353             }
00354         }
00355     }
00356 
00357     if (!deviceFound && strstr(devicePath.ToCStr(), "#OVR00"))
00358     {
00359         Ptr<DeviceManager> pmgr;
00360         {
00361             Lock::Locker devMgrLock(&DevMgrLock);
00362             pmgr = pDeviceMgr;
00363         }
00364         // HMD plugged/unplugged
00365         // This is not a final solution to enumerate HMD devices and get
00366         // a first available handle. This won't work with multiple rifts.
00367         // @TODO (!AB)
00368         pmgr->EnumerateDevices<HMDDevice>();
00369     }
00370 
00371         return !error;
00372 }
00373 
00374 void DeviceManagerThread::DetachDeviceManager()
00375 {
00376     Lock::Locker devMgrLock(&DevMgrLock);
00377     pDeviceMgr = NULL;
00378 }
00379 
00380 } // namespace Win32
00381 
00382 
00383 //-------------------------------------------------------------------------------------
00384 // ***** Creation
00385 
00386 
00387 // Creates a new DeviceManager and initializes OVR.
00388 DeviceManager* DeviceManager::Create()
00389 {
00390 
00391     if (!System::IsInitialized())
00392     {
00393         // Use custom message, since Log is not yet installed.
00394         OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
00395             LogMessage(Log_Debug, "DeviceManager::Create failed - OVR::System not initialized"); );
00396         return 0;
00397     }
00398 
00399     Ptr<Win32::DeviceManager> manager = *new Win32::DeviceManager;
00400 
00401     if (manager)
00402     {
00403         if (manager->Initialize(0))
00404         {            
00405             manager->AddFactory(&SensorDeviceFactory::Instance);
00406             manager->AddFactory(&LatencyTestDeviceFactory::Instance);
00407             manager->AddFactory(&Win32::HMDDeviceFactory::Instance);
00408 
00409             manager->AddRef();
00410         }
00411         else
00412         {
00413             manager.Clear();
00414         }
00415 
00416     }    
00417 
00418     return manager.GetPtr();
00419 }
00420 
00421 
00422 } // namespace OVR
00423 


oculus_sdk
Author(s):
autogenerated on Fri Aug 28 2015 11:53:11