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