nuclear@1: /************************************************************************************ nuclear@1: nuclear@1: Filename : OVR_Win32_DeviceManager.h nuclear@1: Content : Win32-specific DeviceManager header. nuclear@1: Created : September 21, 2012 nuclear@1: Authors : Michael Antonov nuclear@1: nuclear@1: Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. nuclear@1: nuclear@1: Use of this software is subject to the terms of the Oculus license nuclear@1: agreement provided at the time of installation or download, or which nuclear@1: otherwise accompanies this software in either electronic or hard copy form. nuclear@1: nuclear@1: *************************************************************************************/ nuclear@1: nuclear@1: #ifndef OVR_Win32_DeviceManager_h nuclear@1: #define OVR_Win32_DeviceManager_h nuclear@1: nuclear@1: #include "OVR_DeviceImpl.h" nuclear@1: #include "OVR_Win32_DeviceStatus.h" nuclear@1: nuclear@1: #include "Kernel/OVR_Timer.h" nuclear@1: nuclear@1: nuclear@1: namespace OVR { namespace Win32 { nuclear@1: nuclear@1: class DeviceManagerThread; nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** Win32 DeviceManager nuclear@1: nuclear@1: class DeviceManager : public DeviceManagerImpl nuclear@1: { nuclear@1: public: nuclear@1: DeviceManager(); nuclear@1: ~DeviceManager(); nuclear@1: nuclear@1: // Initialize/Shutdowncreate and shutdown manger thread. nuclear@1: virtual bool Initialize(DeviceBase* parent); nuclear@1: virtual void Shutdown(); nuclear@1: nuclear@1: virtual ThreadCommandQueue* GetThreadQueue(); nuclear@1: virtual ThreadId GetThreadId() const; nuclear@1: nuclear@1: virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args); nuclear@1: nuclear@1: virtual bool GetDeviceInfo(DeviceInfo* info) const; nuclear@1: nuclear@1: // Fills HIDDeviceDesc by using the path. nuclear@1: // Returns 'true' if successful, 'false' otherwise. nuclear@1: bool GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const; nuclear@1: nuclear@1: Ptr pThread; nuclear@1: }; nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** Device Manager Background Thread nuclear@1: nuclear@1: class DeviceManagerThread : public Thread, public ThreadCommandQueue, public DeviceStatus::Notifier nuclear@1: { nuclear@1: friend class DeviceManager; nuclear@1: enum { ThreadStackSize = 32 * 1024 }; nuclear@1: public: nuclear@1: DeviceManagerThread(DeviceManager* pdevMgr); nuclear@1: ~DeviceManagerThread(); nuclear@1: nuclear@1: virtual int Run(); nuclear@1: nuclear@1: // ThreadCommandQueue notifications for CommandEvent handling. nuclear@1: virtual void OnPushNonEmpty_Locked() { ::SetEvent(hCommandEvent); } nuclear@1: virtual void OnPopEmpty_Locked() { ::ResetEvent(hCommandEvent); } nuclear@1: nuclear@1: nuclear@1: // Notifier used for different updates (EVENT or regular timing or messages). nuclear@1: class Notifier nuclear@1: { nuclear@1: public: nuclear@1: // Called when overlapped I/O handle is signaled. nuclear@1: virtual void OnOverlappedEvent(HANDLE hevent) { OVR_UNUSED1(hevent); } nuclear@1: nuclear@1: // Called when timing ticks are updated. nuclear@1: // Returns the largest number of microseconds this function can nuclear@1: // wait till next call. nuclear@1: virtual UInt64 OnTicks(UInt64 ticksMks) nuclear@1: { OVR_UNUSED1(ticksMks); return Timer::MksPerSecond * 1000; } nuclear@1: nuclear@1: enum DeviceMessageType nuclear@1: { nuclear@1: DeviceMessage_DeviceAdded = 0, nuclear@1: DeviceMessage_DeviceRemoved = 1, nuclear@1: }; nuclear@1: nuclear@1: // Called to notify device object. nuclear@1: virtual bool OnDeviceMessage(DeviceMessageType messageType, nuclear@1: const String& devicePath, nuclear@1: bool* error) nuclear@1: { OVR_UNUSED3(messageType, devicePath, error); return false; } nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: // Adds device's OVERLAPPED structure for I/O. nuclear@1: // After it's added, Overlapped object will be signaled if a message arrives. nuclear@1: bool AddOverlappedEvent(Notifier* notify, HANDLE hevent); nuclear@1: bool RemoveOverlappedEvent(Notifier* notify, HANDLE hevent); nuclear@1: nuclear@1: // Add notifier that will be called at regular intervals. nuclear@1: bool AddTicksNotifier(Notifier* notify); nuclear@1: bool RemoveTicksNotifier(Notifier* notify); nuclear@1: nuclear@1: bool AddMessageNotifier(Notifier* notify); nuclear@1: bool RemoveMessageNotifier(Notifier* notify); nuclear@1: nuclear@1: // DeviceStatus::Notifier interface. nuclear@1: bool OnMessage(MessageType type, const String& devicePath); nuclear@1: nuclear@1: void DetachDeviceManager(); nuclear@1: nuclear@1: private: nuclear@1: bool threadInitialized() { return hCommandEvent != 0; } nuclear@1: nuclear@1: // Event used to wake us up thread commands are enqueued. nuclear@1: HANDLE hCommandEvent; nuclear@1: nuclear@1: // Event notifications for devices whose OVERLAPPED I/O we service. nuclear@1: // This list is modified through AddDeviceOverlappedEvent. nuclear@1: // WaitHandles[0] always == hCommandEvent, with null device. nuclear@1: Array WaitHandles; nuclear@1: Array WaitNotifiers; nuclear@1: nuclear@1: // Ticks notifiers - used for time-dependent events such as keep-alive. nuclear@1: Array TicksNotifiers; nuclear@1: nuclear@1: // Message notifiers. nuclear@1: Array MessageNotifiers; nuclear@1: nuclear@1: // Object that manages notifications originating from Windows messages. nuclear@1: Ptr pStatusObject; nuclear@1: nuclear@1: Lock DevMgrLock; nuclear@1: // pDeviceMgr should be accessed under DevMgrLock nuclear@1: DeviceManager* pDeviceMgr; // back ptr, no addref. nuclear@1: }; nuclear@1: nuclear@1: }} // namespace Win32::OVR nuclear@1: nuclear@1: #endif // OVR_Win32_DeviceManager_h