oculus1

view libovr/Src/OVR_Device.h @ 23:0c76f70fb7e9

merged
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 28 Sep 2013 04:13:33 +0300
parents
children
line source
1 /************************************************************************************
3 PublicHeader: OVR.h
4 Filename : OVR_Device.h
5 Content : Definition of HMD-related Device interfaces
6 Created : September 21, 2012
7 Authors : Michael Antonov
9 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
11 Use of this software is subject to the terms of the Oculus license
12 agreement provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
15 *************************************************************************************/
17 #ifndef OVR_Device_h
18 #define OVR_Device_h
20 #include "OVR_DeviceConstants.h"
21 #include "OVR_DeviceHandle.h"
22 #include "OVR_DeviceMessages.h"
23 #include "OVR_HIDDeviceBase.h"
25 #include "Kernel/OVR_Atomic.h"
26 #include "Kernel/OVR_RefCount.h"
27 #include "Kernel/OVR_String.h"
29 namespace OVR {
31 // Declared externally
32 class Profile;
33 class ProfileManager; // << Should be renamed for consistency
35 // Forward declarations
36 class SensorDevice;
37 class DeviceCommon;
38 class DeviceManager;
40 // MessageHandler is a base class from which users derive to receive messages,
41 // its OnMessage handler will be called for messages once it is installed on
42 // a device. Same message handler can be installed on multiple devices.
43 class MessageHandler
44 {
45 friend class MessageHandlerImpl;
46 public:
47 MessageHandler();
48 virtual ~MessageHandler();
50 // Returns 'true' if handler is currently installed on any devices.
51 bool IsHandlerInstalled() const;
53 // Should be called from derived class destructor to avoid handler
54 // being called after it exits.
55 void RemoveHandlerFromDevices();
57 // Returns a pointer to the internal lock object that is locked by a
58 // background thread while OnMessage() is called.
59 // This lock guaranteed to survive until ~MessageHandler.
60 Lock* GetHandlerLock() const;
63 virtual void OnMessage(const Message&) { }
65 // Determines if handler supports a specific message type. Can
66 // be used to filter out entire message groups. The result
67 // returned by this function shouldn't change after handler creation.
68 virtual bool SupportsMessageType(MessageType) const { return true; }
70 private:
71 UPInt Internal[4];
72 };
75 //-------------------------------------------------------------------------------------
76 // ***** DeviceBase
78 // DeviceBase is the base class for all OVR Devices. It provides the following basic
79 // functionality:
80 // - Reports device type, manager, and associated parent (if any).
81 // - Supports installable message handlers, which are notified of device events.
82 // - Device objects are created through DeviceHandle::CreateDevice or more commonly
83 // through DeviceEnumerator<>::CreateDevice.
84 // - Created devices are reference counted, starting with RefCount of 1.
85 // - Device is resources are cleaned up when it is Released, although its handles
86 // may survive longer if referenced.
88 class DeviceBase : public NewOverrideBase
89 {
90 friend class DeviceHandle;
91 friend class DeviceManagerImpl;
92 public:
94 // Enumerating DeviceBase enumerates all devices.
95 enum { EnumDeviceType = Device_All };
97 virtual ~DeviceBase() { }
98 virtual void AddRef();
99 virtual void Release();
101 virtual DeviceBase* GetParent() const;
102 virtual DeviceManager* GetManager() const;
104 virtual void SetMessageHandler(MessageHandler* handler);
105 virtual MessageHandler* GetMessageHandler() const;
107 virtual DeviceType GetType() const;
108 virtual bool GetDeviceInfo(DeviceInfo* info) const;
110 // returns the MessageHandler's lock
111 Lock* GetHandlerLock() const;
112 protected:
113 // Internal
114 virtual DeviceCommon* getDeviceCommon() const = 0;
115 };
118 //-------------------------------------------------------------------------------------
119 // ***** DeviceInfo
121 // DeviceInfo describes a device and its capabilities, obtained by calling
122 // GetDeviceInfo. This base class only contains device-independent functionality;
123 // users will normally use a derived HMDInfo or SensorInfo classes for more
124 // extensive device info.
126 class DeviceInfo
127 {
128 public:
129 DeviceInfo() : InfoClassType(Device_None), Type(Device_None), Version(0)
130 { ProductName[0] = Manufacturer[0] = 0; }
132 enum { MaxNameLength = 32 };
134 // Type of device for which DeviceInfo is intended.
135 // This will be set to Device_HMD for HMDInfo structure, note that this may be
136 // different form the actual device type since (Device_None) is valid.
137 const DeviceType InfoClassType;
138 // Type of device this describes. This must be the same as InfoClassType when
139 // InfoClassType != Device_None.
140 DeviceType Type;
141 // Name string describing the product: "Oculus Rift DK1", etc.
142 char ProductName[MaxNameLength];
143 char Manufacturer[MaxNameLength];
144 unsigned Version;
146 protected:
147 DeviceInfo(DeviceType type) : InfoClassType(type), Type(type), Version(0)
148 { ProductName[0] = Manufacturer[0] = 0; }
149 void operator = (const DeviceInfo&) { OVR_ASSERT(0); } // Assignment not allowed.
150 };
153 //-------------------------------------------------------------------------------------
154 // DeviceEnumerationArgs provides device enumeration argumenrs for DeviceManager::EnumerateDevicesEx.
155 class DeviceEnumerationArgs
156 {
157 public:
158 DeviceEnumerationArgs(DeviceType enumType, bool availableOnly)
159 : EnumType(enumType), AvailableOnly(availableOnly)
160 { }
162 // Helper; returns true if args match our enumeration criteria.
163 bool MatchRule(DeviceType type, bool available) const
164 {
165 return ((EnumType == type) || (EnumType == Device_All)) &&
166 (available || !AvailableOnly);
167 }
169 protected:
170 DeviceType EnumType;
171 bool AvailableOnly;
172 };
175 // DeviceEnumerator<> is used to enumerate and create devices of specified class,
176 // it is returned by calling MeviceManager::EnumerateDevices. Initially, the enumerator will
177 // refer to the first device of specified type. Additional devices can be accessed by
178 // calling Next().
180 template<class T = DeviceBase>
181 class DeviceEnumerator : public DeviceHandle
182 {
183 friend class DeviceManager;
184 friend class DeviceManagerImpl;
185 public:
186 DeviceEnumerator()
187 : DeviceHandle(), EnumArgs(Device_None, true) { }
189 // Next advances enumeration to the next device that first criteria.
190 // Returns false if no more devices exist that match enumeration criteria.
191 bool Next() { return enumerateNext(EnumArgs); }
193 // Creates an instance of the device referenced by enumerator; returns null
194 // if enumerator does not refer to a valid device or device is unavailable.
195 // If device was already created, the same object with incremented ref-count is returned.
196 T* CreateDevice() { return static_cast<T*>(DeviceHandle::CreateDevice()); }
198 protected:
199 DeviceEnumerator(const DeviceHandle &dev, const DeviceEnumerationArgs& args)
200 : DeviceHandle(dev), EnumArgs(args)
201 { }
203 DeviceEnumerationArgs EnumArgs;
204 };
206 //-------------------------------------------------------------------------------------
207 // ***** DeviceManager
209 // DeviceManager maintains and provides access to devices supported by OVR, such as
210 // HMDs and sensors. A single instance of DeviceManager is normally created at
211 // program startup, allowing devices to be enumerated and created. DeviceManager is
212 // reference counted and is AddRefed by its created child devices, causing it to
213 // always be the last object that is released.
214 //
215 // Install MessageHandler on DeviceManager to detect when devices are inserted or removed.
216 //
217 // The following code will create the manager and its first available HMDDevice,
218 // and then release it when not needed:
219 //
220 // DeviceManager* manager = DeviceManager::Create();
221 // HMDDevice* hmd = manager->EnumerateDevices<HMDDevice>().CreateDevice();
222 //
223 // if (hmd) hmd->Release();
224 // if (manager) manager->Release();
227 class DeviceManager : public DeviceBase
228 {
229 public:
231 DeviceManager()
232 { }
234 // DeviceBase implementation.
235 virtual DeviceType GetType() const { return Device_Manager; }
236 virtual DeviceManager* GetManager() const { return const_cast<DeviceManager*>(this); }
238 // Every DeviceManager has an associated profile manager, which us used to store
239 // user settings that may affect device behavior.
240 virtual ProfileManager* GetProfileManager() const = 0;
243 // EnumerateDevices enumerates all of the available devices of the specified class,
244 // returning an enumerator that references the first device. An empty enumerator is
245 // returned if no devices are available. The following APIs are exposed through
246 // DeviceEnumerator:
247 // DeviceEnumerator::GetType() - Check device type. Returns Device_None
248 // if no device was found/pointed to.
249 // DeviceEnumerator::GetDeviceInfo() - Get more information on device.
250 // DeviceEnumerator::CreateDevice() - Create an instance of device.
251 // DeviceEnumerator::Next() - Move onto next device.
252 template<class D>
253 DeviceEnumerator<D> EnumerateDevices(bool availableOnly = true)
254 {
255 // TBD: A cleaner (but less efficient) alternative is though enumeratorFromHandle.
256 DeviceEnumerator<> e = EnumerateDevicesEx(DeviceEnumerationArgs((DeviceType)D::EnumDeviceType, availableOnly));
257 return *reinterpret_cast<DeviceEnumerator<D>*>(&e);
258 }
260 // EnumerateDevicesEx provides internal implementation for device enumeration, enumerating
261 // devices based on dynamically specified DeviceType in DeviceEnumerationArgs.
262 // End users should call DeumerateDevices<>() instead.
263 virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args) = 0;
265 // Creates a new DeviceManager. Only one instance of DeviceManager should be created at a time.
266 static DeviceManager* Create();
268 // Static constant for this device type, used in template cast type checks.
269 enum { EnumDeviceType = Device_Manager };
273 // Adds a device (DeviceCreateDesc*) into Devices. Returns NULL,
274 // if unsuccessful or device is already in the list.
275 virtual Ptr<DeviceCreateDesc> AddDevice_NeedsLock(const DeviceCreateDesc& createDesc) = 0;
277 protected:
278 DeviceEnumerator<> enumeratorFromHandle(const DeviceHandle& h, const DeviceEnumerationArgs& args)
279 { return DeviceEnumerator<>(h, args); }
281 DeviceManager* getThis() { return this; }
282 };
286 //-------------------------------------------------------------------------------------
287 // ***** HMDInfo
289 // This structure describes various aspects of the HMD allowing us to configure rendering.
290 //
291 // Currently included data:
292 // - Physical screen dimensions, resolution, and eye distances.
293 // (some of these will be configurable with a tool in the future).
294 // These arguments allow us to properly setup projection across HMDs.
295 // - DisplayDeviceName for identifying HMD screen; system-specific interpretation.
296 //
297 // TBD:
298 // - Power on/ off?
299 // - Sensor rates and capabilities
300 // - Distortion radius/variables
301 // - Screen update frequency
302 // - Distortion needed flag
303 // - Update modes:
304 // Set update mode: Stereo (both sides together), mono (same in both eyes),
305 // Alternating, Alternating scan-lines.
307 class HMDInfo : public DeviceInfo
308 {
309 public:
310 // Size of the entire screen, in pixels.
311 unsigned HResolution, VResolution;
312 // Physical dimensions of the active screen in meters. Can be used to calculate
313 // projection center while considering IPD.
314 float HScreenSize, VScreenSize;
315 // Physical offset from the top of the screen to the eye center, in meters.
316 // This will usually, but not necessarily be half of VScreenSize.
317 float VScreenCenter;
318 // Distance from the eye to screen surface, in meters.
319 // Useful for calculating FOV and projection.
320 float EyeToScreenDistance;
321 // Distance between physical lens centers useful for calculating distortion center.
322 float LensSeparationDistance;
323 // Configured distance between the user's eye centers, in meters. Defaults to 0.064.
324 float InterpupillaryDistance;
326 // Radial distortion correction coefficients.
327 // The distortion assumes that the input texture coordinates will be scaled
328 // by the following equation:
329 // uvResult = uvInput * (K0 + K1 * uvLength^2 + K2 * uvLength^4)
330 // Where uvInput is the UV vector from the center of distortion in direction
331 // of the mapped pixel, uvLength is the magnitude of that vector, and uvResult
332 // the corresponding location after distortion.
333 float DistortionK[4];
335 float ChromaAbCorrection[4];
337 // Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
338 int DesktopX, DesktopY;
340 // Windows:
341 // "\\\\.\\DISPLAY3", etc. Can be used in EnumDisplaySettings/CreateDC.
342 char DisplayDeviceName[32];
344 // MacOS:
345 long DisplayId;
348 HMDInfo()
349 : DeviceInfo(Device_HMD),
350 HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0),
351 VScreenCenter(0), EyeToScreenDistance(0),
352 LensSeparationDistance(0), InterpupillaryDistance(0),
353 DesktopX(0), DesktopY(0), DisplayId(0)
354 {
355 DisplayDeviceName[0] = 0;
356 memset(DistortionK, 0, sizeof(DistortionK));
357 DistortionK[0] = 1;
358 ChromaAbCorrection[0] = ChromaAbCorrection[2] = 1;
359 ChromaAbCorrection[1] = ChromaAbCorrection[3] = 0;
360 }
362 // Operator = copies local fields only (base class must be correct already)
363 void operator = (const HMDInfo& src)
364 {
365 HResolution = src.HResolution;
366 VResolution = src.VResolution;
367 HScreenSize = src.HScreenSize;
368 VScreenSize = src.VScreenSize;
369 VScreenCenter = src.VScreenCenter;
370 EyeToScreenDistance = src.EyeToScreenDistance;
371 LensSeparationDistance = src.LensSeparationDistance;
372 InterpupillaryDistance = src.InterpupillaryDistance;
373 DistortionK[0] = src.DistortionK[0];
374 DistortionK[1] = src.DistortionK[1];
375 DistortionK[2] = src.DistortionK[2];
376 DistortionK[3] = src.DistortionK[3];
377 ChromaAbCorrection[0] = src.ChromaAbCorrection[0];
378 ChromaAbCorrection[1] = src.ChromaAbCorrection[1];
379 ChromaAbCorrection[2] = src.ChromaAbCorrection[2];
380 ChromaAbCorrection[3] = src.ChromaAbCorrection[3];
381 DesktopX = src.DesktopX;
382 DesktopY = src.DesktopY;
383 memcpy(DisplayDeviceName, src.DisplayDeviceName, sizeof(DisplayDeviceName));
384 DisplayId = src.DisplayId;
385 }
387 bool IsSameDisplay(const HMDInfo& o) const
388 {
389 return DisplayId == o.DisplayId &&
390 String::CompareNoCase(DisplayDeviceName,
391 o.DisplayDeviceName) == 0;
392 }
394 };
397 // HMDDevice represents an Oculus HMD device unit. An instance of this class
398 // is typically created from the DeviceManager.
399 // After HMD device is created, we its sensor data can be obtained by
400 // first creating a Sensor object and then.
402 // TBD:
403 // - Configure Sensor
404 // - APIs to set On-Screen message, other states?
406 class HMDDevice : public DeviceBase
407 {
408 public:
409 HMDDevice()
410 { }
412 // Static constant for this device type, used in template cast type checks.
413 enum { EnumDeviceType = Device_HMD };
415 virtual DeviceType GetType() const { return Device_HMD; }
417 // Creates a sensor associated with this HMD.
418 virtual SensorDevice* GetSensor() = 0;
421 // Requests the currently used profile. This profile affects the
422 // settings reported by HMDInfo.
423 virtual Profile* GetProfile() const = 0;
424 // Obtains the currently used profile name. This is initialized to the default
425 // profile name, if any; it can then be changed per-device by SetProfileName.
426 virtual const char* GetProfileName() const = 0;
427 // Sets the profile user name, changing the data returned by GetProfileInfo.
428 virtual bool SetProfileName(const char* name) = 0;
431 // Disconnects from real HMD device. This HMDDevice remains as 'fake' HMD.
432 // SensorDevice ptr is used to restore the 'fake' HMD (can be NULL).
433 HMDDevice* Disconnect(SensorDevice*);
435 // Returns 'true' if HMD device is a 'fake' HMD (was created this way or
436 // 'Disconnect' method was called).
437 bool IsDisconnected() const;
438 };
441 //-------------------------------------------------------------------------------------
442 // ***** SensorRange & SensorInfo
444 // SensorRange specifies maximum value ranges that SensorDevice hardware is configured
445 // to detect. Although this range doesn't affect the scale of MessageBodyFrame values,
446 // physical motions whose positive or negative magnitude is outside the specified range
447 // may get clamped or misreported. Setting lower values may result in higher precision
448 // tracking.
449 struct SensorRange
450 {
451 SensorRange(float maxAcceleration = 0.0f, float maxRotationRate = 0.0f,
452 float maxMagneticField = 0.0f)
453 : MaxAcceleration(maxAcceleration), MaxRotationRate(maxRotationRate),
454 MaxMagneticField(maxMagneticField)
455 { }
457 // Maximum detected acceleration in m/s^2. Up to 8*G equivalent support guaranteed,
458 // where G is ~9.81 m/s^2.
459 // Oculus DK1 HW has thresholds near: 2, 4 (default), 8, 16 G.
460 float MaxAcceleration;
461 // Maximum detected angular velocity in rad/s. Up to 8*Pi support guaranteed.
462 // Oculus DK1 HW thresholds near: 1, 2, 4, 8 Pi (default).
463 float MaxRotationRate;
464 // Maximum detectable Magnetic field strength in Gauss. Up to 2.5 Gauss support guaranteed.
465 // Oculus DK1 HW thresholds near: 0.88, 1.3, 1.9, 2.5 gauss.
466 float MaxMagneticField;
467 };
469 // SensorInfo describes capabilities of the sensor device.
470 class SensorInfo : public DeviceInfo
471 {
472 public:
473 SensorInfo() : DeviceInfo(Device_Sensor), VendorId(0), ProductId(0)
474 {
475 SerialNumber[0] = 0;
476 }
478 // HID Vendor and ProductId of the device.
479 UInt16 VendorId;
480 UInt16 ProductId;
481 // MaxRanges report maximum sensor range values supported by HW.
482 SensorRange MaxRanges;
483 // Sensor (and display) serial number.
484 char SerialNumber[20];
486 private:
487 void operator = (const SensorInfo&) { OVR_ASSERT(0); } // Assignment not allowed.
488 };
491 //-------------------------------------------------------------------------------------
492 // ***** SensorDevice
494 // SensorDevice is an interface to sensor data.
495 // Install a MessageHandler of SensorDevice instance to receive MessageBodyFrame
496 // notifications.
497 //
498 // TBD: Add Polling API? More HID interfaces?
500 class SensorDevice : public HIDDeviceBase, public DeviceBase
501 {
502 public:
503 SensorDevice()
504 { }
506 // Static constant for this device type, used in template cast type checks.
507 enum { EnumDeviceType = Device_Sensor };
509 virtual DeviceType GetType() const { return Device_Sensor; }
512 // CoordinateFrame defines whether messages come in the coordinate frame
513 // of the sensor device or HMD, which has a different internal sensor.
514 // Sensors obtained form the HMD will automatically use HMD coordinates.
515 enum CoordinateFrame
516 {
517 Coord_Sensor = 0,
518 Coord_HMD = 1
519 };
521 virtual void SetCoordinateFrame(CoordinateFrame coordframe) = 0;
522 virtual CoordinateFrame GetCoordinateFrame() const = 0;
524 // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call).
525 // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be
526 // called twice or thrice at the same 'tick'.
527 // If the rate is < 333 then the OnMessage / MessageBodyFrame will be called three
528 // times for each 'tick': the first call will contain averaged values, the second
529 // and third calls will provide with most recent two recorded samples.
530 virtual void SetReportRate(unsigned rateHz) = 0;
531 // Returns currently set report rate, in Hz. If 0 - error occurred.
532 // Note, this value may be different from the one provided for SetReportRate. The return
533 // value will contain the actual rate.
534 virtual unsigned GetReportRate() const = 0;
536 // Sets maximum range settings for the sensor described by SensorRange.
537 // The function will fail if you try to pass values outside Maximum supported
538 // by the HW, as described by SensorInfo.
539 // Pass waitFlag == true to wait for command completion. For waitFlag == true,
540 // returns true if the range was applied successfully (no HW error).
541 // For waitFlag = false, return 'true' means that command was enqueued successfully.
542 virtual bool SetRange(const SensorRange& range, bool waitFlag = false) = 0;
544 // Return the current sensor range settings for the device. These may not exactly
545 // match the values applied through SetRange.
546 virtual void GetRange(SensorRange* range) const = 0;
547 };
549 //-------------------------------------------------------------------------------------
550 // ***** LatencyTestConfiguration
551 // LatencyTestConfiguration specifies configuration information for the Oculus Latency Tester device.
552 struct LatencyTestConfiguration
553 {
554 LatencyTestConfiguration(const Color& threshold, bool sendSamples = false)
555 : Threshold(threshold), SendSamples(sendSamples)
556 {
557 }
559 // The color threshold for triggering a detected display change.
560 Color Threshold;
561 // Flag specifying whether we wish to receive a stream of color values from the sensor.
562 bool SendSamples;
563 };
565 //-------------------------------------------------------------------------------------
566 // ***** LatencyTestDisplay
567 // LatencyTestDisplay sets the mode and contents of the Latency Tester LED display.
568 // See the 'Latency Tester Specification' document for more details.
569 struct LatencyTestDisplay
570 {
571 LatencyTestDisplay(UByte mode, UInt32 value)
572 : Mode(mode), Value(value)
573 {
574 }
576 UByte Mode; // The display mode that we wish to select.
577 UInt32 Value; // The value to display.
578 };
580 //-------------------------------------------------------------------------------------
581 // ***** LatencyTestDevice
583 // LatencyTestDevice provides an interface to the Oculus Latency Tester which is used to test 'motion to photon' latency.
584 class LatencyTestDevice : public HIDDeviceBase, public DeviceBase
585 {
586 public:
587 LatencyTestDevice()
588 { }
590 // Static constant for this device type, used in template cast type checks.
591 enum { EnumDeviceType = Device_LatencyTester };
593 virtual DeviceType GetType() const { return Device_LatencyTester; }
595 // Specifies configuration information including the threshold for triggering a detected color change,
596 // and a flag to enable a stream of sensor values (typically used for debugging).
597 virtual bool SetConfiguration(const LatencyTestConfiguration& configuration, bool waitFlag = false) = 0;
599 // Get configuration information from device.
600 virtual bool GetConfiguration(LatencyTestConfiguration* configuration) = 0;
602 // Used to calibrate the latency tester at the start of a test. Display the specified color on the screen
603 // beneath the latency tester and then call this method. Calibration information is lost
604 // when power is removed from the device.
605 virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false) = 0;
607 // Triggers the start of a measurement. This starts the millisecond timer on the device and
608 // causes it to respond with the 'MessageLatencyTestStarted' message.
609 virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false) = 0;
611 // Used to set the value displayed on the LED display panel.
612 virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false) = 0;
614 virtual DeviceBase* GetDevice() { return this; }
615 };
617 } // namespace OVR
619 #endif