OVR_DeviceImpl.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   OVR_DeviceImpl.h
00004 Content     :   Partial back-end independent implementation of Device interfaces
00005 Created     :   October 10, 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_DeviceImpl.h"
00017 #include "Kernel/OVR_Atomic.h"
00018 #include "Kernel/OVR_Log.h"
00019 #include "Kernel/OVR_System.h"
00020 
00021 #include "OVR_DeviceImpl.h"
00022 #include "OVR_SensorImpl.h"
00023 #include "OVR_Profile.h"
00024 
00025 namespace OVR {
00026 
00027 
00028 //-------------------------------------------------------------------------------------
00029 // ***** SharedLock
00030 
00031 // This is a general purpose globally shared Lock implementation that should probably be
00032 // moved to Kernel.
00033 // May in theory busy spin-wait if we hit contention on first lock creation,
00034 // but this shouldn't matter in practice since Lock* should be cached.
00035 
00036 
00037 enum { LockInitMarker = 0xFFFFFFFF };
00038 
00039 Lock* SharedLock::GetLockAddRef()
00040 {
00041     int oldUseCount;
00042 
00043     do {
00044         oldUseCount = UseCount;
00045         if (oldUseCount == LockInitMarker)
00046             continue;
00047 
00048         if (oldUseCount == 0)
00049         {
00050             // Initialize marker
00051             if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 0, LockInitMarker))
00052             {
00053                 Construct<Lock>(Buffer);
00054                 do { }
00055                 while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 1));
00056                 return toLock();
00057             }
00058             continue;
00059         }
00060 
00061     } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount + 1));
00062 
00063     return toLock();
00064 }
00065 
00066 void SharedLock::ReleaseLock(Lock* plock)
00067 {
00068     OVR_UNUSED(plock);
00069     OVR_ASSERT(plock == toLock());
00070 
00071     int oldUseCount;
00072 
00073     do {
00074         oldUseCount = UseCount;
00075         OVR_ASSERT(oldUseCount != LockInitMarker);
00076 
00077         if (oldUseCount == 1)
00078         {
00079             // Initialize marker
00080             if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 1, LockInitMarker))
00081             {
00082                 Destruct<Lock>(toLock());
00083 
00084                 do { }
00085                 while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 0));
00086 
00087                 return;
00088             }
00089             continue;
00090         }
00091 
00092     } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount - 1));
00093 }
00094 
00095 
00096 
00097 //-------------------------------------------------------------------------------------
00098 // ***** MessageHandler
00099 
00100 // Threading notes:
00101 // The OnMessage() handler and SetMessageHandler are currently synchronized
00102 // through a separately stored shared Lock object to avoid calling the handler 
00103 // from background thread while it's being removed.
00104 
00105 static SharedLock MessageHandlerSharedLock;
00106 
00107 
00108 class MessageHandlerImpl
00109 {
00110 public:
00111     MessageHandlerImpl()
00112         : pLock(MessageHandlerSharedLock.GetLockAddRef())
00113     {
00114     }
00115     ~MessageHandlerImpl()
00116     {
00117         MessageHandlerSharedLock.ReleaseLock(pLock);
00118         pLock = 0;
00119     }
00120 
00121     static MessageHandlerImpl* FromHandler(MessageHandler* handler)
00122     { return (MessageHandlerImpl*)&handler->Internal; }
00123     static const MessageHandlerImpl* FromHandler(const MessageHandler* handler)
00124     { return (const MessageHandlerImpl*)&handler->Internal; }
00125 
00126     // This lock is held while calling a handler and when we are applied/
00127     // removed from a device.
00128     Lock*                     pLock;
00129     // List of device we are applied to.
00130     List<MessageHandlerRef>   UseList;
00131 };
00132 
00133 
00134 MessageHandlerRef::MessageHandlerRef(DeviceBase* device)
00135     : pLock(MessageHandlerSharedLock.GetLockAddRef()), pDevice(device), pHandler(0)
00136 {
00137 }
00138 
00139 MessageHandlerRef::~MessageHandlerRef()
00140 {
00141     {
00142         Lock::Locker lockScope(pLock);
00143         if (pHandler)
00144         {
00145             pHandler = 0;
00146             RemoveNode();
00147         }
00148     }
00149     MessageHandlerSharedLock.ReleaseLock(pLock);
00150     pLock = 0;
00151 }
00152 
00153 void MessageHandlerRef::SetHandler(MessageHandler* handler)
00154 {    
00155     OVR_ASSERT(!handler ||
00156                MessageHandlerImpl::FromHandler(handler)->pLock == pLock);    
00157     Lock::Locker lockScope(pLock);
00158     SetHandler_NTS(handler);
00159 }
00160 
00161 void MessageHandlerRef::SetHandler_NTS(MessageHandler* handler)
00162 {   
00163     if (pHandler != handler)
00164     {
00165         if (pHandler)
00166             RemoveNode();
00167         pHandler = handler;
00168 
00169         if (handler)
00170         {
00171             MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(handler);
00172             handlerImpl->UseList.PushBack(this);
00173         }
00174         // TBD: Call notifier on device?
00175     }
00176 }
00177 
00178 
00179 MessageHandler::MessageHandler()
00180 {    
00181     OVR_COMPILER_ASSERT(sizeof(Internal) > sizeof(MessageHandlerImpl));
00182     Construct<MessageHandlerImpl>(Internal);
00183 }
00184 
00185 MessageHandler::~MessageHandler()
00186 {
00187     MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
00188     {
00189         Lock::Locker lockedScope(handlerImpl->pLock);
00190         OVR_ASSERT_LOG(handlerImpl->UseList.IsEmpty(),
00191             ("~MessageHandler %p - Handler still active; call RemoveHandlerFromDevices", this));
00192     }
00193 
00194     Destruct<MessageHandlerImpl>(handlerImpl);    
00195 }
00196 
00197 bool MessageHandler::IsHandlerInstalled() const
00198 {
00199     const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);    
00200     Lock::Locker lockedScope(handlerImpl->pLock);
00201     return handlerImpl->UseList.IsEmpty() != true;
00202 }
00203 
00204 
00205 void MessageHandler::RemoveHandlerFromDevices()
00206 {
00207     MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
00208     Lock::Locker lockedScope(handlerImpl->pLock);
00209 
00210     while(!handlerImpl->UseList.IsEmpty())
00211     {
00212         MessageHandlerRef* use = handlerImpl->UseList.GetFirst();
00213         use->SetHandler_NTS(0);
00214     }
00215 }
00216 
00217 Lock* MessageHandler::GetHandlerLock() const
00218 {
00219     const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
00220     return handlerImpl->pLock;
00221 }
00222 
00223 
00224 //-------------------------------------------------------------------------------------
00225 // ***** DeviceBase
00226    
00227 
00228 // Delegate relevant implementation to DeviceRectord to avoid re-implementation in
00229 // every derived Device.
00230 void DeviceBase::AddRef()
00231 {
00232     getDeviceCommon()->DeviceAddRef();
00233 }
00234 void DeviceBase::Release()
00235 {
00236     getDeviceCommon()->DeviceRelease();
00237 }
00238 DeviceBase* DeviceBase::GetParent() const
00239 {
00240     return getDeviceCommon()->pParent.GetPtr();
00241 }
00242 DeviceManager* DeviceBase::GetManager() const
00243 {
00244     return getDeviceCommon()->pCreateDesc->GetManagerImpl();
00245 }
00246 
00247 void DeviceBase::SetMessageHandler(MessageHandler* handler)
00248 {
00249     getDeviceCommon()->HandlerRef.SetHandler(handler);
00250 }
00251 MessageHandler* DeviceBase::GetMessageHandler() const
00252 {
00253     return getDeviceCommon()->HandlerRef.GetHandler();
00254 }
00255 
00256 DeviceType DeviceBase::GetType() const
00257 {
00258     return getDeviceCommon()->pCreateDesc->Type;
00259 }
00260 
00261 bool DeviceBase::GetDeviceInfo(DeviceInfo* info) const
00262 {
00263     return getDeviceCommon()->pCreateDesc->GetDeviceInfo(info);
00264     //info->Name[0] = 0;
00265     //return false;
00266 }
00267 
00268 // returns the MessageHandler's lock
00269 Lock* DeviceBase::GetHandlerLock() const
00270 {
00271     return getDeviceCommon()->HandlerRef.GetLock();
00272 }
00273 
00274 // Derive DeviceManagerCreateDesc to provide abstract function implementation.
00275 class DeviceManagerCreateDesc : public DeviceCreateDesc
00276 {
00277 public:
00278     DeviceManagerCreateDesc(DeviceFactory* factory)
00279         : DeviceCreateDesc(factory, Device_Manager) { }
00280 
00281     // We don't need there on Manager since it isn't assigned to DeviceHandle.
00282     virtual DeviceCreateDesc* Clone() const                        { return 0; }
00283     virtual MatchResult MatchDevice(const DeviceCreateDesc&,
00284                                     DeviceCreateDesc**) const      { return Match_None; }
00285     virtual DeviceBase* NewDeviceInstance()                        { return 0; }
00286     virtual bool        GetDeviceInfo(DeviceInfo*) const           { return false; }
00287 };
00288 
00289 //-------------------------------------------------------------------------------------
00290 // ***** DeviceManagerImpl
00291 
00292 DeviceManagerImpl::DeviceManagerImpl()
00293     : DeviceImpl<OVR::DeviceManager>(CreateManagerDesc(), 0)
00294       //,DeviceCreateDescList(pCreateDesc ? pCreateDesc->pLock : 0)
00295 {
00296     if (pCreateDesc)
00297     {
00298         pCreateDesc->pLock->pManager = this;
00299     }
00300 }
00301 
00302 DeviceManagerImpl::~DeviceManagerImpl()
00303 {
00304     // Shutdown must've been called.
00305     OVR_ASSERT(!pCreateDesc->pDevice);
00306 
00307     // Remove all factories
00308     while(!Factories.IsEmpty())
00309     {
00310         DeviceFactory* factory = Factories.GetFirst();
00311         factory->RemovedFromManager();
00312         factory->RemoveNode();
00313     }
00314 }
00315 
00316 DeviceCreateDesc* DeviceManagerImpl::CreateManagerDesc()
00317 {
00318     DeviceCreateDesc* managerDesc = new DeviceManagerCreateDesc(0);
00319     if (managerDesc)
00320     {
00321         managerDesc->pLock = *new DeviceManagerLock;
00322     }
00323     return managerDesc;
00324 }
00325 
00326 bool DeviceManagerImpl::Initialize(DeviceBase* parent)
00327 {
00328     OVR_UNUSED(parent);
00329     if (!pCreateDesc || !pCreateDesc->pLock)
00330                 return false;
00331 
00332     pProfileManager = *ProfileManager::Create();
00333 
00334     return true;
00335 }
00336 
00337 void DeviceManagerImpl::Shutdown()
00338 {
00339     // Remove all device descriptors from list while the lock is held.
00340     // Some descriptors may survive longer due to handles.    
00341     while(!Devices.IsEmpty())
00342     {     
00343         DeviceCreateDesc* devDesc = Devices.GetFirst();
00344         OVR_ASSERT(!devDesc->pDevice); // Manager shouldn't be dying while Device exists.
00345         devDesc->Enumerated = false;
00346         devDesc->RemoveNode();
00347         devDesc->pNext = devDesc->pPrev = 0;
00348 
00349         if (devDesc->HandleCount == 0)
00350         {
00351             delete devDesc;
00352         }
00353     }
00354     Devices.Clear();
00355 
00356     // These must've been cleared by caller.
00357     OVR_ASSERT(pCreateDesc->pDevice == 0);
00358     OVR_ASSERT(pCreateDesc->pLock->pManager == 0);
00359 
00360     pProfileManager.Clear();
00361 }
00362 
00363 
00364 // Callbacks for DeviceCreation/Release    
00365 DeviceBase* DeviceManagerImpl::CreateDevice_MgrThread(DeviceCreateDesc* createDesc, DeviceBase* parent)
00366 {
00367     // Calls to DeviceManagerImpl::CreateDevice are enqueued with wait while holding pManager,
00368     // so 'this' must remain valid.
00369     OVR_ASSERT(createDesc->pLock->pManager);    
00370 
00371     Lock::Locker devicesLock(GetLock());
00372 
00373     // If device already exists, just AddRef to it.
00374     if (createDesc->pDevice)
00375     {
00376         createDesc->pDevice->AddRef();
00377         return createDesc->pDevice;
00378     }
00379 
00380     if (!parent)
00381         parent = this;
00382 
00383     DeviceBase* device = createDesc->NewDeviceInstance();
00384     
00385     if (device)
00386     {
00387         if (device->getDeviceCommon()->Initialize(parent))
00388         {
00389            createDesc->pDevice = device;
00390         }
00391         else
00392         {
00393             // Don't go through Release() to avoid PushCall behaviour,
00394             // as it is not needed here.
00395             delete device;
00396             device = 0;
00397         }
00398     }
00399      
00400     return device;
00401 }
00402 
00403 Void DeviceManagerImpl::ReleaseDevice_MgrThread(DeviceBase* device)
00404 {
00405     // descKeepAlive will keep ManagerLock object alive as well,
00406     // allowing us to exit gracefully.    
00407     Ptr<DeviceCreateDesc>  descKeepAlive;
00408     Lock::Locker           devicesLock(GetLock());
00409     DeviceCommon*          devCommon = device->getDeviceCommon();
00410 
00411     while(1)
00412     {
00413         UInt32 refCount = devCommon->RefCount;
00414 
00415         if (refCount > 1)
00416         {
00417             if (devCommon->RefCount.CompareAndSet_NoSync(refCount, refCount-1))
00418             {
00419                 // We decreented from initial count higher then 1;
00420                 // nothing else to do.
00421                 return 0;
00422             }        
00423         }
00424         else if (devCommon->RefCount.CompareAndSet_NoSync(1, 0))
00425         {
00426             // { 1 -> 0 } decrement succeded. Destroy this device.
00427             break;
00428         }
00429     }
00430 
00431     // At this point, may be releasing the device manager itself.
00432     // This does not matter, however, since shutdown logic is the same
00433     // in both cases. DeviceManager::Shutdown with begin shutdown process for
00434     // the internal manager thread, which will eventually destroy itself.
00435     // TBD: Clean thread shutdown.
00436     descKeepAlive = devCommon->pCreateDesc;
00437     descKeepAlive->pDevice = 0;
00438     devCommon->Shutdown();
00439     delete device;
00440     return 0;
00441 }
00442 
00443 
00444 
00445 Void DeviceManagerImpl::EnumerateAllFactoryDevices()
00446 {
00447     // 1. Mark matching devices as NOT enumerated.
00448     // 2. Call factory to enumerate all HW devices, adding any device that 
00449     //    was not matched.
00450     // 3. Remove non-matching devices.
00451 
00452     Lock::Locker deviceLock(GetLock());
00453 
00454     DeviceCreateDesc* devDesc, *nextdevDesc;
00455 
00456     // 1.
00457     for(devDesc = Devices.GetFirst();
00458         !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
00459     {
00460         //if (devDesc->pFactory == factory)
00461             devDesc->Enumerated = false;
00462     }
00463     
00464     // 2.
00465     DeviceFactory* factory = Factories.GetFirst();
00466     while(!Factories.IsNull(factory))
00467     {
00468         EnumerateFactoryDevices(factory);
00469         factory = factory->pNext;
00470     }
00471 
00472     
00473     // 3.
00474     for(devDesc = Devices.GetFirst();
00475         !Devices.IsNull(devDesc);  devDesc = nextdevDesc)
00476     {
00477         // In case 'devDesc' gets removed.
00478         nextdevDesc = devDesc->pNext; 
00479 
00480         // Note, device might be not enumerated since it is opened and
00481         // in use! Do NOT notify 'device removed' in this case (!AB)
00482         if (!devDesc->Enumerated)
00483         {
00484             // This deletes the devDesc for HandleCount == 0 due to Release in DeviceHandle.
00485             CallOnDeviceRemoved(devDesc);
00486 
00487             /*
00488             if (devDesc->HandleCount == 0)
00489             {                
00490                 // Device must be dead if it ever existed, since it AddRefs to us.
00491                 // ~DeviceCreateDesc removes its node from list.
00492                 OVR_ASSERT(!devDesc->pDevice);
00493                 delete devDesc;
00494             }
00495             */
00496         }
00497     }
00498 
00499     return 0;
00500 }
00501 
00502 Ptr<DeviceCreateDesc> DeviceManagerImpl::AddDevice_NeedsLock(
00503     const DeviceCreateDesc& createDesc)
00504 {
00505     // If found, mark as enumerated and we are done.
00506     DeviceCreateDesc* descCandidate = 0;
00507 
00508     for(DeviceCreateDesc* devDesc = Devices.GetFirst();
00509         !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
00510     {
00511         DeviceCreateDesc::MatchResult mr = devDesc->MatchDevice(createDesc, &descCandidate);
00512         if (mr == DeviceCreateDesc::Match_Found)
00513         {
00514             devDesc->Enumerated = true;
00515             if (!devDesc->pDevice)
00516                 CallOnDeviceAdded(devDesc);
00517             return devDesc;
00518         }
00519     }
00520 
00521     // Update candidate (this may involve writing fields to HMDDevice createDesc).
00522     if (descCandidate)
00523     {
00524         bool newDevice = false;
00525         if (descCandidate->UpdateMatchedCandidate(createDesc, &newDevice))
00526         {
00527             descCandidate->Enumerated = true;
00528             if (!descCandidate->pDevice || newDevice)
00529                 CallOnDeviceAdded(descCandidate);
00530             return descCandidate;
00531         }
00532     }
00533 
00534     // If not found, add new device.
00535     //  - This stores a new descriptor with
00536     //    {pDevice = 0, HandleCount = 1, Enumerated = true}
00537     DeviceCreateDesc* desc = createDesc.Clone();
00538     desc->pLock = pCreateDesc->pLock;
00539     Devices.PushBack(desc);
00540     desc->Enumerated = true;
00541 
00542     CallOnDeviceAdded(desc);
00543 
00544     return desc;
00545 }
00546 
00547 Ptr<DeviceCreateDesc> DeviceManagerImpl::FindDevice(
00548     const String& path, 
00549     DeviceType deviceType)
00550 {
00551     Lock::Locker deviceLock(GetLock());
00552     DeviceCreateDesc* devDesc;
00553 
00554     for (devDesc = Devices.GetFirst();
00555         !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
00556     {
00557         if ((deviceType == Device_None || deviceType == devDesc->Type) &&
00558             devDesc->MatchDevice(path))
00559             return devDesc;
00560     }
00561     return NULL;
00562 }
00563 
00564 Ptr<DeviceCreateDesc> DeviceManagerImpl::FindHIDDevice(const HIDDeviceDesc& hidDevDesc)
00565 {
00566     Lock::Locker deviceLock(GetLock());
00567     DeviceCreateDesc* devDesc;
00568     
00569     for (devDesc = Devices.GetFirst();
00570         !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
00571     {
00572         if (devDesc->MatchHIDDevice(hidDevDesc))
00573             return devDesc;
00574     }
00575     return NULL;
00576 }
00577   
00578 void DeviceManagerImpl::DetectHIDDevice(const HIDDeviceDesc& hidDevDesc)
00579 {
00580     Lock::Locker deviceLock(GetLock());
00581     DeviceFactory* factory = Factories.GetFirst();
00582     while(!Factories.IsNull(factory))
00583     {
00584         if (factory->DetectHIDDevice(this, hidDevDesc))
00585             break;
00586         factory = factory->pNext;
00587     }
00588     
00589 }
00590     
00591 // Enumerates devices for a particular factory.
00592 Void DeviceManagerImpl::EnumerateFactoryDevices(DeviceFactory* factory)
00593 {
00594        
00595     class FactoryEnumerateVisitor : public DeviceFactory::EnumerateVisitor
00596     {        
00597         DeviceManagerImpl* pManager;
00598         DeviceFactory*     pFactory;
00599     public:
00600         FactoryEnumerateVisitor(DeviceManagerImpl* manager, DeviceFactory* factory)
00601             : pManager(manager), pFactory(factory) { }
00602 
00603         virtual void Visit(const DeviceCreateDesc& createDesc)
00604         {
00605             pManager->AddDevice_NeedsLock(createDesc);
00606         }
00607     };
00608 
00609     FactoryEnumerateVisitor newDeviceVisitor(this, factory);
00610     factory->EnumerateDevices(newDeviceVisitor);
00611 
00612 
00613     return 0;
00614 }
00615 
00616 
00617 DeviceEnumerator<> DeviceManagerImpl::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
00618 {
00619     Lock::Locker deviceLock(GetLock());
00620     
00621     if (Devices.IsEmpty())
00622         return DeviceEnumerator<>();
00623 
00624     DeviceCreateDesc*  firstDeviceDesc = Devices.GetFirst();
00625     DeviceEnumerator<> e = enumeratorFromHandle(DeviceHandle(firstDeviceDesc), args);
00626 
00627     if (!args.MatchRule(firstDeviceDesc->Type, firstDeviceDesc->Enumerated))
00628     {
00629         e.Next();
00630     }
00631     
00632     return e;
00633 }
00634 
00635 //-------------------------------------------------------------------------------------
00636 // ***** DeviceCommon
00637 
00638 void DeviceCommon::DeviceAddRef()
00639 {
00640     RefCount++;
00641 }
00642 
00643 void DeviceCommon::DeviceRelease()
00644 {
00645     while(1)
00646     {
00647         UInt32 refCount = RefCount;
00648         OVR_ASSERT(refCount > 0);
00649         
00650         if (refCount == 1)
00651         {
00652             DeviceManagerImpl*  manager = pCreateDesc->GetManagerImpl();
00653             ThreadCommandQueue* queue   = manager->GetThreadQueue();
00654 
00655             // Enqueue ReleaseDevice for {1 -> 0} transition with no wait.
00656             // We pass our reference ownership into the queue to destroy.
00657             // It's in theory possible for another thread to re-steal our device reference,
00658             // but that is checked for atomically in DeviceManagerImpl::ReleaseDevice.
00659             if (!queue->PushCall(manager, &DeviceManagerImpl::ReleaseDevice_MgrThread,
00660                                           pCreateDesc->pDevice))
00661             {
00662                 // PushCall shouldn't fail because background thread runs while manager is
00663                 // alive and we are holding Manager alive through pParent chain.
00664                 OVR_ASSERT(false);
00665             }
00666 
00667             // Warning! At his point everything, including manager, may be dead.
00668             break;
00669         }
00670         else if (RefCount.CompareAndSet_NoSync(refCount, refCount-1))
00671         {
00672             break;
00673         }
00674     }
00675 }
00676 
00677 
00678 
00679 //-------------------------------------------------------------------------------------
00680 // ***** DeviceCreateDesc
00681 
00682 
00683 void DeviceCreateDesc::AddRef()
00684 {
00685     // Technically, HandleCount { 0 -> 1 } transition can only happen during Lock,
00686     // but we leave this to caller to worry about (happens during enumeration).
00687     HandleCount++;
00688 }
00689 
00690 void DeviceCreateDesc::Release()
00691 {
00692     while(1)
00693     {
00694         UInt32 handleCount = HandleCount;
00695         // HandleCount must obviously be >= 1, since we are releasing it.
00696         OVR_ASSERT(handleCount > 0);
00697 
00698         // {1 -> 0} transition may cause us to be destroyed, so require a lock.
00699         if (handleCount == 1)
00700         {       
00701             Ptr<DeviceManagerLock>  lockKeepAlive;
00702             Lock::Locker            deviceLockScope(GetLock());
00703 
00704             if (!HandleCount.CompareAndSet_NoSync(handleCount, 0))
00705                 continue;
00706             
00707             OVR_ASSERT(pDevice == 0);
00708 
00709             // Destroy *this if the manager was destroyed already, or Enumerated
00710             // is false (device no longer available).           
00711             if (!GetManagerImpl() || !Enumerated)
00712             {
00713                 lockKeepAlive = pLock;
00714 
00715                 // Remove from manager list (only matters for !Enumerated).
00716                 if (pNext)
00717                 {
00718                     RemoveNode();
00719                     pNext = pPrev = 0;
00720                 }
00721 
00722                 delete this;
00723             }
00724 
00725             // Available DeviceCreateDesc may survive with { HandleCount == 0 },
00726             // in case it might be enumerated again later.
00727             break;
00728         }
00729         else if (HandleCount.CompareAndSet_NoSync(handleCount, handleCount-1))
00730         {
00731             break;
00732         }
00733     }
00734 }
00735 
00736 HMDDevice* HMDDevice::Disconnect(SensorDevice* psensor)
00737 {
00738     if (!psensor)
00739         return NULL;
00740 
00741     OVR::DeviceManager* manager = GetManager();
00742     if (manager)
00743     {
00744         //DeviceManagerImpl* mgrImpl = static_cast<DeviceManagerImpl*>(manager);
00745         Ptr<DeviceCreateDesc> desc = getDeviceCommon()->pCreateDesc;
00746         if (desc)
00747         {
00748             class Visitor : public DeviceFactory::EnumerateVisitor
00749             {
00750                 Ptr<DeviceCreateDesc> Desc;
00751             public:
00752                 Visitor(DeviceCreateDesc* desc) : Desc(desc) {}
00753                 virtual void Visit(const DeviceCreateDesc& createDesc) 
00754                 {
00755                     Lock::Locker lock(Desc->GetLock());
00756                     Desc->UpdateMatchedCandidate(createDesc);
00757                 }
00758             } visitor(desc);
00759             //SensorDeviceImpl* sImpl = static_cast<SensorDeviceImpl*>(psensor);
00760 
00761             SensorDisplayInfoImpl displayInfo;
00762 
00763             if (psensor->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
00764             {
00765                 displayInfo.Unpack();
00766 
00767                 // If we got display info, try to match / create HMDDevice as well
00768                 // so that sensor settings give preference.
00769                 if (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt)
00770                 {
00771                     SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(displayInfo, visitor);
00772                 }
00773             }
00774         }
00775     }
00776     return this;
00777 }
00778 
00779 bool  HMDDevice::IsDisconnected() const
00780 {
00781     OVR::HMDInfo info;
00782     GetDeviceInfo(&info);
00783     // if strlen(info.DisplayDeviceName) == 0 then
00784     // this HMD is 'fake' (created using sensor).
00785     return (strlen(info.DisplayDeviceName) == 0);
00786 }
00787 
00788 
00789 } // namespace OVR
00790 


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