oculus1
diff libovr/Src/OVR_DeviceImpl.h @ 1:e2f9e4603129
added LibOVR and started a simple vr wrapper.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 14 Sep 2013 16:14:59 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libovr/Src/OVR_DeviceImpl.h Sat Sep 14 16:14:59 2013 +0300 1.3 @@ -0,0 +1,432 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_DeviceImpl.h 1.7 +Content : Partial back-end independent implementation of Device interfaces 1.8 +Created : October 10, 2012 1.9 +Authors : Michael Antonov 1.10 + 1.11 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 1.12 + 1.13 +Use of this software is subject to the terms of the Oculus license 1.14 +agreement provided at the time of installation or download, or which 1.15 +otherwise accompanies this software in either electronic or hard copy form. 1.16 + 1.17 +*************************************************************************************/ 1.18 + 1.19 +#ifndef OVR_DeviceImpl_h 1.20 +#define OVR_DeviceImpl_h 1.21 + 1.22 +#include "OVR_Device.h" 1.23 +#include "Kernel/OVR_Atomic.h" 1.24 +#include "Kernel/OVR_Log.h" 1.25 +#include "Kernel/OVR_System.h" 1.26 + 1.27 +#include "Kernel/OVR_Threads.h" 1.28 +#include "OVR_ThreadCommandQueue.h" 1.29 +#include "OVR_HIDDevice.h" 1.30 + 1.31 +namespace OVR { 1.32 + 1.33 +class DeviceManagerImpl; 1.34 +class DeviceFactory; 1.35 + 1.36 +enum 1.37 +{ 1.38 + Oculus_VendorId = 0x2833 1.39 +}; 1.40 + 1.41 +//------------------------------------------------------------------------------------- 1.42 +// Globally shared Lock implementation used for MessageHandlers. 1.43 + 1.44 +class SharedLock 1.45 +{ 1.46 +public: 1.47 + SharedLock() : UseCount(0) {} 1.48 + 1.49 + Lock* GetLockAddRef(); 1.50 + void ReleaseLock(Lock* plock); 1.51 + 1.52 +private: 1.53 + Lock* toLock() { return (Lock*)Buffer; } 1.54 + 1.55 + // UseCount and max alignment. 1.56 + volatile int UseCount; 1.57 + UInt64 Buffer[(sizeof(Lock)+sizeof(UInt64)-1)/sizeof(UInt64)]; 1.58 +}; 1.59 + 1.60 + 1.61 +// Wrapper for MessageHandler that includes synchronization logic. 1.62 +// References to MessageHandlers are organized in a list to allow for them to 1.63 +// easily removed with MessageHandler::RemoveAllHandlers. 1.64 +class MessageHandlerRef : public ListNode<MessageHandlerRef> 1.65 +{ 1.66 +public: 1.67 + MessageHandlerRef(DeviceBase* device); 1.68 + ~MessageHandlerRef(); 1.69 + 1.70 + void SetHandler(MessageHandler* hander); 1.71 + 1.72 + // Not-thread-safe version 1.73 + void SetHandler_NTS(MessageHandler* hander); 1.74 + 1.75 + void Call(const Message& msg) 1.76 + { 1.77 + Lock::Locker lockScope(pLock); 1.78 + if (pHandler) 1.79 + pHandler->OnMessage(msg); 1.80 + } 1.81 + 1.82 + Lock* GetLock() const { return pLock; } 1.83 + 1.84 + // GetHandler() is not thread safe if used out of order across threads; nothing can be done 1.85 + // about that. 1.86 + MessageHandler* GetHandler() const { return pHandler; } 1.87 + DeviceBase* GetDevice() const { return pDevice; } 1.88 + 1.89 +private: 1.90 + Lock* pLock; // Cached global handler lock. 1.91 + DeviceBase* pDevice; 1.92 + MessageHandler* pHandler; 1.93 +}; 1.94 + 1.95 + 1.96 + 1.97 +//------------------------------------------------------------------------------------- 1.98 + 1.99 +// DeviceManagerLock is a synchronization lock used by DeviceManager for Devices 1.100 +// and is allocated separately for potentially longer lifetime. 1.101 +// 1.102 +// DeviceManagerLock is used for all of the following: 1.103 +// - Adding/removing devices 1.104 +// - Reporting manager lifetime (pManager != 0) for DeviceHandles 1.105 +// - Protecting device creation/shutdown. 1.106 + 1.107 +class DeviceManagerLock : public RefCountBase<DeviceManagerLock> 1.108 +{ 1.109 +public: 1.110 + Lock CreateLock; 1.111 + DeviceManagerImpl* pManager; 1.112 + 1.113 + DeviceManagerLock() : pManager(0) { } 1.114 +}; 1.115 + 1.116 + 1.117 +// DeviceCreateDesc provides all of the information needed to create any device, a derived 1.118 +// instance of this class is created by DeviceFactory during enumeration. 1.119 +// - DeviceCreateDesc may or may not be a part of DeviceManager::Devices list (check pNext != 0). 1.120 +// - Referenced and kept alive by DeviceHandle. 1.121 + 1.122 +class DeviceCreateDesc : public ListNode<DeviceCreateDesc>, public NewOverrideBase 1.123 +{ 1.124 + void operator = (const DeviceCreateDesc&) { } // Assign not supported; suppress MSVC warning. 1.125 +public: 1.126 + DeviceCreateDesc(DeviceFactory* factory, DeviceType type) 1.127 + : pFactory(factory), Type(type), pLock(0), HandleCount(0), pDevice(0), Enumerated(true) 1.128 + { 1.129 + pNext = pPrev = 0; 1.130 + } 1.131 + 1.132 + virtual ~DeviceCreateDesc() 1.133 + { 1.134 + OVR_ASSERT(!pDevice); 1.135 + if (pNext) 1.136 + RemoveNode(); 1.137 + } 1.138 + 1.139 + DeviceManagerImpl* GetManagerImpl() const { return pLock->pManager; } 1.140 + Lock* GetLock() const { return &pLock->CreateLock; } 1.141 + 1.142 + // DeviceCreateDesc reference counting is tied to Devices list management, 1.143 + // see comments for HandleCount. 1.144 + void AddRef(); 1.145 + void Release(); 1.146 + 1.147 + 1.148 + // *** Device creation/matching Interface 1.149 + 1.150 + 1.151 + // Cloning copies us to an allocated object when new device is enumerated. 1.152 + virtual DeviceCreateDesc* Clone() const = 0; 1.153 + // Creates a new device instance without Initializing it; the 1.154 + // later is done my Initialize()/Shutdown() methods of the device itself. 1.155 + virtual DeviceBase* NewDeviceInstance() = 0; 1.156 + // Override to return device-specific info. 1.157 + virtual bool GetDeviceInfo(DeviceInfo* info) const = 0; 1.158 + 1.159 + 1.160 + enum MatchResult 1.161 + { 1.162 + Match_None, 1.163 + Match_Found, 1.164 + Match_Candidate 1.165 + }; 1.166 + 1.167 + // Override to return Match_Found if descriptor matches our device. 1.168 + // Match_Candidate can be returned, with pcandicate update, if this may be a match 1.169 + // but more searching is necessary. If this is the case UpdateMatchedCandidate will be called. 1.170 + virtual MatchResult MatchDevice(const DeviceCreateDesc& other, 1.171 + DeviceCreateDesc** pcandidate) const = 0; 1.172 + 1.173 + // Called for matched candidate after all potential matches are iterated. 1.174 + // Used to update HMDevice creation arguments from Sensor. 1.175 + // Optional return param 'newDeviceFlag' will be set to true if the 1.176 + // 'desc' refers to a new device; false, otherwise. 1.177 + // Return 'false' to create new object, 'true' if done with this argument. 1.178 + virtual bool UpdateMatchedCandidate( 1.179 + const DeviceCreateDesc& desc, bool* newDeviceFlag = NULL) 1.180 + { OVR_UNUSED2(desc, newDeviceFlag); return false; } 1.181 + 1.182 + // Matches HID device to the descriptor. 1.183 + virtual bool MatchHIDDevice(const HIDDeviceDesc&) const { return false; } 1.184 + 1.185 + // Matches device by path. 1.186 + virtual bool MatchDevice(const String& /*path*/) { return false; } 1.187 +//protected: 1.188 + DeviceFactory* const pFactory; 1.189 + const DeviceType Type; 1.190 + 1.191 + // List in which this descriptor lives. pList->CreateLock required if added/removed. 1.192 + Ptr<DeviceManagerLock> pLock; 1.193 + 1.194 + // Strong references to us: Incremented by Device, DeviceHandles & Enumerators. 1.195 + // May be 0 if device not created and there are no handles. 1.196 + // Following transitions require pList->CreateLock: 1.197 + // {1 -> 0}: May delete & remove handle if no longer available. 1.198 + // {0 -> 1}: Device creation is only possible if manager is still alive. 1.199 + AtomicInt<UInt32> HandleCount; 1.200 + // If not null, points to our created device instance. Modified during lock only. 1.201 + DeviceBase* pDevice; 1.202 + // True if device is marked as available during enumeration. 1.203 + bool Enumerated; 1.204 +}; 1.205 + 1.206 + 1.207 + 1.208 +// Common data present in the implementation of every DeviceBase. 1.209 +// Injected by DeviceImpl. 1.210 +class DeviceCommon 1.211 +{ 1.212 +public: 1.213 + AtomicInt<UInt32> RefCount; 1.214 + Ptr<DeviceCreateDesc> pCreateDesc; 1.215 + Ptr<DeviceBase> pParent; 1.216 + MessageHandlerRef HandlerRef; 1.217 + 1.218 + DeviceCommon(DeviceCreateDesc* createDesc, DeviceBase* device, DeviceBase* parent) 1.219 + : RefCount(1), pCreateDesc(createDesc), pParent(parent), HandlerRef(device) 1.220 + { 1.221 + } 1.222 + 1.223 + // Device reference counting delegates to Manager thread to actually kill devices. 1.224 + void DeviceAddRef(); 1.225 + void DeviceRelease(); 1.226 + 1.227 + Lock* GetLock() const { return pCreateDesc->GetLock(); } 1.228 + 1.229 + virtual bool Initialize(DeviceBase* parent) = 0; 1.230 + virtual void Shutdown() = 0; 1.231 +}; 1.232 + 1.233 + 1.234 +//------------------------------------------------------------------------------------- 1.235 +// DeviceImpl address DeviceRecord implementation to a device base class B. 1.236 +// B must be derived form DeviceBase. 1.237 + 1.238 +template<class B> 1.239 +class DeviceImpl : public B, public DeviceCommon 1.240 +{ 1.241 +public: 1.242 + DeviceImpl(DeviceCreateDesc* createDesc, DeviceBase* parent) 1.243 + : DeviceCommon(createDesc, getThis(), parent) 1.244 + { 1.245 + } 1.246 + 1.247 + // Convenience method to avoid manager access typecasts. 1.248 + DeviceManagerImpl* GetManagerImpl() const { return pCreateDesc->pLock->pManager; } 1.249 + 1.250 + // Inline to avoid warnings. 1.251 + DeviceImpl* getThis() { return this; } 1.252 + 1.253 + // Common implementation delegate to avoid virtual inheritance and dynamic casts. 1.254 + virtual DeviceCommon* getDeviceCommon() const { return (DeviceCommon*)this; } 1.255 + 1.256 + /* 1.257 + virtual void AddRef() { pCreateDesc->DeviceAddRef(); } 1.258 + virtual void Release() { pCreateDesc->DeviceRelease(); } 1.259 + virtual DeviceBase* GetParent() const { return pParent.GetPtr(); } 1.260 + virtual DeviceManager* GetManager() const { return pCreateDesc->pLock->pManager;} 1.261 + virtual void SetMessageHandler(MessageHandler* handler) { HanderRef.SetHandler(handler); } 1.262 + virtual MessageHandler* GetMessageHandler() const { return HanderRef.GetHandler(); } 1.263 + virtual DeviceType GetType() const { return pCreateDesc->Type; } 1.264 + virtual DeviceType GetType() const { return pCreateDesc->Type; } 1.265 + */ 1.266 +}; 1.267 + 1.268 + 1.269 +//------------------------------------------------------------------------------------- 1.270 +// ***** DeviceFactory 1.271 + 1.272 +// DeviceFactory is maintained in DeviceManager for each separately-enumerable 1.273 +// device type; factories allow separation of unrelated enumeration code. 1.274 + 1.275 +class DeviceFactory : public ListNode<DeviceFactory>, public NewOverrideBase 1.276 +{ 1.277 +public: 1.278 + 1.279 + DeviceFactory() : pManager(0) 1.280 + { 1.281 + pNext = pPrev = 0; 1.282 + } 1.283 + virtual ~DeviceFactory() { } 1.284 + 1.285 + DeviceManagerImpl* GetManagerImpl() { return pManager; } 1.286 + 1.287 + // Notifiers called when we are added to/removed from a device. 1.288 + virtual bool AddedToManager(DeviceManagerImpl* manager) 1.289 + { 1.290 + OVR_ASSERT(pManager == 0); 1.291 + pManager = manager; 1.292 + return true; 1.293 + } 1.294 + 1.295 + virtual void RemovedFromManager() 1.296 + { 1.297 + pManager = 0; 1.298 + } 1.299 + 1.300 + 1.301 + // *** Device Enumeration/Creation Support 1.302 + 1.303 + // Passed to EnumerateDevices to be informed of every device detected. 1.304 + class EnumerateVisitor 1.305 + { 1.306 + public: 1.307 + virtual void Visit(const DeviceCreateDesc& createDesc) = 0; 1.308 + }; 1.309 + 1.310 + // Enumerates factory devices by notifying EnumerateVisitor about every 1.311 + // device that is present. 1.312 + virtual void EnumerateDevices(EnumerateVisitor& visitor) = 0; 1.313 + 1.314 + // Matches vendorId/productId pair with the factory; returns 'true' 1.315 + // if the factory can handle the device. 1.316 + virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const 1.317 + { 1.318 + OVR_UNUSED2(vendorId, productId); 1.319 + return false; 1.320 + } 1.321 + 1.322 + // Detects the HID device and adds the DeviceCreateDesc into Devices list, if 1.323 + // the device belongs to this factory. Returns 'false', if not. 1.324 + virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc) 1.325 + { 1.326 + OVR_UNUSED2(pdevMgr, desc); 1.327 + return false; 1.328 + } 1.329 + 1.330 +protected: 1.331 + DeviceManagerImpl* pManager; 1.332 +}; 1.333 + 1.334 + 1.335 +//------------------------------------------------------------------------------------- 1.336 +// ***** DeviceManagerImpl 1.337 + 1.338 +// DeviceManagerImpl is a partial default DeviceManager implementation that 1.339 +// maintains a list of devices and supports their enumeration. 1.340 + 1.341 +class DeviceManagerImpl : public DeviceImpl<OVR::DeviceManager>, public ThreadCommandQueue 1.342 +{ 1.343 +public: 1.344 + DeviceManagerImpl(); 1.345 + ~DeviceManagerImpl(); 1.346 + 1.347 + // Constructor helper function to create Descriptor and manager lock during initialization. 1.348 + static DeviceCreateDesc* CreateManagerDesc(); 1.349 + 1.350 + // DeviceManagerImpl provides partial implementation of Initialize/Shutdown that must 1.351 + // be called by the platform-specific derived class. 1.352 + virtual bool Initialize(DeviceBase* parent); 1.353 + virtual void Shutdown(); 1.354 + 1.355 + 1.356 + // Every DeviceManager has an associated profile manager, which is used to store 1.357 + // user settings that may affect device behavior. 1.358 + virtual ProfileManager* GetProfileManager() const { return pProfileManager.GetPtr(); } 1.359 + 1.360 + // Override to return ThreadCommandQueue implementation used to post commands 1.361 + // to the background device manager thread (that must be created by Initialize). 1.362 + virtual ThreadCommandQueue* GetThreadQueue() = 0; 1.363 + 1.364 + // Returns the thread id of the DeviceManager. 1.365 + virtual ThreadId GetThreadId() const = 0; 1.366 + 1.367 + virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args); 1.368 + 1.369 + 1.370 + // 1.371 + void AddFactory(DeviceFactory* factory) 1.372 + { 1.373 + // This lock is only needed if we call AddFactory after manager thread creation. 1.374 + Lock::Locker scopeLock(GetLock()); 1.375 + Factories.PushBack(factory); 1.376 + factory->AddedToManager(this); 1.377 + } 1.378 + 1.379 + void CallOnDeviceAdded(DeviceCreateDesc* desc) 1.380 + { 1.381 + HandlerRef.Call(MessageDeviceStatus(Message_DeviceAdded, this, DeviceHandle(desc))); 1.382 + } 1.383 + void CallOnDeviceRemoved(DeviceCreateDesc* desc) 1.384 + { 1.385 + HandlerRef.Call(MessageDeviceStatus(Message_DeviceRemoved, this, DeviceHandle(desc))); 1.386 + } 1.387 + 1.388 + // Helper to access Common data for a device. 1.389 + static DeviceCommon* GetDeviceCommon(DeviceBase* device) 1.390 + { 1.391 + return device->getDeviceCommon(); 1.392 + } 1.393 + 1.394 + 1.395 + // Background-thread callbacks for DeviceCreation/Release. These 1.396 + DeviceBase* CreateDevice_MgrThread(DeviceCreateDesc* createDesc, DeviceBase* parent = 0); 1.397 + Void ReleaseDevice_MgrThread(DeviceBase* device); 1.398 + 1.399 + 1.400 + // Calls EnumerateDevices() on all factories 1.401 + virtual Void EnumerateAllFactoryDevices(); 1.402 + // Enumerates devices for a particular factory. 1.403 + virtual Void EnumerateFactoryDevices(DeviceFactory* factory); 1.404 + 1.405 + virtual HIDDeviceManager* GetHIDDeviceManager() const 1.406 + { 1.407 + return HidDeviceManager; 1.408 + } 1.409 + 1.410 + // Adds device (DeviceCreateDesc*) into Devices. Returns NULL, 1.411 + // if unsuccessful or device is already in the list. 1.412 + virtual Ptr<DeviceCreateDesc> AddDevice_NeedsLock(const DeviceCreateDesc& createDesc); 1.413 + 1.414 + // Finds a device descriptor by path and optional type. 1.415 + Ptr<DeviceCreateDesc> FindDevice(const String& path, DeviceType = Device_None); 1.416 + 1.417 + // Finds HID device by HIDDeviceDesc. 1.418 + Ptr<DeviceCreateDesc> FindHIDDevice(const HIDDeviceDesc&); 1.419 + void DetectHIDDevice(const HIDDeviceDesc&); 1.420 + 1.421 + // Manager Lock-protected list of devices. 1.422 + List<DeviceCreateDesc> Devices; 1.423 + 1.424 + // Factories used to detect and manage devices. 1.425 + List<DeviceFactory> Factories; 1.426 + 1.427 +protected: 1.428 + Ptr<HIDDeviceManager> HidDeviceManager; 1.429 + Ptr<ProfileManager> pProfileManager; 1.430 +}; 1.431 + 1.432 + 1.433 +} // namespace OVR 1.434 + 1.435 +#endif