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
|