nuclear@1: /************************************************************************************ nuclear@1: nuclear@1: PublicHeader: OVR.h nuclear@1: Filename : OVR_Device.h nuclear@1: Content : Definition of HMD-related Device interfaces 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_Device_h nuclear@1: #define OVR_Device_h nuclear@1: nuclear@1: #include "OVR_DeviceConstants.h" nuclear@1: #include "OVR_DeviceHandle.h" nuclear@1: #include "OVR_DeviceMessages.h" nuclear@1: #include "OVR_HIDDeviceBase.h" nuclear@1: nuclear@1: #include "Kernel/OVR_Atomic.h" nuclear@1: #include "Kernel/OVR_RefCount.h" nuclear@1: #include "Kernel/OVR_String.h" nuclear@1: nuclear@1: namespace OVR { nuclear@1: nuclear@1: // Declared externally nuclear@1: class Profile; nuclear@1: class ProfileManager; // << Should be renamed for consistency nuclear@1: nuclear@1: // Forward declarations nuclear@1: class SensorDevice; nuclear@1: class DeviceCommon; nuclear@1: class DeviceManager; nuclear@1: nuclear@1: // MessageHandler is a base class from which users derive to receive messages, nuclear@1: // its OnMessage handler will be called for messages once it is installed on nuclear@1: // a device. Same message handler can be installed on multiple devices. nuclear@1: class MessageHandler nuclear@1: { nuclear@1: friend class MessageHandlerImpl; nuclear@1: public: nuclear@1: MessageHandler(); nuclear@1: virtual ~MessageHandler(); nuclear@1: nuclear@1: // Returns 'true' if handler is currently installed on any devices. nuclear@1: bool IsHandlerInstalled() const; nuclear@1: nuclear@1: // Should be called from derived class destructor to avoid handler nuclear@1: // being called after it exits. nuclear@1: void RemoveHandlerFromDevices(); nuclear@1: nuclear@1: // Returns a pointer to the internal lock object that is locked by a nuclear@1: // background thread while OnMessage() is called. nuclear@1: // This lock guaranteed to survive until ~MessageHandler. nuclear@1: Lock* GetHandlerLock() const; nuclear@1: nuclear@1: nuclear@1: virtual void OnMessage(const Message&) { } nuclear@1: nuclear@1: // Determines if handler supports a specific message type. Can nuclear@1: // be used to filter out entire message groups. The result nuclear@1: // returned by this function shouldn't change after handler creation. nuclear@1: virtual bool SupportsMessageType(MessageType) const { return true; } nuclear@1: nuclear@1: private: nuclear@1: UPInt Internal[4]; nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** DeviceBase nuclear@1: nuclear@1: // DeviceBase is the base class for all OVR Devices. It provides the following basic nuclear@1: // functionality: nuclear@1: // - Reports device type, manager, and associated parent (if any). nuclear@1: // - Supports installable message handlers, which are notified of device events. nuclear@1: // - Device objects are created through DeviceHandle::CreateDevice or more commonly nuclear@1: // through DeviceEnumerator<>::CreateDevice. nuclear@1: // - Created devices are reference counted, starting with RefCount of 1. nuclear@1: // - Device is resources are cleaned up when it is Released, although its handles nuclear@1: // may survive longer if referenced. nuclear@1: nuclear@1: class DeviceBase : public NewOverrideBase nuclear@1: { nuclear@1: friend class DeviceHandle; nuclear@1: friend class DeviceManagerImpl; nuclear@1: public: nuclear@1: nuclear@1: // Enumerating DeviceBase enumerates all devices. nuclear@1: enum { EnumDeviceType = Device_All }; nuclear@1: nuclear@1: virtual ~DeviceBase() { } nuclear@1: virtual void AddRef(); nuclear@1: virtual void Release(); nuclear@1: nuclear@1: virtual DeviceBase* GetParent() const; nuclear@1: virtual DeviceManager* GetManager() const; nuclear@1: nuclear@1: virtual void SetMessageHandler(MessageHandler* handler); nuclear@1: virtual MessageHandler* GetMessageHandler() const; nuclear@1: nuclear@1: virtual DeviceType GetType() const; nuclear@1: virtual bool GetDeviceInfo(DeviceInfo* info) const; nuclear@1: nuclear@1: // returns the MessageHandler's lock nuclear@1: Lock* GetHandlerLock() const; nuclear@1: protected: nuclear@1: // Internal nuclear@1: virtual DeviceCommon* getDeviceCommon() const = 0; nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** DeviceInfo nuclear@1: nuclear@1: // DeviceInfo describes a device and its capabilities, obtained by calling nuclear@1: // GetDeviceInfo. This base class only contains device-independent functionality; nuclear@1: // users will normally use a derived HMDInfo or SensorInfo classes for more nuclear@1: // extensive device info. nuclear@1: nuclear@1: class DeviceInfo nuclear@1: { nuclear@1: public: nuclear@1: DeviceInfo() : InfoClassType(Device_None), Type(Device_None), Version(0) nuclear@1: { ProductName[0] = Manufacturer[0] = 0; } nuclear@1: nuclear@1: enum { MaxNameLength = 32 }; nuclear@1: nuclear@1: // Type of device for which DeviceInfo is intended. nuclear@1: // This will be set to Device_HMD for HMDInfo structure, note that this may be nuclear@1: // different form the actual device type since (Device_None) is valid. nuclear@1: const DeviceType InfoClassType; nuclear@1: // Type of device this describes. This must be the same as InfoClassType when nuclear@1: // InfoClassType != Device_None. nuclear@1: DeviceType Type; nuclear@1: // Name string describing the product: "Oculus Rift DK1", etc. nuclear@1: char ProductName[MaxNameLength]; nuclear@1: char Manufacturer[MaxNameLength]; nuclear@1: unsigned Version; nuclear@1: nuclear@1: protected: nuclear@1: DeviceInfo(DeviceType type) : InfoClassType(type), Type(type), Version(0) nuclear@1: { ProductName[0] = Manufacturer[0] = 0; } nuclear@1: void operator = (const DeviceInfo&) { OVR_ASSERT(0); } // Assignment not allowed. nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // DeviceEnumerationArgs provides device enumeration argumenrs for DeviceManager::EnumerateDevicesEx. nuclear@1: class DeviceEnumerationArgs nuclear@1: { nuclear@1: public: nuclear@1: DeviceEnumerationArgs(DeviceType enumType, bool availableOnly) nuclear@1: : EnumType(enumType), AvailableOnly(availableOnly) nuclear@1: { } nuclear@1: nuclear@1: // Helper; returns true if args match our enumeration criteria. nuclear@1: bool MatchRule(DeviceType type, bool available) const nuclear@1: { nuclear@1: return ((EnumType == type) || (EnumType == Device_All)) && nuclear@1: (available || !AvailableOnly); nuclear@1: } nuclear@1: nuclear@1: protected: nuclear@1: DeviceType EnumType; nuclear@1: bool AvailableOnly; nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: // DeviceEnumerator<> is used to enumerate and create devices of specified class, nuclear@1: // it is returned by calling MeviceManager::EnumerateDevices. Initially, the enumerator will nuclear@1: // refer to the first device of specified type. Additional devices can be accessed by nuclear@1: // calling Next(). nuclear@1: nuclear@1: template nuclear@1: class DeviceEnumerator : public DeviceHandle nuclear@1: { nuclear@1: friend class DeviceManager; nuclear@1: friend class DeviceManagerImpl; nuclear@1: public: nuclear@1: DeviceEnumerator() nuclear@1: : DeviceHandle(), EnumArgs(Device_None, true) { } nuclear@1: nuclear@1: // Next advances enumeration to the next device that first criteria. nuclear@1: // Returns false if no more devices exist that match enumeration criteria. nuclear@1: bool Next() { return enumerateNext(EnumArgs); } nuclear@1: nuclear@1: // Creates an instance of the device referenced by enumerator; returns null nuclear@1: // if enumerator does not refer to a valid device or device is unavailable. nuclear@1: // If device was already created, the same object with incremented ref-count is returned. nuclear@1: T* CreateDevice() { return static_cast(DeviceHandle::CreateDevice()); } nuclear@1: nuclear@1: protected: nuclear@1: DeviceEnumerator(const DeviceHandle &dev, const DeviceEnumerationArgs& args) nuclear@1: : DeviceHandle(dev), EnumArgs(args) nuclear@1: { } nuclear@1: nuclear@1: DeviceEnumerationArgs EnumArgs; nuclear@1: }; nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** DeviceManager nuclear@1: nuclear@1: // DeviceManager maintains and provides access to devices supported by OVR, such as nuclear@1: // HMDs and sensors. A single instance of DeviceManager is normally created at nuclear@1: // program startup, allowing devices to be enumerated and created. DeviceManager is nuclear@1: // reference counted and is AddRefed by its created child devices, causing it to nuclear@1: // always be the last object that is released. nuclear@1: // nuclear@1: // Install MessageHandler on DeviceManager to detect when devices are inserted or removed. nuclear@1: // nuclear@1: // The following code will create the manager and its first available HMDDevice, nuclear@1: // and then release it when not needed: nuclear@1: // nuclear@1: // DeviceManager* manager = DeviceManager::Create(); nuclear@1: // HMDDevice* hmd = manager->EnumerateDevices().CreateDevice(); nuclear@1: // nuclear@1: // if (hmd) hmd->Release(); nuclear@1: // if (manager) manager->Release(); nuclear@1: nuclear@1: nuclear@1: class DeviceManager : public DeviceBase nuclear@1: { nuclear@1: public: nuclear@1: nuclear@1: DeviceManager() nuclear@1: { } nuclear@1: nuclear@1: // DeviceBase implementation. nuclear@1: virtual DeviceType GetType() const { return Device_Manager; } nuclear@1: virtual DeviceManager* GetManager() const { return const_cast(this); } nuclear@1: nuclear@1: // Every DeviceManager has an associated profile manager, which us used to store nuclear@1: // user settings that may affect device behavior. nuclear@1: virtual ProfileManager* GetProfileManager() const = 0; nuclear@1: nuclear@1: nuclear@1: // EnumerateDevices enumerates all of the available devices of the specified class, nuclear@1: // returning an enumerator that references the first device. An empty enumerator is nuclear@1: // returned if no devices are available. The following APIs are exposed through nuclear@1: // DeviceEnumerator: nuclear@1: // DeviceEnumerator::GetType() - Check device type. Returns Device_None nuclear@1: // if no device was found/pointed to. nuclear@1: // DeviceEnumerator::GetDeviceInfo() - Get more information on device. nuclear@1: // DeviceEnumerator::CreateDevice() - Create an instance of device. nuclear@1: // DeviceEnumerator::Next() - Move onto next device. nuclear@1: template nuclear@1: DeviceEnumerator EnumerateDevices(bool availableOnly = true) nuclear@1: { nuclear@1: // TBD: A cleaner (but less efficient) alternative is though enumeratorFromHandle. nuclear@1: DeviceEnumerator<> e = EnumerateDevicesEx(DeviceEnumerationArgs((DeviceType)D::EnumDeviceType, availableOnly)); nuclear@1: return *reinterpret_cast*>(&e); nuclear@1: } nuclear@1: nuclear@1: // EnumerateDevicesEx provides internal implementation for device enumeration, enumerating nuclear@1: // devices based on dynamically specified DeviceType in DeviceEnumerationArgs. nuclear@1: // End users should call DeumerateDevices<>() instead. nuclear@1: virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args) = 0; nuclear@1: nuclear@1: // Creates a new DeviceManager. Only one instance of DeviceManager should be created at a time. nuclear@1: static DeviceManager* Create(); nuclear@1: nuclear@1: // Static constant for this device type, used in template cast type checks. nuclear@1: enum { EnumDeviceType = Device_Manager }; nuclear@1: nuclear@1: nuclear@1: nuclear@1: // Adds a device (DeviceCreateDesc*) into Devices. Returns NULL, nuclear@1: // if unsuccessful or device is already in the list. nuclear@1: virtual Ptr AddDevice_NeedsLock(const DeviceCreateDesc& createDesc) = 0; nuclear@1: nuclear@1: protected: nuclear@1: DeviceEnumerator<> enumeratorFromHandle(const DeviceHandle& h, const DeviceEnumerationArgs& args) nuclear@1: { return DeviceEnumerator<>(h, args); } nuclear@1: nuclear@1: DeviceManager* getThis() { return this; } nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** HMDInfo nuclear@1: nuclear@1: // This structure describes various aspects of the HMD allowing us to configure rendering. nuclear@1: // nuclear@1: // Currently included data: nuclear@1: // - Physical screen dimensions, resolution, and eye distances. nuclear@1: // (some of these will be configurable with a tool in the future). nuclear@1: // These arguments allow us to properly setup projection across HMDs. nuclear@1: // - DisplayDeviceName for identifying HMD screen; system-specific interpretation. nuclear@1: // nuclear@1: // TBD: nuclear@1: // - Power on/ off? nuclear@1: // - Sensor rates and capabilities nuclear@1: // - Distortion radius/variables nuclear@1: // - Screen update frequency nuclear@1: // - Distortion needed flag nuclear@1: // - Update modes: nuclear@1: // Set update mode: Stereo (both sides together), mono (same in both eyes), nuclear@1: // Alternating, Alternating scan-lines. nuclear@1: nuclear@1: class HMDInfo : public DeviceInfo nuclear@1: { nuclear@1: public: nuclear@1: // Size of the entire screen, in pixels. nuclear@1: unsigned HResolution, VResolution; nuclear@1: // Physical dimensions of the active screen in meters. Can be used to calculate nuclear@1: // projection center while considering IPD. nuclear@1: float HScreenSize, VScreenSize; nuclear@1: // Physical offset from the top of the screen to the eye center, in meters. nuclear@1: // This will usually, but not necessarily be half of VScreenSize. nuclear@1: float VScreenCenter; nuclear@1: // Distance from the eye to screen surface, in meters. nuclear@1: // Useful for calculating FOV and projection. nuclear@1: float EyeToScreenDistance; nuclear@1: // Distance between physical lens centers useful for calculating distortion center. nuclear@1: float LensSeparationDistance; nuclear@1: // Configured distance between the user's eye centers, in meters. Defaults to 0.064. nuclear@1: float InterpupillaryDistance; nuclear@1: nuclear@1: // Radial distortion correction coefficients. nuclear@1: // The distortion assumes that the input texture coordinates will be scaled nuclear@1: // by the following equation: nuclear@1: // uvResult = uvInput * (K0 + K1 * uvLength^2 + K2 * uvLength^4) nuclear@1: // Where uvInput is the UV vector from the center of distortion in direction nuclear@1: // of the mapped pixel, uvLength is the magnitude of that vector, and uvResult nuclear@1: // the corresponding location after distortion. nuclear@1: float DistortionK[4]; nuclear@1: nuclear@1: float ChromaAbCorrection[4]; nuclear@1: nuclear@1: // Desktop coordinate position of the screen (can be negative; may not be present on all platforms) nuclear@1: int DesktopX, DesktopY; nuclear@1: nuclear@1: // Windows: nuclear@1: // "\\\\.\\DISPLAY3", etc. Can be used in EnumDisplaySettings/CreateDC. nuclear@1: char DisplayDeviceName[32]; nuclear@1: nuclear@1: // MacOS: nuclear@1: long DisplayId; nuclear@1: nuclear@1: nuclear@1: HMDInfo() nuclear@1: : DeviceInfo(Device_HMD), nuclear@1: HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0), nuclear@1: VScreenCenter(0), EyeToScreenDistance(0), nuclear@1: LensSeparationDistance(0), InterpupillaryDistance(0), nuclear@1: DesktopX(0), DesktopY(0), DisplayId(0) nuclear@1: { nuclear@1: DisplayDeviceName[0] = 0; nuclear@1: memset(DistortionK, 0, sizeof(DistortionK)); nuclear@1: DistortionK[0] = 1; nuclear@1: ChromaAbCorrection[0] = ChromaAbCorrection[2] = 1; nuclear@1: ChromaAbCorrection[1] = ChromaAbCorrection[3] = 0; nuclear@1: } nuclear@1: nuclear@1: // Operator = copies local fields only (base class must be correct already) nuclear@1: void operator = (const HMDInfo& src) nuclear@1: { nuclear@1: HResolution = src.HResolution; nuclear@1: VResolution = src.VResolution; nuclear@1: HScreenSize = src.HScreenSize; nuclear@1: VScreenSize = src.VScreenSize; nuclear@1: VScreenCenter = src.VScreenCenter; nuclear@1: EyeToScreenDistance = src.EyeToScreenDistance; nuclear@1: LensSeparationDistance = src.LensSeparationDistance; nuclear@1: InterpupillaryDistance = src.InterpupillaryDistance; nuclear@1: DistortionK[0] = src.DistortionK[0]; nuclear@1: DistortionK[1] = src.DistortionK[1]; nuclear@1: DistortionK[2] = src.DistortionK[2]; nuclear@1: DistortionK[3] = src.DistortionK[3]; nuclear@1: ChromaAbCorrection[0] = src.ChromaAbCorrection[0]; nuclear@1: ChromaAbCorrection[1] = src.ChromaAbCorrection[1]; nuclear@1: ChromaAbCorrection[2] = src.ChromaAbCorrection[2]; nuclear@1: ChromaAbCorrection[3] = src.ChromaAbCorrection[3]; nuclear@1: DesktopX = src.DesktopX; nuclear@1: DesktopY = src.DesktopY; nuclear@1: memcpy(DisplayDeviceName, src.DisplayDeviceName, sizeof(DisplayDeviceName)); nuclear@1: DisplayId = src.DisplayId; nuclear@1: } nuclear@1: nuclear@1: bool IsSameDisplay(const HMDInfo& o) const nuclear@1: { nuclear@1: return DisplayId == o.DisplayId && nuclear@1: String::CompareNoCase(DisplayDeviceName, nuclear@1: o.DisplayDeviceName) == 0; nuclear@1: } nuclear@1: nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: // HMDDevice represents an Oculus HMD device unit. An instance of this class nuclear@1: // is typically created from the DeviceManager. nuclear@1: // After HMD device is created, we its sensor data can be obtained by nuclear@1: // first creating a Sensor object and then. nuclear@1: nuclear@1: // TBD: nuclear@1: // - Configure Sensor nuclear@1: // - APIs to set On-Screen message, other states? nuclear@1: nuclear@1: class HMDDevice : public DeviceBase nuclear@1: { nuclear@1: public: nuclear@1: HMDDevice() nuclear@1: { } nuclear@1: nuclear@1: // Static constant for this device type, used in template cast type checks. nuclear@1: enum { EnumDeviceType = Device_HMD }; nuclear@1: nuclear@1: virtual DeviceType GetType() const { return Device_HMD; } nuclear@1: nuclear@1: // Creates a sensor associated with this HMD. nuclear@1: virtual SensorDevice* GetSensor() = 0; nuclear@1: nuclear@1: nuclear@1: // Requests the currently used profile. This profile affects the nuclear@1: // settings reported by HMDInfo. nuclear@1: virtual Profile* GetProfile() const = 0; nuclear@1: // Obtains the currently used profile name. This is initialized to the default nuclear@1: // profile name, if any; it can then be changed per-device by SetProfileName. nuclear@1: virtual const char* GetProfileName() const = 0; nuclear@1: // Sets the profile user name, changing the data returned by GetProfileInfo. nuclear@1: virtual bool SetProfileName(const char* name) = 0; nuclear@1: nuclear@1: nuclear@1: // Disconnects from real HMD device. This HMDDevice remains as 'fake' HMD. nuclear@1: // SensorDevice ptr is used to restore the 'fake' HMD (can be NULL). nuclear@1: HMDDevice* Disconnect(SensorDevice*); nuclear@1: nuclear@1: // Returns 'true' if HMD device is a 'fake' HMD (was created this way or nuclear@1: // 'Disconnect' method was called). nuclear@1: bool IsDisconnected() const; nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** SensorRange & SensorInfo nuclear@1: nuclear@1: // SensorRange specifies maximum value ranges that SensorDevice hardware is configured nuclear@1: // to detect. Although this range doesn't affect the scale of MessageBodyFrame values, nuclear@1: // physical motions whose positive or negative magnitude is outside the specified range nuclear@1: // may get clamped or misreported. Setting lower values may result in higher precision nuclear@1: // tracking. nuclear@1: struct SensorRange nuclear@1: { nuclear@1: SensorRange(float maxAcceleration = 0.0f, float maxRotationRate = 0.0f, nuclear@1: float maxMagneticField = 0.0f) nuclear@1: : MaxAcceleration(maxAcceleration), MaxRotationRate(maxRotationRate), nuclear@1: MaxMagneticField(maxMagneticField) nuclear@1: { } nuclear@1: nuclear@1: // Maximum detected acceleration in m/s^2. Up to 8*G equivalent support guaranteed, nuclear@1: // where G is ~9.81 m/s^2. nuclear@1: // Oculus DK1 HW has thresholds near: 2, 4 (default), 8, 16 G. nuclear@1: float MaxAcceleration; nuclear@1: // Maximum detected angular velocity in rad/s. Up to 8*Pi support guaranteed. nuclear@1: // Oculus DK1 HW thresholds near: 1, 2, 4, 8 Pi (default). nuclear@1: float MaxRotationRate; nuclear@1: // Maximum detectable Magnetic field strength in Gauss. Up to 2.5 Gauss support guaranteed. nuclear@1: // Oculus DK1 HW thresholds near: 0.88, 1.3, 1.9, 2.5 gauss. nuclear@1: float MaxMagneticField; nuclear@1: }; nuclear@1: nuclear@1: // SensorInfo describes capabilities of the sensor device. nuclear@1: class SensorInfo : public DeviceInfo nuclear@1: { nuclear@1: public: nuclear@1: SensorInfo() : DeviceInfo(Device_Sensor), VendorId(0), ProductId(0) nuclear@1: { nuclear@1: SerialNumber[0] = 0; nuclear@1: } nuclear@1: nuclear@1: // HID Vendor and ProductId of the device. nuclear@1: UInt16 VendorId; nuclear@1: UInt16 ProductId; nuclear@1: // MaxRanges report maximum sensor range values supported by HW. nuclear@1: SensorRange MaxRanges; nuclear@1: // Sensor (and display) serial number. nuclear@1: char SerialNumber[20]; nuclear@1: nuclear@1: private: nuclear@1: void operator = (const SensorInfo&) { OVR_ASSERT(0); } // Assignment not allowed. nuclear@1: }; nuclear@1: nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** SensorDevice nuclear@1: nuclear@1: // SensorDevice is an interface to sensor data. nuclear@1: // Install a MessageHandler of SensorDevice instance to receive MessageBodyFrame nuclear@1: // notifications. nuclear@1: // nuclear@1: // TBD: Add Polling API? More HID interfaces? nuclear@1: nuclear@1: class SensorDevice : public HIDDeviceBase, public DeviceBase nuclear@1: { nuclear@1: public: nuclear@1: SensorDevice() nuclear@1: { } nuclear@1: nuclear@1: // Static constant for this device type, used in template cast type checks. nuclear@1: enum { EnumDeviceType = Device_Sensor }; nuclear@1: nuclear@1: virtual DeviceType GetType() const { return Device_Sensor; } nuclear@1: nuclear@1: nuclear@1: // CoordinateFrame defines whether messages come in the coordinate frame nuclear@1: // of the sensor device or HMD, which has a different internal sensor. nuclear@1: // Sensors obtained form the HMD will automatically use HMD coordinates. nuclear@1: enum CoordinateFrame nuclear@1: { nuclear@1: Coord_Sensor = 0, nuclear@1: Coord_HMD = 1 nuclear@1: }; nuclear@1: nuclear@1: virtual void SetCoordinateFrame(CoordinateFrame coordframe) = 0; nuclear@1: virtual CoordinateFrame GetCoordinateFrame() const = 0; nuclear@1: nuclear@1: // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). nuclear@1: // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be nuclear@1: // called twice or thrice at the same 'tick'. nuclear@1: // If the rate is < 333 then the OnMessage / MessageBodyFrame will be called three nuclear@1: // times for each 'tick': the first call will contain averaged values, the second nuclear@1: // and third calls will provide with most recent two recorded samples. nuclear@1: virtual void SetReportRate(unsigned rateHz) = 0; nuclear@1: // Returns currently set report rate, in Hz. If 0 - error occurred. nuclear@1: // Note, this value may be different from the one provided for SetReportRate. The return nuclear@1: // value will contain the actual rate. nuclear@1: virtual unsigned GetReportRate() const = 0; nuclear@1: nuclear@1: // Sets maximum range settings for the sensor described by SensorRange. nuclear@1: // The function will fail if you try to pass values outside Maximum supported nuclear@1: // by the HW, as described by SensorInfo. nuclear@1: // Pass waitFlag == true to wait for command completion. For waitFlag == true, nuclear@1: // returns true if the range was applied successfully (no HW error). nuclear@1: // For waitFlag = false, return 'true' means that command was enqueued successfully. nuclear@1: virtual bool SetRange(const SensorRange& range, bool waitFlag = false) = 0; nuclear@1: nuclear@1: // Return the current sensor range settings for the device. These may not exactly nuclear@1: // match the values applied through SetRange. nuclear@1: virtual void GetRange(SensorRange* range) const = 0; nuclear@1: }; nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** LatencyTestConfiguration nuclear@1: // LatencyTestConfiguration specifies configuration information for the Oculus Latency Tester device. nuclear@1: struct LatencyTestConfiguration nuclear@1: { nuclear@1: LatencyTestConfiguration(const Color& threshold, bool sendSamples = false) nuclear@1: : Threshold(threshold), SendSamples(sendSamples) nuclear@1: { nuclear@1: } nuclear@1: nuclear@1: // The color threshold for triggering a detected display change. nuclear@1: Color Threshold; nuclear@1: // Flag specifying whether we wish to receive a stream of color values from the sensor. nuclear@1: bool SendSamples; nuclear@1: }; nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** LatencyTestDisplay nuclear@1: // LatencyTestDisplay sets the mode and contents of the Latency Tester LED display. nuclear@1: // See the 'Latency Tester Specification' document for more details. nuclear@1: struct LatencyTestDisplay nuclear@1: { nuclear@1: LatencyTestDisplay(UByte mode, UInt32 value) nuclear@1: : Mode(mode), Value(value) nuclear@1: { nuclear@1: } nuclear@1: nuclear@1: UByte Mode; // The display mode that we wish to select. nuclear@1: UInt32 Value; // The value to display. nuclear@1: }; nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** LatencyTestDevice nuclear@1: nuclear@1: // LatencyTestDevice provides an interface to the Oculus Latency Tester which is used to test 'motion to photon' latency. nuclear@1: class LatencyTestDevice : public HIDDeviceBase, public DeviceBase nuclear@1: { nuclear@1: public: nuclear@1: LatencyTestDevice() nuclear@1: { } nuclear@1: nuclear@1: // Static constant for this device type, used in template cast type checks. nuclear@1: enum { EnumDeviceType = Device_LatencyTester }; nuclear@1: nuclear@1: virtual DeviceType GetType() const { return Device_LatencyTester; } nuclear@1: nuclear@1: // Specifies configuration information including the threshold for triggering a detected color change, nuclear@1: // and a flag to enable a stream of sensor values (typically used for debugging). nuclear@1: virtual bool SetConfiguration(const LatencyTestConfiguration& configuration, bool waitFlag = false) = 0; nuclear@1: nuclear@1: // Get configuration information from device. nuclear@1: virtual bool GetConfiguration(LatencyTestConfiguration* configuration) = 0; nuclear@1: nuclear@1: // Used to calibrate the latency tester at the start of a test. Display the specified color on the screen nuclear@1: // beneath the latency tester and then call this method. Calibration information is lost nuclear@1: // when power is removed from the device. nuclear@1: virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false) = 0; nuclear@1: nuclear@1: // Triggers the start of a measurement. This starts the millisecond timer on the device and nuclear@1: // causes it to respond with the 'MessageLatencyTestStarted' message. nuclear@1: virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false) = 0; nuclear@1: nuclear@1: // Used to set the value displayed on the LED display panel. nuclear@1: virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false) = 0; nuclear@1: nuclear@1: virtual DeviceBase* GetDevice() { return this; } nuclear@1: }; nuclear@1: nuclear@1: } // namespace OVR nuclear@1: nuclear@1: #endif