oculus1

annotate libovr/Src/OVR_DeviceImpl.cpp @ 17:cfe4979ab3eb

ops, minor error in the last commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 21 Sep 2013 07:09:48 +0300
parents
children
rev   line source
nuclear@1 1 /************************************************************************************
nuclear@1 2
nuclear@1 3 Filename : OVR_DeviceImpl.h
nuclear@1 4 Content : Partial back-end independent implementation of Device interfaces
nuclear@1 5 Created : October 10, 2012
nuclear@1 6 Authors : Michael Antonov
nuclear@1 7
nuclear@1 8 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
nuclear@1 9
nuclear@1 10 Use of this software is subject to the terms of the Oculus license
nuclear@1 11 agreement provided at the time of installation or download, or which
nuclear@1 12 otherwise accompanies this software in either electronic or hard copy form.
nuclear@1 13
nuclear@1 14 *************************************************************************************/
nuclear@1 15
nuclear@1 16 #include "OVR_DeviceImpl.h"
nuclear@1 17 #include "Kernel/OVR_Atomic.h"
nuclear@1 18 #include "Kernel/OVR_Log.h"
nuclear@1 19 #include "Kernel/OVR_System.h"
nuclear@1 20
nuclear@1 21 #include "OVR_DeviceImpl.h"
nuclear@1 22 #include "OVR_SensorImpl.h"
nuclear@1 23 #include "OVR_Profile.h"
nuclear@1 24
nuclear@1 25 namespace OVR {
nuclear@1 26
nuclear@1 27
nuclear@1 28 //-------------------------------------------------------------------------------------
nuclear@1 29 // ***** SharedLock
nuclear@1 30
nuclear@1 31 // This is a general purpose globally shared Lock implementation that should probably be
nuclear@1 32 // moved to Kernel.
nuclear@1 33 // May in theory busy spin-wait if we hit contention on first lock creation,
nuclear@1 34 // but this shouldn't matter in practice since Lock* should be cached.
nuclear@1 35
nuclear@1 36
nuclear@1 37 enum { LockInitMarker = 0xFFFFFFFF };
nuclear@1 38
nuclear@1 39 Lock* SharedLock::GetLockAddRef()
nuclear@1 40 {
nuclear@1 41 int oldUseCount;
nuclear@1 42
nuclear@1 43 do {
nuclear@1 44 oldUseCount = UseCount;
nuclear@1 45 if (oldUseCount == LockInitMarker)
nuclear@1 46 continue;
nuclear@1 47
nuclear@1 48 if (oldUseCount == 0)
nuclear@1 49 {
nuclear@1 50 // Initialize marker
nuclear@1 51 if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 0, LockInitMarker))
nuclear@1 52 {
nuclear@1 53 Construct<Lock>(Buffer);
nuclear@1 54 do { }
nuclear@1 55 while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 1));
nuclear@1 56 return toLock();
nuclear@1 57 }
nuclear@1 58 continue;
nuclear@1 59 }
nuclear@1 60
nuclear@1 61 } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount + 1));
nuclear@1 62
nuclear@1 63 return toLock();
nuclear@1 64 }
nuclear@1 65
nuclear@1 66 void SharedLock::ReleaseLock(Lock* plock)
nuclear@1 67 {
nuclear@1 68 OVR_UNUSED(plock);
nuclear@1 69 OVR_ASSERT(plock == toLock());
nuclear@1 70
nuclear@1 71 int oldUseCount;
nuclear@1 72
nuclear@1 73 do {
nuclear@1 74 oldUseCount = UseCount;
nuclear@1 75 OVR_ASSERT(oldUseCount != LockInitMarker);
nuclear@1 76
nuclear@1 77 if (oldUseCount == 1)
nuclear@1 78 {
nuclear@1 79 // Initialize marker
nuclear@1 80 if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 1, LockInitMarker))
nuclear@1 81 {
nuclear@1 82 Destruct<Lock>(toLock());
nuclear@1 83
nuclear@1 84 do { }
nuclear@1 85 while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 0));
nuclear@1 86
nuclear@1 87 return;
nuclear@1 88 }
nuclear@1 89 continue;
nuclear@1 90 }
nuclear@1 91
nuclear@1 92 } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount - 1));
nuclear@1 93 }
nuclear@1 94
nuclear@1 95
nuclear@1 96
nuclear@1 97 //-------------------------------------------------------------------------------------
nuclear@1 98 // ***** MessageHandler
nuclear@1 99
nuclear@1 100 // Threading notes:
nuclear@1 101 // The OnMessage() handler and SetMessageHandler are currently synchronized
nuclear@1 102 // through a separately stored shared Lock object to avoid calling the handler
nuclear@1 103 // from background thread while it's being removed.
nuclear@1 104
nuclear@1 105 static SharedLock MessageHandlerSharedLock;
nuclear@1 106
nuclear@1 107
nuclear@1 108 class MessageHandlerImpl
nuclear@1 109 {
nuclear@1 110 public:
nuclear@1 111 MessageHandlerImpl()
nuclear@1 112 : pLock(MessageHandlerSharedLock.GetLockAddRef())
nuclear@1 113 {
nuclear@1 114 }
nuclear@1 115 ~MessageHandlerImpl()
nuclear@1 116 {
nuclear@1 117 MessageHandlerSharedLock.ReleaseLock(pLock);
nuclear@1 118 pLock = 0;
nuclear@1 119 }
nuclear@1 120
nuclear@1 121 static MessageHandlerImpl* FromHandler(MessageHandler* handler)
nuclear@1 122 { return (MessageHandlerImpl*)&handler->Internal; }
nuclear@1 123 static const MessageHandlerImpl* FromHandler(const MessageHandler* handler)
nuclear@1 124 { return (const MessageHandlerImpl*)&handler->Internal; }
nuclear@1 125
nuclear@1 126 // This lock is held while calling a handler and when we are applied/
nuclear@1 127 // removed from a device.
nuclear@1 128 Lock* pLock;
nuclear@1 129 // List of device we are applied to.
nuclear@1 130 List<MessageHandlerRef> UseList;
nuclear@1 131 };
nuclear@1 132
nuclear@1 133
nuclear@1 134 MessageHandlerRef::MessageHandlerRef(DeviceBase* device)
nuclear@1 135 : pLock(MessageHandlerSharedLock.GetLockAddRef()), pDevice(device), pHandler(0)
nuclear@1 136 {
nuclear@1 137 }
nuclear@1 138
nuclear@1 139 MessageHandlerRef::~MessageHandlerRef()
nuclear@1 140 {
nuclear@1 141 {
nuclear@1 142 Lock::Locker lockScope(pLock);
nuclear@1 143 if (pHandler)
nuclear@1 144 {
nuclear@1 145 pHandler = 0;
nuclear@1 146 RemoveNode();
nuclear@1 147 }
nuclear@1 148 }
nuclear@1 149 MessageHandlerSharedLock.ReleaseLock(pLock);
nuclear@1 150 pLock = 0;
nuclear@1 151 }
nuclear@1 152
nuclear@1 153 void MessageHandlerRef::SetHandler(MessageHandler* handler)
nuclear@1 154 {
nuclear@1 155 OVR_ASSERT(!handler ||
nuclear@1 156 MessageHandlerImpl::FromHandler(handler)->pLock == pLock);
nuclear@1 157 Lock::Locker lockScope(pLock);
nuclear@1 158 SetHandler_NTS(handler);
nuclear@1 159 }
nuclear@1 160
nuclear@1 161 void MessageHandlerRef::SetHandler_NTS(MessageHandler* handler)
nuclear@1 162 {
nuclear@1 163 if (pHandler != handler)
nuclear@1 164 {
nuclear@1 165 if (pHandler)
nuclear@1 166 RemoveNode();
nuclear@1 167 pHandler = handler;
nuclear@1 168
nuclear@1 169 if (handler)
nuclear@1 170 {
nuclear@1 171 MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(handler);
nuclear@1 172 handlerImpl->UseList.PushBack(this);
nuclear@1 173 }
nuclear@1 174 // TBD: Call notifier on device?
nuclear@1 175 }
nuclear@1 176 }
nuclear@1 177
nuclear@1 178
nuclear@1 179 MessageHandler::MessageHandler()
nuclear@1 180 {
nuclear@1 181 OVR_COMPILER_ASSERT(sizeof(Internal) > sizeof(MessageHandlerImpl));
nuclear@1 182 Construct<MessageHandlerImpl>(Internal);
nuclear@1 183 }
nuclear@1 184
nuclear@1 185 MessageHandler::~MessageHandler()
nuclear@1 186 {
nuclear@1 187 MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
nuclear@1 188 {
nuclear@1 189 Lock::Locker lockedScope(handlerImpl->pLock);
nuclear@1 190 OVR_ASSERT_LOG(handlerImpl->UseList.IsEmpty(),
nuclear@1 191 ("~MessageHandler %p - Handler still active; call RemoveHandlerFromDevices", this));
nuclear@1 192 }
nuclear@1 193
nuclear@1 194 Destruct<MessageHandlerImpl>(handlerImpl);
nuclear@1 195 }
nuclear@1 196
nuclear@1 197 bool MessageHandler::IsHandlerInstalled() const
nuclear@1 198 {
nuclear@1 199 const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
nuclear@1 200 Lock::Locker lockedScope(handlerImpl->pLock);
nuclear@1 201 return handlerImpl->UseList.IsEmpty() != true;
nuclear@1 202 }
nuclear@1 203
nuclear@1 204
nuclear@1 205 void MessageHandler::RemoveHandlerFromDevices()
nuclear@1 206 {
nuclear@1 207 MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
nuclear@1 208 Lock::Locker lockedScope(handlerImpl->pLock);
nuclear@1 209
nuclear@1 210 while(!handlerImpl->UseList.IsEmpty())
nuclear@1 211 {
nuclear@1 212 MessageHandlerRef* use = handlerImpl->UseList.GetFirst();
nuclear@1 213 use->SetHandler_NTS(0);
nuclear@1 214 }
nuclear@1 215 }
nuclear@1 216
nuclear@1 217 Lock* MessageHandler::GetHandlerLock() const
nuclear@1 218 {
nuclear@1 219 const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
nuclear@1 220 return handlerImpl->pLock;
nuclear@1 221 }
nuclear@1 222
nuclear@1 223
nuclear@1 224 //-------------------------------------------------------------------------------------
nuclear@1 225 // ***** DeviceBase
nuclear@1 226
nuclear@1 227
nuclear@1 228 // Delegate relevant implementation to DeviceRectord to avoid re-implementation in
nuclear@1 229 // every derived Device.
nuclear@1 230 void DeviceBase::AddRef()
nuclear@1 231 {
nuclear@1 232 getDeviceCommon()->DeviceAddRef();
nuclear@1 233 }
nuclear@1 234 void DeviceBase::Release()
nuclear@1 235 {
nuclear@1 236 getDeviceCommon()->DeviceRelease();
nuclear@1 237 }
nuclear@1 238 DeviceBase* DeviceBase::GetParent() const
nuclear@1 239 {
nuclear@1 240 return getDeviceCommon()->pParent.GetPtr();
nuclear@1 241 }
nuclear@1 242 DeviceManager* DeviceBase::GetManager() const
nuclear@1 243 {
nuclear@1 244 return getDeviceCommon()->pCreateDesc->GetManagerImpl();
nuclear@1 245 }
nuclear@1 246
nuclear@1 247 void DeviceBase::SetMessageHandler(MessageHandler* handler)
nuclear@1 248 {
nuclear@1 249 getDeviceCommon()->HandlerRef.SetHandler(handler);
nuclear@1 250 }
nuclear@1 251 MessageHandler* DeviceBase::GetMessageHandler() const
nuclear@1 252 {
nuclear@1 253 return getDeviceCommon()->HandlerRef.GetHandler();
nuclear@1 254 }
nuclear@1 255
nuclear@1 256 DeviceType DeviceBase::GetType() const
nuclear@1 257 {
nuclear@1 258 return getDeviceCommon()->pCreateDesc->Type;
nuclear@1 259 }
nuclear@1 260
nuclear@1 261 bool DeviceBase::GetDeviceInfo(DeviceInfo* info) const
nuclear@1 262 {
nuclear@1 263 return getDeviceCommon()->pCreateDesc->GetDeviceInfo(info);
nuclear@1 264 //info->Name[0] = 0;
nuclear@1 265 //return false;
nuclear@1 266 }
nuclear@1 267
nuclear@1 268 // returns the MessageHandler's lock
nuclear@1 269 Lock* DeviceBase::GetHandlerLock() const
nuclear@1 270 {
nuclear@1 271 return getDeviceCommon()->HandlerRef.GetLock();
nuclear@1 272 }
nuclear@1 273
nuclear@1 274 // Derive DeviceManagerCreateDesc to provide abstract function implementation.
nuclear@1 275 class DeviceManagerCreateDesc : public DeviceCreateDesc
nuclear@1 276 {
nuclear@1 277 public:
nuclear@1 278 DeviceManagerCreateDesc(DeviceFactory* factory)
nuclear@1 279 : DeviceCreateDesc(factory, Device_Manager) { }
nuclear@1 280
nuclear@1 281 // We don't need there on Manager since it isn't assigned to DeviceHandle.
nuclear@1 282 virtual DeviceCreateDesc* Clone() const { return 0; }
nuclear@1 283 virtual MatchResult MatchDevice(const DeviceCreateDesc&,
nuclear@1 284 DeviceCreateDesc**) const { return Match_None; }
nuclear@1 285 virtual DeviceBase* NewDeviceInstance() { return 0; }
nuclear@1 286 virtual bool GetDeviceInfo(DeviceInfo*) const { return false; }
nuclear@1 287 };
nuclear@1 288
nuclear@1 289 //-------------------------------------------------------------------------------------
nuclear@1 290 // ***** DeviceManagerImpl
nuclear@1 291
nuclear@1 292 DeviceManagerImpl::DeviceManagerImpl()
nuclear@1 293 : DeviceImpl<OVR::DeviceManager>(CreateManagerDesc(), 0)
nuclear@1 294 //,DeviceCreateDescList(pCreateDesc ? pCreateDesc->pLock : 0)
nuclear@1 295 {
nuclear@1 296 if (pCreateDesc)
nuclear@1 297 {
nuclear@1 298 pCreateDesc->pLock->pManager = this;
nuclear@1 299 }
nuclear@1 300 }
nuclear@1 301
nuclear@1 302 DeviceManagerImpl::~DeviceManagerImpl()
nuclear@1 303 {
nuclear@1 304 // Shutdown must've been called.
nuclear@1 305 OVR_ASSERT(!pCreateDesc->pDevice);
nuclear@1 306
nuclear@1 307 // Remove all factories
nuclear@1 308 while(!Factories.IsEmpty())
nuclear@1 309 {
nuclear@1 310 DeviceFactory* factory = Factories.GetFirst();
nuclear@1 311 factory->RemovedFromManager();
nuclear@1 312 factory->RemoveNode();
nuclear@1 313 }
nuclear@1 314 }
nuclear@1 315
nuclear@1 316 DeviceCreateDesc* DeviceManagerImpl::CreateManagerDesc()
nuclear@1 317 {
nuclear@1 318 DeviceCreateDesc* managerDesc = new DeviceManagerCreateDesc(0);
nuclear@1 319 if (managerDesc)
nuclear@1 320 {
nuclear@1 321 managerDesc->pLock = *new DeviceManagerLock;
nuclear@1 322 }
nuclear@1 323 return managerDesc;
nuclear@1 324 }
nuclear@1 325
nuclear@1 326 bool DeviceManagerImpl::Initialize(DeviceBase* parent)
nuclear@1 327 {
nuclear@1 328 OVR_UNUSED(parent);
nuclear@1 329 if (!pCreateDesc || !pCreateDesc->pLock)
nuclear@1 330 return false;
nuclear@1 331
nuclear@1 332 pProfileManager = *ProfileManager::Create();
nuclear@1 333
nuclear@1 334 return true;
nuclear@1 335 }
nuclear@1 336
nuclear@1 337 void DeviceManagerImpl::Shutdown()
nuclear@1 338 {
nuclear@1 339 // Remove all device descriptors from list while the lock is held.
nuclear@1 340 // Some descriptors may survive longer due to handles.
nuclear@1 341 while(!Devices.IsEmpty())
nuclear@1 342 {
nuclear@1 343 DeviceCreateDesc* devDesc = Devices.GetFirst();
nuclear@1 344 OVR_ASSERT(!devDesc->pDevice); // Manager shouldn't be dying while Device exists.
nuclear@1 345 devDesc->Enumerated = false;
nuclear@1 346 devDesc->RemoveNode();
nuclear@1 347 devDesc->pNext = devDesc->pPrev = 0;
nuclear@1 348
nuclear@1 349 if (devDesc->HandleCount == 0)
nuclear@1 350 {
nuclear@1 351 delete devDesc;
nuclear@1 352 }
nuclear@1 353 }
nuclear@1 354 Devices.Clear();
nuclear@1 355
nuclear@1 356 // These must've been cleared by caller.
nuclear@1 357 OVR_ASSERT(pCreateDesc->pDevice == 0);
nuclear@1 358 OVR_ASSERT(pCreateDesc->pLock->pManager == 0);
nuclear@1 359
nuclear@1 360 pProfileManager.Clear();
nuclear@1 361 }
nuclear@1 362
nuclear@1 363
nuclear@1 364 // Callbacks for DeviceCreation/Release
nuclear@1 365 DeviceBase* DeviceManagerImpl::CreateDevice_MgrThread(DeviceCreateDesc* createDesc, DeviceBase* parent)
nuclear@1 366 {
nuclear@1 367 // Calls to DeviceManagerImpl::CreateDevice are enqueued with wait while holding pManager,
nuclear@1 368 // so 'this' must remain valid.
nuclear@1 369 OVR_ASSERT(createDesc->pLock->pManager);
nuclear@1 370
nuclear@1 371 Lock::Locker devicesLock(GetLock());
nuclear@1 372
nuclear@1 373 // If device already exists, just AddRef to it.
nuclear@1 374 if (createDesc->pDevice)
nuclear@1 375 {
nuclear@1 376 createDesc->pDevice->AddRef();
nuclear@1 377 return createDesc->pDevice;
nuclear@1 378 }
nuclear@1 379
nuclear@1 380 if (!parent)
nuclear@1 381 parent = this;
nuclear@1 382
nuclear@1 383 DeviceBase* device = createDesc->NewDeviceInstance();
nuclear@1 384
nuclear@1 385 if (device)
nuclear@1 386 {
nuclear@1 387 if (device->getDeviceCommon()->Initialize(parent))
nuclear@1 388 {
nuclear@1 389 createDesc->pDevice = device;
nuclear@1 390 }
nuclear@1 391 else
nuclear@1 392 {
nuclear@1 393 // Don't go through Release() to avoid PushCall behaviour,
nuclear@1 394 // as it is not needed here.
nuclear@1 395 delete device;
nuclear@1 396 device = 0;
nuclear@1 397 }
nuclear@1 398 }
nuclear@1 399
nuclear@1 400 return device;
nuclear@1 401 }
nuclear@1 402
nuclear@1 403 Void DeviceManagerImpl::ReleaseDevice_MgrThread(DeviceBase* device)
nuclear@1 404 {
nuclear@1 405 // descKeepAlive will keep ManagerLock object alive as well,
nuclear@1 406 // allowing us to exit gracefully.
nuclear@1 407 Ptr<DeviceCreateDesc> descKeepAlive;
nuclear@1 408 Lock::Locker devicesLock(GetLock());
nuclear@1 409 DeviceCommon* devCommon = device->getDeviceCommon();
nuclear@1 410
nuclear@1 411 while(1)
nuclear@1 412 {
nuclear@1 413 UInt32 refCount = devCommon->RefCount;
nuclear@1 414
nuclear@1 415 if (refCount > 1)
nuclear@1 416 {
nuclear@1 417 if (devCommon->RefCount.CompareAndSet_NoSync(refCount, refCount-1))
nuclear@1 418 {
nuclear@1 419 // We decreented from initial count higher then 1;
nuclear@1 420 // nothing else to do.
nuclear@1 421 return 0;
nuclear@1 422 }
nuclear@1 423 }
nuclear@1 424 else if (devCommon->RefCount.CompareAndSet_NoSync(1, 0))
nuclear@1 425 {
nuclear@1 426 // { 1 -> 0 } decrement succeded. Destroy this device.
nuclear@1 427 break;
nuclear@1 428 }
nuclear@1 429 }
nuclear@1 430
nuclear@1 431 // At this point, may be releasing the device manager itself.
nuclear@1 432 // This does not matter, however, since shutdown logic is the same
nuclear@1 433 // in both cases. DeviceManager::Shutdown with begin shutdown process for
nuclear@1 434 // the internal manager thread, which will eventually destroy itself.
nuclear@1 435 // TBD: Clean thread shutdown.
nuclear@1 436 descKeepAlive = devCommon->pCreateDesc;
nuclear@1 437 descKeepAlive->pDevice = 0;
nuclear@1 438 devCommon->Shutdown();
nuclear@1 439 delete device;
nuclear@1 440 return 0;
nuclear@1 441 }
nuclear@1 442
nuclear@1 443
nuclear@1 444
nuclear@1 445 Void DeviceManagerImpl::EnumerateAllFactoryDevices()
nuclear@1 446 {
nuclear@1 447 // 1. Mark matching devices as NOT enumerated.
nuclear@1 448 // 2. Call factory to enumerate all HW devices, adding any device that
nuclear@1 449 // was not matched.
nuclear@1 450 // 3. Remove non-matching devices.
nuclear@1 451
nuclear@1 452 Lock::Locker deviceLock(GetLock());
nuclear@1 453
nuclear@1 454 DeviceCreateDesc* devDesc, *nextdevDesc;
nuclear@1 455
nuclear@1 456 // 1.
nuclear@1 457 for(devDesc = Devices.GetFirst();
nuclear@1 458 !Devices.IsNull(devDesc); devDesc = devDesc->pNext)
nuclear@1 459 {
nuclear@1 460 //if (devDesc->pFactory == factory)
nuclear@1 461 devDesc->Enumerated = false;
nuclear@1 462 }
nuclear@1 463
nuclear@1 464 // 2.
nuclear@1 465 DeviceFactory* factory = Factories.GetFirst();
nuclear@1 466 while(!Factories.IsNull(factory))
nuclear@1 467 {
nuclear@1 468 EnumerateFactoryDevices(factory);
nuclear@1 469 factory = factory->pNext;
nuclear@1 470 }
nuclear@1 471
nuclear@1 472
nuclear@1 473 // 3.
nuclear@1 474 for(devDesc = Devices.GetFirst();
nuclear@1 475 !Devices.IsNull(devDesc); devDesc = nextdevDesc)
nuclear@1 476 {
nuclear@1 477 // In case 'devDesc' gets removed.
nuclear@1 478 nextdevDesc = devDesc->pNext;
nuclear@1 479
nuclear@1 480 // Note, device might be not enumerated since it is opened and
nuclear@1 481 // in use! Do NOT notify 'device removed' in this case (!AB)
nuclear@1 482 if (!devDesc->Enumerated)
nuclear@1 483 {
nuclear@1 484 // This deletes the devDesc for HandleCount == 0 due to Release in DeviceHandle.
nuclear@1 485 CallOnDeviceRemoved(devDesc);
nuclear@1 486
nuclear@1 487 /*
nuclear@1 488 if (devDesc->HandleCount == 0)
nuclear@1 489 {
nuclear@1 490 // Device must be dead if it ever existed, since it AddRefs to us.
nuclear@1 491 // ~DeviceCreateDesc removes its node from list.
nuclear@1 492 OVR_ASSERT(!devDesc->pDevice);
nuclear@1 493 delete devDesc;
nuclear@1 494 }
nuclear@1 495 */
nuclear@1 496 }
nuclear@1 497 }
nuclear@1 498
nuclear@1 499 return 0;
nuclear@1 500 }
nuclear@1 501
nuclear@1 502 Ptr<DeviceCreateDesc> DeviceManagerImpl::AddDevice_NeedsLock(
nuclear@1 503 const DeviceCreateDesc& createDesc)
nuclear@1 504 {
nuclear@1 505 // If found, mark as enumerated and we are done.
nuclear@1 506 DeviceCreateDesc* descCandidate = 0;
nuclear@1 507
nuclear@1 508 for(DeviceCreateDesc* devDesc = Devices.GetFirst();
nuclear@1 509 !Devices.IsNull(devDesc); devDesc = devDesc->pNext)
nuclear@1 510 {
nuclear@1 511 DeviceCreateDesc::MatchResult mr = devDesc->MatchDevice(createDesc, &descCandidate);
nuclear@1 512 if (mr == DeviceCreateDesc::Match_Found)
nuclear@1 513 {
nuclear@1 514 devDesc->Enumerated = true;
nuclear@1 515 if (!devDesc->pDevice)
nuclear@1 516 CallOnDeviceAdded(devDesc);
nuclear@1 517 return devDesc;
nuclear@1 518 }
nuclear@1 519 }
nuclear@1 520
nuclear@1 521 // Update candidate (this may involve writing fields to HMDDevice createDesc).
nuclear@1 522 if (descCandidate)
nuclear@1 523 {
nuclear@1 524 bool newDevice = false;
nuclear@1 525 if (descCandidate->UpdateMatchedCandidate(createDesc, &newDevice))
nuclear@1 526 {
nuclear@1 527 descCandidate->Enumerated = true;
nuclear@1 528 if (!descCandidate->pDevice || newDevice)
nuclear@1 529 CallOnDeviceAdded(descCandidate);
nuclear@1 530 return descCandidate;
nuclear@1 531 }
nuclear@1 532 }
nuclear@1 533
nuclear@1 534 // If not found, add new device.
nuclear@1 535 // - This stores a new descriptor with
nuclear@1 536 // {pDevice = 0, HandleCount = 1, Enumerated = true}
nuclear@1 537 DeviceCreateDesc* desc = createDesc.Clone();
nuclear@1 538 desc->pLock = pCreateDesc->pLock;
nuclear@1 539 Devices.PushBack(desc);
nuclear@1 540 desc->Enumerated = true;
nuclear@1 541
nuclear@1 542 CallOnDeviceAdded(desc);
nuclear@1 543
nuclear@1 544 return desc;
nuclear@1 545 }
nuclear@1 546
nuclear@1 547 Ptr<DeviceCreateDesc> DeviceManagerImpl::FindDevice(
nuclear@1 548 const String& path,
nuclear@1 549 DeviceType deviceType)
nuclear@1 550 {
nuclear@1 551 Lock::Locker deviceLock(GetLock());
nuclear@1 552 DeviceCreateDesc* devDesc;
nuclear@1 553
nuclear@1 554 for (devDesc = Devices.GetFirst();
nuclear@1 555 !Devices.IsNull(devDesc); devDesc = devDesc->pNext)
nuclear@1 556 {
nuclear@1 557 if ((deviceType == Device_None || deviceType == devDesc->Type) &&
nuclear@1 558 devDesc->MatchDevice(path))
nuclear@1 559 return devDesc;
nuclear@1 560 }
nuclear@1 561 return NULL;
nuclear@1 562 }
nuclear@1 563
nuclear@1 564 Ptr<DeviceCreateDesc> DeviceManagerImpl::FindHIDDevice(const HIDDeviceDesc& hidDevDesc)
nuclear@1 565 {
nuclear@1 566 Lock::Locker deviceLock(GetLock());
nuclear@1 567 DeviceCreateDesc* devDesc;
nuclear@1 568
nuclear@1 569 for (devDesc = Devices.GetFirst();
nuclear@1 570 !Devices.IsNull(devDesc); devDesc = devDesc->pNext)
nuclear@1 571 {
nuclear@1 572 if (devDesc->MatchHIDDevice(hidDevDesc))
nuclear@1 573 return devDesc;
nuclear@1 574 }
nuclear@1 575 return NULL;
nuclear@1 576 }
nuclear@1 577
nuclear@1 578 void DeviceManagerImpl::DetectHIDDevice(const HIDDeviceDesc& hidDevDesc)
nuclear@1 579 {
nuclear@1 580 Lock::Locker deviceLock(GetLock());
nuclear@1 581 DeviceFactory* factory = Factories.GetFirst();
nuclear@1 582 while(!Factories.IsNull(factory))
nuclear@1 583 {
nuclear@1 584 if (factory->DetectHIDDevice(this, hidDevDesc))
nuclear@1 585 break;
nuclear@1 586 factory = factory->pNext;
nuclear@1 587 }
nuclear@1 588
nuclear@1 589 }
nuclear@1 590
nuclear@1 591 // Enumerates devices for a particular factory.
nuclear@1 592 Void DeviceManagerImpl::EnumerateFactoryDevices(DeviceFactory* factory)
nuclear@1 593 {
nuclear@1 594
nuclear@1 595 class FactoryEnumerateVisitor : public DeviceFactory::EnumerateVisitor
nuclear@1 596 {
nuclear@1 597 DeviceManagerImpl* pManager;
nuclear@1 598 DeviceFactory* pFactory;
nuclear@1 599 public:
nuclear@1 600 FactoryEnumerateVisitor(DeviceManagerImpl* manager, DeviceFactory* factory)
nuclear@1 601 : pManager(manager), pFactory(factory) { }
nuclear@1 602
nuclear@1 603 virtual void Visit(const DeviceCreateDesc& createDesc)
nuclear@1 604 {
nuclear@1 605 pManager->AddDevice_NeedsLock(createDesc);
nuclear@1 606 }
nuclear@1 607 };
nuclear@1 608
nuclear@1 609 FactoryEnumerateVisitor newDeviceVisitor(this, factory);
nuclear@1 610 factory->EnumerateDevices(newDeviceVisitor);
nuclear@1 611
nuclear@1 612
nuclear@1 613 return 0;
nuclear@1 614 }
nuclear@1 615
nuclear@1 616
nuclear@1 617 DeviceEnumerator<> DeviceManagerImpl::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
nuclear@1 618 {
nuclear@1 619 Lock::Locker deviceLock(GetLock());
nuclear@1 620
nuclear@1 621 if (Devices.IsEmpty())
nuclear@1 622 return DeviceEnumerator<>();
nuclear@1 623
nuclear@1 624 DeviceCreateDesc* firstDeviceDesc = Devices.GetFirst();
nuclear@1 625 DeviceEnumerator<> e = enumeratorFromHandle(DeviceHandle(firstDeviceDesc), args);
nuclear@1 626
nuclear@1 627 if (!args.MatchRule(firstDeviceDesc->Type, firstDeviceDesc->Enumerated))
nuclear@1 628 {
nuclear@1 629 e.Next();
nuclear@1 630 }
nuclear@1 631
nuclear@1 632 return e;
nuclear@1 633 }
nuclear@1 634
nuclear@1 635 //-------------------------------------------------------------------------------------
nuclear@1 636 // ***** DeviceCommon
nuclear@1 637
nuclear@1 638 void DeviceCommon::DeviceAddRef()
nuclear@1 639 {
nuclear@1 640 RefCount++;
nuclear@1 641 }
nuclear@1 642
nuclear@1 643 void DeviceCommon::DeviceRelease()
nuclear@1 644 {
nuclear@1 645 while(1)
nuclear@1 646 {
nuclear@1 647 UInt32 refCount = RefCount;
nuclear@1 648 OVR_ASSERT(refCount > 0);
nuclear@1 649
nuclear@1 650 if (refCount == 1)
nuclear@1 651 {
nuclear@1 652 DeviceManagerImpl* manager = pCreateDesc->GetManagerImpl();
nuclear@1 653 ThreadCommandQueue* queue = manager->GetThreadQueue();
nuclear@1 654
nuclear@1 655 // Enqueue ReleaseDevice for {1 -> 0} transition with no wait.
nuclear@1 656 // We pass our reference ownership into the queue to destroy.
nuclear@1 657 // It's in theory possible for another thread to re-steal our device reference,
nuclear@1 658 // but that is checked for atomically in DeviceManagerImpl::ReleaseDevice.
nuclear@1 659 if (!queue->PushCall(manager, &DeviceManagerImpl::ReleaseDevice_MgrThread,
nuclear@1 660 pCreateDesc->pDevice))
nuclear@1 661 {
nuclear@1 662 // PushCall shouldn't fail because background thread runs while manager is
nuclear@1 663 // alive and we are holding Manager alive through pParent chain.
nuclear@1 664 OVR_ASSERT(false);
nuclear@1 665 }
nuclear@1 666
nuclear@1 667 // Warning! At his point everything, including manager, may be dead.
nuclear@1 668 break;
nuclear@1 669 }
nuclear@1 670 else if (RefCount.CompareAndSet_NoSync(refCount, refCount-1))
nuclear@1 671 {
nuclear@1 672 break;
nuclear@1 673 }
nuclear@1 674 }
nuclear@1 675 }
nuclear@1 676
nuclear@1 677
nuclear@1 678
nuclear@1 679 //-------------------------------------------------------------------------------------
nuclear@1 680 // ***** DeviceCreateDesc
nuclear@1 681
nuclear@1 682
nuclear@1 683 void DeviceCreateDesc::AddRef()
nuclear@1 684 {
nuclear@1 685 // Technically, HandleCount { 0 -> 1 } transition can only happen during Lock,
nuclear@1 686 // but we leave this to caller to worry about (happens during enumeration).
nuclear@1 687 HandleCount++;
nuclear@1 688 }
nuclear@1 689
nuclear@1 690 void DeviceCreateDesc::Release()
nuclear@1 691 {
nuclear@1 692 while(1)
nuclear@1 693 {
nuclear@1 694 UInt32 handleCount = HandleCount;
nuclear@1 695 // HandleCount must obviously be >= 1, since we are releasing it.
nuclear@1 696 OVR_ASSERT(handleCount > 0);
nuclear@1 697
nuclear@1 698 // {1 -> 0} transition may cause us to be destroyed, so require a lock.
nuclear@1 699 if (handleCount == 1)
nuclear@1 700 {
nuclear@1 701 Ptr<DeviceManagerLock> lockKeepAlive;
nuclear@1 702 Lock::Locker deviceLockScope(GetLock());
nuclear@1 703
nuclear@1 704 if (!HandleCount.CompareAndSet_NoSync(handleCount, 0))
nuclear@1 705 continue;
nuclear@1 706
nuclear@1 707 OVR_ASSERT(pDevice == 0);
nuclear@1 708
nuclear@1 709 // Destroy *this if the manager was destroyed already, or Enumerated
nuclear@1 710 // is false (device no longer available).
nuclear@1 711 if (!GetManagerImpl() || !Enumerated)
nuclear@1 712 {
nuclear@1 713 lockKeepAlive = pLock;
nuclear@1 714
nuclear@1 715 // Remove from manager list (only matters for !Enumerated).
nuclear@1 716 if (pNext)
nuclear@1 717 {
nuclear@1 718 RemoveNode();
nuclear@1 719 pNext = pPrev = 0;
nuclear@1 720 }
nuclear@1 721
nuclear@1 722 delete this;
nuclear@1 723 }
nuclear@1 724
nuclear@1 725 // Available DeviceCreateDesc may survive with { HandleCount == 0 },
nuclear@1 726 // in case it might be enumerated again later.
nuclear@1 727 break;
nuclear@1 728 }
nuclear@1 729 else if (HandleCount.CompareAndSet_NoSync(handleCount, handleCount-1))
nuclear@1 730 {
nuclear@1 731 break;
nuclear@1 732 }
nuclear@1 733 }
nuclear@1 734 }
nuclear@1 735
nuclear@1 736 HMDDevice* HMDDevice::Disconnect(SensorDevice* psensor)
nuclear@1 737 {
nuclear@1 738 if (!psensor)
nuclear@1 739 return NULL;
nuclear@1 740
nuclear@1 741 OVR::DeviceManager* manager = GetManager();
nuclear@1 742 if (manager)
nuclear@1 743 {
nuclear@1 744 //DeviceManagerImpl* mgrImpl = static_cast<DeviceManagerImpl*>(manager);
nuclear@1 745 Ptr<DeviceCreateDesc> desc = getDeviceCommon()->pCreateDesc;
nuclear@1 746 if (desc)
nuclear@1 747 {
nuclear@1 748 class Visitor : public DeviceFactory::EnumerateVisitor
nuclear@1 749 {
nuclear@1 750 Ptr<DeviceCreateDesc> Desc;
nuclear@1 751 public:
nuclear@1 752 Visitor(DeviceCreateDesc* desc) : Desc(desc) {}
nuclear@1 753 virtual void Visit(const DeviceCreateDesc& createDesc)
nuclear@1 754 {
nuclear@1 755 Lock::Locker lock(Desc->GetLock());
nuclear@1 756 Desc->UpdateMatchedCandidate(createDesc);
nuclear@1 757 }
nuclear@1 758 } visitor(desc);
nuclear@1 759 //SensorDeviceImpl* sImpl = static_cast<SensorDeviceImpl*>(psensor);
nuclear@1 760
nuclear@1 761 SensorDisplayInfoImpl displayInfo;
nuclear@1 762
nuclear@1 763 if (psensor->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
nuclear@1 764 {
nuclear@1 765 displayInfo.Unpack();
nuclear@1 766
nuclear@1 767 // If we got display info, try to match / create HMDDevice as well
nuclear@1 768 // so that sensor settings give preference.
nuclear@1 769 if (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt)
nuclear@1 770 {
nuclear@1 771 SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(displayInfo, visitor);
nuclear@1 772 }
nuclear@1 773 }
nuclear@1 774 }
nuclear@1 775 }
nuclear@1 776 return this;
nuclear@1 777 }
nuclear@1 778
nuclear@1 779 bool HMDDevice::IsDisconnected() const
nuclear@1 780 {
nuclear@1 781 OVR::HMDInfo info;
nuclear@1 782 GetDeviceInfo(&info);
nuclear@1 783 // if strlen(info.DisplayDeviceName) == 0 then
nuclear@1 784 // this HMD is 'fake' (created using sensor).
nuclear@1 785 return (strlen(info.DisplayDeviceName) == 0);
nuclear@1 786 }
nuclear@1 787
nuclear@1 788
nuclear@1 789 } // namespace OVR
nuclear@1 790